My biggest coding takeaway

 Posted by (Visited 11190 times)  Game talk  Tagged with: ,
Jan 052012
 

Rigid programming philosophies are the devil.

Look, I am upfront about the fact that I am not an amazing programmer. I am not even a really competent one. I hack. I didn’t go through a CS degree, I don’t actually know a lot of the lingo, etc.

On the other hand, I have in fact been credited as a programmer on published games. I have programmed in quite a lot of languages, I prototype my own stuff regularly, and my name is on several technical patents. I seem to have a knack for seeing architectural solutions to problems, and for inventing technical solutions. (I generally prefer to partner with a genius coder for the actual implementation thereof — and have been lucky enough to work with many of them!).

So take everything I am about to say with the appropriate grain of salt.

I have seen too many projects get hosed by “the right way to do things”… like say planning your entire game in UML on three hallways worth of paper on the walls, only to find the resulting code too slow to actually use (this is a true story… and I apologize to the many friends and extremely smart folks who worked on the project I am talking about!). Or insisting on the absolute perfect approach to object-oriented or domain-driven design or whatever, when two lines would get you the same result with better performance, less obfuscation, and easier maintainability.

The right way to do things the first time is the way that gets it working the fastest so you can see if your solution even makes sense.

The right way to rewrite it once that works is to make it fault-tolerant and scalable.

The wrong thing to do is build a giant system first, and try to account for every possibility. Odds are very good that you need to write a screwdriver, not a power drill that can double as a belt sander. And really, in the long run, wouldn’t you rather have a tool chest with a solid screwdriver, a decent hammer, and a good pair of pliers — rather than a power drill/sander/screwdriver than can pound nails with its handle?

This doesn’t mean that you don’t plan ahead. Sure — your first pass should include as elegant a solution as you can think of for the actual problem at hand; it just shouldn’t include solutions for problems you invented for yourself. And it doesn’t mean that you might not end up with complex systems in the end. Sure — over time, you will encounter new problems, and it will turn out the hammer you already have can handle them with minor modifications — which can turn into cruft over time if you are not careful.

But why start further down that path than you need to? A is a cool idea and a useful pattern, not a solution to every problem.

FWIW, I feel the same way about religious adherence to project-management-philosophy-of-the-day stuff too. Basically, as soon as I hear “we’re doing this this way” followed by a few buzzwords, I can’t help but heave a giant mental sigh. So hmm, perhaps the right title for this post should have been “dogma is evil.” 🙂

Lastly, never trust a programmer who says that he only knows one language. The more in love with one language someone is, the more likely they seem to be to fall into the above trap… and if you are one of said programmers — try more languages. 🙂 Each language I have learned has introduced me to a new programming concept that rewrote my mental model of programming in general. It’s OK to have favorites — I do! — but it’s always best to use the right tool for the job.

(FWIW, my favorite at any given moment is entirely based on “what lets me stage up a working prototype as fast as possible”).

  11 Responses to “My biggest coding takeaway”

  1. “what lets me stage up a working prototype as fast as possible”

    Isn’t your whole idea based on that ? Having a prototype of design (gameplay ?) asap?
    In the idea that it would be a lost of time to spend hours and hours making a system if not fun to play (so you have to start again!).

  2. I do agree with your post in many ways, but there’s a caveat:

    “I generally prefer to team up with a genius coder” and “your first pass should include as elegant a solution as you can think of for the actual problem at hand” – where do those coders come from? The ones that can think of elegant solutions for the problem at hand?

    In most cases, they are the person that in a previous life planned the “entire game in UML on three hallways worth of paper on the walls, only to find the resulting code too slow to actually use”, and then learned from their mistakes (there are some who don’t learn).

    You’re basically asking people not to do the things that make them the genius coders you want to work with.

    (I should perhaps add that in my book a genius coder is one who understands software architecture/design as well as low-level things, and can balance the two. Other people’s views often focus only on one or the other.)

  3. unwesen,

    You may be right that I am asking people not to learn from mistakes, but instead to skip forwards to knowledge… 🙂 That isn’t really my intent. I think that the learning will also come better in small bites rather than in giant ones.

    All of the times I have gotten myself in deep trouble with development, be it on design, on code, whatever, it was by trying to bite off too large and speculative a piece of work. It is harder to find the mistakes when you have something that is too large to easily pull apart. Even UML diagrams are susceptible to that.

    Learning from mistakes happens best when you can fail fast. Both dogmas and overplanning tend to get in the way of that, in my experience.

  4. Genius coder and experienced coder are not the same.

    A dual wielding team member is powerful indeed.

  5. I try to err on the side of extensible, because I can’t know what’s going to be asked of me, so I at least try to make something that can handle (just about) anything I can imagine. And once the prototype is awesome…it will never be rewritten, at least in my experience.

    So, if asked to make an attack that does 20 damage,I would not create a function to call when the mouse button is pushed that would take a target in as a parameter that then reduces its health by 20, even though that’s fast to write.

    I would make a spell system that gives each spell a bunch of effects that do different things like instant damage, buffs, and add other things like resource costs and cooldowns, because I know they’re coming.

    It takes longer, and is more painful to use, but that little 20 damage spell will turn into a requirement for a spell that does 300-400 damage, instantly, and reduces enemy speed by 30pct for 15 seconds then heals your allies for 100-150 damage in a 20 yard radius, resets all of your cooldowns, increases your might by 125 for 10 seconds, and then puts a DoT on all enemies within 10 yards of the original target doing 15 damage every 2 seconds for 20 seconds.

    It is a tradeoff, but having more powerful systems when prototyping can also make iterations faster since they might be able to be changed faster once they’re there, and seeing the possibilities might help designers to discover things faster.

  6. Most new coding “paradigms” are coding paradigms that were stylish ten years ago, resurrected and dressed up in new lingo. There is a modest army of consultants who make a very comfortable living going around to various shops and selling snake oil to management.

    I always build my tools to have more potential applications than needed for the task at hand. Sometimes I get a rush job dumped in my lap and I have to crank out an app in a half hour to process 100,000 database entries. But even then, I try to write the code with an eye towards reuse.

    Yes, I would rather have my Swiss army knife in my pocket than a pocketknife, a penknife, two screwdrivers, a pair of scissors, a toothpick, a bottle opener, a can opener, an awl and a pair of pliers. For some applications, one unit with multiple functions is more efficient than a specialized unit for each individual function.

    Context varies and you have to be adaptable, but my preference leans towards the multi-tool. If I’m forced to make just a hammer for somebody… well, I make a hammer. An elegant, ergonomic, efficient hammer. With engraving.

    And if I like how it turns out, I’ll probably roll it into the next iteration of the multi-tool 🙂

  7. Yukon Sam said: Yes, I would rather have my Swiss army knife in my pocket than a pocketknife, a penknife, two screwdrivers, a pair of scissors, a toothpick, a bottle opener, a can opener, an awl and a pair of pliers. For some applications, one unit with multiple functions is more efficient than a specialized unit for each individual function.

    You’re comparing apples to oranges. A Swiss army-knife is for small jobs, and once-in-a-great-while occasions. A hammer is for everyday construction. Anyone who has ever worked in construction (making anything, not just buildings) can tell you that the best tool for the job, is the tool for the job. It may be “clever” to have a Sanding/Auguring/Hammering/Drilling/Slicing/Cutting/Welding/Vacuming super-tool, but ultimately, it’s just easier to use a hammer to pound a nail in; it’s easier to use a light-weight drill to drill a hole, etc… We live in a world with far too many “clever” people, and not enough “smart” people.

    If you want to design a level in a game, use a level editor. If you want to design a spell system, use a pen and paper with some dice. You could waste months coding and designing a program that allows you to input all the rule-sets and runs a simulation based on rules you then have to develop afterward, or you could spend those months actually making the spell system. I love my multi-tool as much as anyone, but I still go grab a butter-knife when I’m eating supper; I still get my pliers from my tool-box when I need to fix the sink. Super-tools are for when you’re away from your tool-box, and need something done now (like when you have to unscrew a battery cover from a remote-control boat at the lake for your kids) not for serious jobs.

    Would it not be easier (and therefore faster) to just design a Hammer (fireball spell), a Screwdriver (healing spell), and a Pliers (AOE DOT spell) than to try and figure out a USEFUL way to put them all together into one clunky tool (super-spell)? Sure, the super-spell can be fired off with one button, but then what are the players for if not for pressing a bunch of buttons?

    John said: It takes longer, and is more painful to use, but that little 20 damage spell will turn into a requirement for a spell that does 300-400 damage, instantly, and reduces enemy speed by 30pct for 15 seconds then heals your allies for 100-150 damage in a 20 yard radius, resets all of your cooldowns, increases your might by 125 for 10 seconds, and then puts a DoT on all enemies within 10 yards of the original target doing 15 damage every 2 seconds for 20 seconds.

    One of the most common complaints about FF7 (though it remains one of my favorite games of all time, and I still play it) was that the player didn’t really interact with the combat process in any meaningful way other than to make a selection. Sometimes the players want to hit A B Up Down A X B to get a specific effect. In an MMO, the SKILL is in knowing when to press the right buttons and in what order to get the desired effect of what you proposed as a super-spell.

    Rather than pressing “1” to get “Super-buff-kill-spell-2000, they want

    A) Press “1” for buff
    B) Press “2” for AOE-Damage
    C) Press “3” for DOT
    D) Press “4” for fireball – lvl 4
    E) Press “5” for AOE-Heal
    F) Press “6” for Self-heal, or Target-Heal
    The problem is, they don’t know they want that. They DON’T want to know that at the start of the game. The fun is in learning that process, not just the story content or missions. This is why WoW-clones suffer. Too much of the process is the same, so there’s nothing new to learn.

    I think that modern game design is taking us back in the direction of FF7. We have “scenes” that we must “watch” and press a button at the right time, or die. This is ridiculous, and prevents immersion into the story. The players can become so focused on watching for that stupid indicator, that they miss the conversation. I have seen this happen, they end up asking someone like myself (who has played it before) what they just missed.

    Rather than making all games easier, maybe game designers should go back to the philosophy of “Not all players will be able to beat this game.” Keep it simple, but make it a challenge as well. Not every game has to have this ultra complex story.

    Mario. Simple, super-challenging, and still enjoyed by thousands of people every day.

    Build a Mario first, then work on expanding it.

  8. “A Swiss army-knife is for small jobs, and once-in-a-great-while occasions. A hammer is for everyday construction.”

    And this is where the metaphor breaks down. A well-designed software tool with multiple functions can perform each of its specialized functions just as well as a specialized tool. It can be a top-flight hammer that morphs into a top-flight screwdriver. And because the functions share common code, it can be a lot less bulky than a box full of specialized tools with a great deal of redundnat wood and metal.

    I’m not doctrinaire about it. I can and do write one-offs for a single purpose. But if I can fold something into the Everything Machine without unnecessary bloat, I’m happy to do so.

    We live in a world with far too many “clever” people, and not enough “smart” people.

    Probably true. We could no doubt have a vigorous debate about who falls into which category. I’m pretty confident about my own positioning.

  9. In my limited experience as a bad programmer and a pretty good songwriter the shape of the thing is determined by the first hard problem you have to solve. And too much GUI too fast is the path to gray goo just as too many changes makes a song hard to play, hard to remember and a digital dust collector on the hard drive. If you don’t know what you want to do, don’t until you do. Yes, I experiment. They go in a folder called “experiments” and if one of them early or late gives me an idea of ‘what to do’, they get moved to a real project folder.

    It’s ok to quit when something feels wrong. What I’m puzzling at the moment is should I stop or file something away when the music is working perfectly but the song scares me because I know it will get me killed.

  10. And this is where the metaphor breaks down. A well-designed software tool with multiple functions can perform each of its specialized functions just as well as a specialized tool. It can be a top-flight hammer that morphs into a top-flight screwdriver. And because the functions share common code, it can be a lot less bulky than a box full of specialized tools with a great deal of redundnat wood and metal.

    Not really, consider it a different way if you will. How log will it take you to find an error in the “Everything Machine”? It would be far longer than to just replace the Handle in the “Hammer” program. So, yes, it requires a bigger box to have all the different tools, but repairs/replacements, and even upgrades, are far quicker to deal with.

    The point that Raph was making was basically the same thing. Use simpler tools, and spend less time fixing/replacing/upgrading them, therefore saving man-hours. Saving man-hours saves money.

    I understand that this is a double-edged sword, you obviously still want to have a job. However, you could do more projects before you retire if you spent less time fixing broken software.

  11. […] the latest and greatest tool set. This year, after a post on Raph Koster’s Blog about his Biggest Coding Takeaway, I realized I had been completely guilty of all of his points. I was rigid about my approach to […]

Sorry, the comment form is closed at this time.