Problem on referencing a vector of derived class

Started by
20 comments, last by mychii 7 years, 10 months ago

I guess... be generic when you can and it promotes code re-use, and be specific if it feels like you're trying to cram something into a pattern that doesn't fit - or rethink your design.


To me, it's easy to make things generic. So easy, that I often over-abstract. I notice this in some 3rd party libraries and engines too, like there's no concrete goal. Claiming "reusable code" can be a siren song for over-engineering - I'd rather have clean but concrete code that I can easily abstract as necessary.
So I now tend to be more concrete and abstract only as I see a pressing reason to (depending on what layer of code I'm working on - utility and helper stuff tends to be more abstract, for practical reasons), because it's always easy for me to make something more abstract, and harder to make an abstract thing concrete without rewriting it from scratch.

This smells heavily of unneeded abstraction, so in my own code, I'd need to justify it to myself before adding abstractions. I'm just not convinced of the value of it.
However, you obviously don't need to justify your code to me. :)

Since it was suggested to the OP, and since he seems eager to adopt it, I still question whether it's a good thing or if it's over-engineering. He seems to want to treat them all identically, but I don't see a need (or even a valuable enough benefit that outweighs the cons of over-abstracting) to treat them all identically, and by default, I feel they shouldn't be treated identically, because they aren't actually related.
Each component type is processed by a different system and each system does different work, the only thing they have in common - as far as I can see - is the name of the design pattern we are applying. And a shared design pattern isn't enough motivation for me to use inheritance: functions are a design pattern, but we don't put unrelated functions into a map together. Typically, only functions that are genuinely interchangeable do we typically treat as interchangeable. There are exceptions, ofcourse, but by default I question it as a big-picture engineering code smell.
Flyweights are also a design pattern, but unrelated flyweights shouldn't be put in a map together without a compelling reason - though I see people often doing this in their "asset managers", and I occasionally fall in the trap of doing it myself before I realize it doesn't make sense.

I guess what I'm getting at, is that treating things in an abstract way clearly has benefits [...]

And detriments. Programming is always about tradeoffs. Things can be too concrete, and they can be too abstract. Since it's easier (at least for me) to make concrete things abstract than to make abstract things concrete, by starting concrete and getting more abstract as needed, I save myself work.
There's definitely a balance to it; especially with game engines, where the internet is a vast graveyard of people writing engines in so generic ways that not a single completed game ever gets created with them.

I find abstractions easy to write and easy to over-engineer, so after doing abstract-anything-that-can-be-abstracted style of coding, I realized I wasn't benefiting much from it, so now I tone it back and ask myself, "What abstractions actually are worth the added code complexity?". Because they seem to promise more benefits than they actually deliver, I'm extra wary about them - despite them being pleasantly easy to write and appealing to me as a programmer; I want my mind to set up warning bells when I see abstractions without significant reason. (Abstractions at lower levels of code make sense for me - helper functions and algorithms and containers and so on, but when I start getting to the glue that holds everything together, I want to hone it and have something solid that targets an actual game).

It might just come down to different engineering styles and the different lens we are viewing our respective projects through.
I do like your idea of separating the component data ownership away from the systems, and will have to give that some thought.

Thanks for discussing this! It's an enjoyable topic for me, and large-scale system engineering is an area I still have alot of room for growth in; sorry for being a tad pushy and too argumentative. :)

Advertisement

I'm not over-engineering. Actually I'm keeping it simple. I only use what I need to solve scalability issues I faced before. ECS is one example of good abstraction already for me. I started off without it on some small games. Time to time, the game gets a little bigger and the game objects become bloated with concrete variables cross-referencing to everybody, whether it's from various base classes or concrete class itself.

As it gets bigger, it gets crazier and difficult to maintain, faced by a deadline. ECS saved us, even though we may do it wrong a few times.

The abstraction doesn't come up out of nowhere. When I heard the advice about the concrete solution was seem to be the only option I can get, even if it solved my usability problem, I had to ask myself "What kind of problem will I get into later in the end?"

My mind is only filled with the fact that me and my colleague may end up working 24 hours just because things become tangled and difficult to maintain. We got a deadline to catch up, and by that we got to throw some hackish codes to make it seems fine. In the end we got into a lot of trouble when updating the game or reusing some parts of it for a new game.

My client can just email me and ask if this can be fixed/updated in X days and upload it, or ask what game I can make within X months after the last one. If we have no deadline and can publish anytime we like, we may not even think about it being difficult whatsoever.

If you worry that I'd keep abstracting things out, note that I am not making a game engine here, I'm making a game. I reuse anything from what I had before; game engine or not if anyone want to call it. Again, I don't address scalability I don't need or the ones that were not problematic before.

However, it's a broad interesting discussion about scalability that I'd rather open a new thread, since my use case on this one is already solved.

Thanks again everyone. :D

This topic is closed to new replies.

Advertisement