Trying Something New
by George on Jun.26, 2010, under Coding, Uncategorized
This site has been quiet for too long. That’s why I’ve got involved with the #iDevBlogADay initiative. There’s a bunch of great indie developers contributing as part of a regular roster. If you want to follow all of us just subscribe to this feed.
Any good programmer is always looking for new tools and ideas to improve the code they write and to become more productive. For myself, fifteen years after I began coding professionally, this is truer than ever.
So when Noel Llopis started dropping odd comments on Twitter about ‘no classes’, ‘plain old data structures’ and ‘no singletons’ I was intrigued. How did this work? Where did this style come from? Did it lead to simple, effective code? Was it a style that would work for me? Is it a style that will work for you?
If you haven’t already read Noel’s article from yesterday describing his current coding style, then go ahead and read it now.
Take your time, I’ll wait.
It’s definitely an unusual style, and flies in the face of ‘traditional’ wisdom. So what’s life like in a world without objects? Pretty cool, actually. I’ve been experimenting with it for the last couple of weeks, and here are a few observations that might encourage you to give this style a go.
The ‘Rules’
It’s hard to change style so dramatically, so a few rules of thumb are useful to help keep on track. This style is sufficiently different that it takes time to get your head around it. Prepare to spend some time writing (and re-writing) your first code this way.
- No classes.
- Use simple structs to store data / state information, making everything visible.
- Avoid dynamic memory allocation and pointers in general.
- Nothing is global – all data is passed as needed to functions that require it.
- Functions have a single purpose – for a given set of input data, generate an output, avoiding any side effects.
- Use TDD for everything.
TDD Becomes Much Easier
Test Driven Development (TDD) has always appealed to me, but to be honest my history with TDD is a bit like my attempts to build a model railway – plenty of well intentioned starts but no completed projects. Sooner or later I’d always give up on TDD because it just didn’t fit the way I’m used to coding.
But in a world of simple data and functions with a single purpose, TDD comes into it’s own. The tests you write drive the code to be as simple as possible with none of the cruft that typically accumulates in class definitions. And constructing tests is simple – create some simple test data, pass it into a function and check the resulting outputs. All tests follow this simple formula, with not a single pesky mock object in sight.
Lean Code And A Sense Of Progress
The resulting code feels resistant to bloat. Nothing is hidden, and every function has a clear purpose with no unexpected side effects. Time will tell if this pattern persists as the code matures. I’m constantly surprised by the way the code evolves down unexpected avenues.
Every test, every function has a purpose that is clearly defined. This simplicity has a huge appeal. A test and the code that goes with it can be written fairly quickly, and each additional test provides visible progress.
Struct Is The New Interface
I’m used to relying heavily on interfaces or abstract classes in my coding, and the lack of such an option concerned me somewhat. It still does – I miss the option to have a collection of ‘game objects’ and know that I can call Update() on all of them no matter what they are – Crates, Zombies or Flying Quesadillas.
What did surprise me was that rather than accumulating everything into a single class, the data naturally falls into a collection of several parts more in keeping with the idea of components in an OO system (composition over inheritance). For example, when I was writing a leaf particle system the resulting code combined the following bits of data – a mesh, an array of (generic) particles, an array of leaf specific particle data and a free-list for deleting and creating particles from a statically allocated array.
This fragmentation may seem unfortunate, but in fact it’s a strength. The functions that deal with a mesh are applicable to all meshes, not just rendering particles. The free-list struct and functions can be used anywhere that elements in an array need to be frequently created and destroyed. Where in an OO design you carry around an entire object to each method or function call, with this approach you only pass around the ‘part’ of the object that is directly relevant.
Coding Is Fun Again
Ultimately this is the most important point for me. I’m enjoying coding this way. Progress is rapid, and through the use of unit testing, progress is very visible. My free time for game programming is extremely limited, so the ability to write code in small, manageable chunks is a big win. Refactoring can be undertaken with confidence, knowing that the unit tests and the basic structure of the code give some protection against unintended side effects.
This style won’t suit everyone, and it will absolutely terrify the Architecture Astronauts, but if you’re interested then give it a go and let me know how you get on!
Related posts:
2 Comments for this entry
2 Trackbacks / Pingbacks for this entry
-
Tuning Your Game Made Easy - Acorn Heroes
July 9th, 2010 on 7:59 am[...] The corresponding code for this article can be found here. Note that the DebugServer code comes from Miguel’s article, and the AsyncSocket code comes from here. I’ve added a minimal amount to Miguel’s code to pass received commands on to the DebugUtils functions found in Debug.[h|mm]. I haven’t had time to create a complete sample project, but the code provided should drop into any existing code base with minimal fuss. If the coding style looks a little strange, you may want to also read this and this. [...]
-
Puzzle Planets Postmortem - Acorn Heroes
March 28th, 2011 on 12:42 pm[...] Geographic. The code base uses OpenGL and mostly C++ (see notes on my current coding style here). 3d assets were built in Cinema 4d and exported as .obj files before conversion into final game [...]
June 26th, 2010 on 1:30 am
Good to hear you liked the approach, George. The key concept to make this work is exactly what you describe in “Struct Is The New Interface”. A lot of programmers never make that mental leap, but you seem to have done it right away: Things need to be split up into smaller bits of data that can be treated in a common way.
The only drawback I can see is that, while this style makes each function very simple and easy to understand, it can make the overall picture harder to follow. Next week I’ll get into more detail into how I’m splitting objects and how I keep references between them (indices and handles mostly, no pointers, that way they can be serialized really easily and are fully portable).
Thanks for the great article!
July 1st, 2010 on 8:57 pm
Hi Noel,
It certainly takes some getting used to. For me, the hardest part so far is sticking to TDD. Although, almost without fail, the times when I avoid TDD are the times I end up with bad or non-working code.
I do miss the ability to have, say, an abstract class that represents an Action with a single method “Execute()”. This is one OO construct that has worked really well for me in the past, for scripting actions, input handlers and so on. Function pointers is an option here, but not a particularly nice one.