Advertisement

Hi, Im Dave and I'm an Generic-aholic.

Started by April 29, 2016 09:58 AM
11 comments, last by frob 8 years, 5 months ago

Welcome,

I think I need help. When ever I code a feature/system/helper/tool/whatever for a game, it has to be generic. I feel like I am addicted to making things as generic as possible, even when such systems don't need to be generic. Sure having generic systems can be great, but when ever I have to create a specific system, I still can get out of the mind set of 'how can this thing be more generic', and frankly things take longer than the should because of this.

So let me tell you where it all began. My first project in the industry was made using an inhouse engine with no editor. We tried to make thing as generic as possible so they would 'just work'. no faffing about. We used other editors, such as Tiled or someother software, to create data assets which would be loaded in to game, and 'just work'.

I was in charge of implementing enemies, particles, projectiles and such (which all came from one art package). Looking back on the project I love how it all 'just worked', The artist would create a character, I would go in *do some magic* export. Run the game, and that character (with simple AI) would be working as in tended. The whole thing was so independent of code you could have a character fire a gun, when the bullet exploded it could spawn a character, which then would explode spawn particles, damage surrounding,x ,y z - no code required.

It was great.

However, now I am working with unity, that has an editor. Things don't need to be as automatic as the previous project. its perfectly acceptable and easy to enter values. Because its easy to attach components to game objects, specific components are often a way to go. The existing code base when I joined the project was alien to be, because often it was very specific. Even now when I have to create a new system / re-write an old one, I write it generically. But it is Bottle necked by specific systems, and im left with a choice, make my system less generic or Change another system (which would spiral out of control!).

I think I need to learn how to know when to drop the Generic implementation of a system in favour for a more Specific implementation.

Any advice?

TL;DR: I always try and create generic systems in game, as a result things take longer than if it was a Specific implementation. How do you decide if something should be generic or specific.

Mobile Developer at PawPrint Games ltd.

(Not "mobile" as in I move around a lot, but as in phones, mobile phone developer)

(Although I am mobile. no, not as in a babies mobile, I move from place to place)

(Not "place" as in fish, but location.)

TL;DR: I always try and create generic systems in game, as a result things take longer than if it was a Specific implementation. How do you decide if something should be generic or specific.

There's an old saying that you should "write a solution from scratch once, copy/paste it the second time, and refactor it to be generic the third time". While not hard-and-fast rule, I do find it a useful guideline.

Make yourself always write the specific implementation the first time. When you realise you need the same functionality in another location, it's pretty likely that you now have a better idea of the problem constraints than if you'd have tried to make it generic right off the bat.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Advertisement

i am the opposite. when it comes to the technical parts (rendering, etc) i always try using generic solutions.

but if it is comes to the game itself, or the specific software i doing, i always use the most shortest, uglyest, hardcoded inflexible solutions, becouse that is ~10x faster to do, and becouse i rarely will create the same app again, so i will not need to recycle the code once again, it not worths wasting generic implementations.

TL;DR: I always try and create generic systems in game, as a result things take longer than if it was a Specific implementation. How do you decide if something should be generic or specific.

There's an old saying that you should "write a solution from scratch once, copy/paste it the second time, and refactor it to be generic the third time". While not hard-and-fast rule, I do find it a useful guideline.

Make yourself always write the specific implementation the first time. When you realise you need the same functionality in another location, it's pretty likely that you now have a better idea of the problem constraints than if you'd have tried to make it generic right off the bat.

I think the other half of the issue is the mentality of trying to code something to cater for all possible future use-cases which is impossible. If you know of a future use-case then it just becomes a current use-case but one can waste alot of time trying to allow for them.

I think the other half of the issue is the mentality of trying to code something to cater for all possible future use-cases which is impossible. If you know of a future use-case then it just becomes a current use-case but one can waste alot of time trying to allow for them.

Yeah you see this a lot -- people try to make something so generic that it becomes super bloated and "frameworky". "Enterprise software" has become a pejorative term for these kinds of bloated, factory-laden, onion-esque interface-layered designs :lol:
Good "generic" components should be as simple as possible, following SOLID rules and being reusable through composition into any different framework. i.e. they should do as little as possible. A generic solution often means making many small reusable parts that can be assembled in infinite ways, rather than a big configurable system that can be configured in specific ways.

I've found that if I actually just focus on your current requirements instead of fretting over future use-cases (as warned in Dave's other post, above), I actually end up writing simpler, smaller, more SOLID components than I do when trying to write "future proof" crap. So, you can have your cake and eat it too :wink:

There's an old saying that you should "write a solution from scratch once, copy/paste it the second time, and refactor it to be generic the third time". While not hard-and-fast rule, I do find it a useful guideline..

I had this same idea taught to me as, "do something twice, then solve it the generic way". I find it generally more useful than a strict interpretation of DRY where you'd try and build the generic system sooner, with less use cases known to you.

Yeah, the 2 times then refactor on the third has been my general rule as well.

Advertisement
Hey why did you become addicted to making your code more generic? Generic code takes more time and isn't rewarding, considering it's frame work rather than GFX. Maybe some psychological preference of feeling smart over doing good, or keeping code clean as well as the kitchen sink clean rather than food in it =P

Well I'm quite addicted to generic code too, but I don't like that in the end.

Anyway I like what Geri and Hodgman said.

Aside from having a clear scope, well defined rules of what you want to do / how to behave, and a working prototype, something that helps fight the "genericness" urge is to use assert.

What if somebody wants to use foo( ptrEnemy ) with a null pointer because it isn't initialized or an enemy couldn't be found?


assert( !ptrEnemy && "Enemy can't be null" );

What if the user wants to load the materials first then textures (and not viceversa)?


void loadMaterials()
{
    assert( texturesLoaded && "Textures must be loaded at this stage when loading materials" );
}

Artificially restricting the number of ways users can interact with your API prevents you from getting stuck in coding "all possible case scenarios". Make your users adapt to a few ways of interactions rather than allowing them to do whatever they want in the order they want.

If you think you're doing your users a favour by giving this kind of flexibility, you're not. Users want to be told when they're doing something wrong (hence the asserts) and users want to go online and find an answer in stack overflow on how to use your library and move on.

Having a few combination of valid usage scenarios googles far better when all search hits agree on what to do ("ok this is definitely the right way of using the library then") than having a lots of Google results where everyone tells completely different story on how to initialize and use your library (and obviously some ways will be buggier than others).

Of course that some flexibility is good, but too much is counterproductive for everyone involved. Artificially limit them and place asserts when non intended ways are detected.

Later on if that limitation needs to be lifted, you can do so.

Edit: In the context of GUI tools where the user isn't a programmer, replace "assert" with some form of UI feedback (like flashing red in a bottom status bar, with an explanation of what they're doing wrong. Word it expressively so it can be easily searchable online. Having numbered error codes can also help)

Yeah, I find it better to work with a restricted set of access, and if absolutely necessary expand. Less ways in and out makes the feature more robust. Basically, working from an API standpoint.

And if indeed the scope needs a refactor to accommodate new features, refactor.

Writing 'generic' code from the get go only serves to muddy the water, bloats the code and interface, and often tries to solve problems that don't even exist, or encourage feature creep.

I have the same problem, it can be really hard to keep your feature set focused, but so far, it's been the better strategy. Don't over-think it, just do it.

I still sometimes write way too much code that don't solve any immediate problems. And it's not 'pretty'. Good code is succinct, and easy to read, with well defined boundaries and scope.

Aside from having a clear scope, well defined rules of what you want to do / how to behave, and a working prototype, something that helps fight the "genericness" urge is to use assert.

Yeah I often do this as well in places where I know that I could add a new feature, but I don't need it right now (basically: YAGNI tells me not to waste my time on it)

I'll often leave some breadcrumbs for future-me or a co-worker though, on these "feature assertions":

ASSERTMSG( texturesLoaded, "Textures must be loaded at this stage when loading materials. This restriction could be relaxed with a little work if it's actually required." );

This topic is closed to new replies.

Advertisement