It’s been long and very eventful few months.
Phil Spencer at E3, announcing that Microsoft is aquiring Undead Labs
Looking ahead to a rather bigger future version of Undead Labs — and a State of Decay 3 that’s even more ambitious than 2 was — I’ve been doing a lot of code reviews on my existing code base to see what new hires will have to deal with.
The results are not always pretty. On the purely functional side, the code has held up reasonably well. But it’s got the logical coherence of the street grid in a medieval city — it’s full of quirks, blind alleys, dead code and other hazards waiting to trap the unwary. I rather despair of being able to introduce new TAs to the team without (a) spending inordinate amounts of time on teaching and (b) dying of shame.
The first thing jumps out at me when I read over our code is the hodgepodge of different styles. Not only does the code reflect several different individual styles — any codebase with more than zero coders has that — it also shows distinct archaeological strata in my own style over the last eight years. There’s code that reads like C# (right down to C# naming conventions) and code that reads like MEL. There’s code that does everything in giant 1,000 line monster functions and code that can’t seem to take a step without definining a new class.
Style drift is inevitable — and healthy. It shows that a team is growing and getting better. Unfortunately it also makes it hard to keep a codebase healthy. Trying to revert to the mindset I had seven or eight years ago is difficult as well as embarassing; trying to understand why I did something a certain way is often so much work that it’s tempting to simply rubbish a working but creaky solution and write a shiny new one from scratch.
Alas, it’s easy to plan on writing new and improved systems. Nobody, after all, plans on writing new and improved bugs… but that doesn’t mean you won’t. And the time spent fixing those new bugs is time not spent on new functionality (and the new bugs that come with that).
It’s a big investment to get back to where you are today.
So, dealing with all that fugly old code is definitely not an easy task. Letting things sit is an invitation to code rot and a drag on training; constantly trying to rebuild from scratch means a long struggle just to get back to parity.
The closest thing I’ve been able to come up with as an “answer” is gradualism — don’t let code sit ungroomed, but try to nudge it in the right direction instead of nuking it from orbit and building on the glass. A steady diet of small improvements and modernisations is very preferable to simply burning the whole house down every few years.
At least, I hope it is.
One of the most interesting hidden taxes in old code is the incredible mare’s nest of duplication.
No individual really knows a whole codebase very well. Plus, some people tend to reinvent their own solutions instead of looking around for what’s already there. Meanwhile some people — myself definitely included! — are constantly tempted to invent pure, perfect, abstract solutions for all the world’s problems… solutions so abstract that they often languish away in Platonic purity, unused because they level of abstraction is impossibly high.
And, of course, everybody is better at solving code problems than at naming the solutions, so even the the most well-intentioned colleague may never even know that the tools they want are lying there in plain sight.
Duplication isn’t just a waste of time — it’s an obstacle to making things better and an invitation to code rot. All else being equal, every line of code is a potential liabilitt. So a good part of trying to modernise the codebase is simply going to be cleaning house: finding and standardizing the fifty different ways people look for files that are ‘in the project’ or ‘not in the project’, the dozens of ways people decide of one object is a child of another, the scores of methods for deciding what is or is not supposed to be animatable, and so on.
Untangling that Gordian knot is going to be a large project — one of those things that you have to describe in meetings as “a process”.
I’ve already shared a draft of the doc I’m working on as part of the process.
It may be casually described as a “coding standards” document, but that’s not really a good description: I scarcely give a damn about things like where brackets go. What I’m groping for — and it’s definitely an exploration — is the right way to foster and grow a shared approach to problem solving. Neat well organized code is certainly part of that, but it’s only a small part. The real end product of a process like this is not just better code: it’s a better coding culture.
It might be a bit suprising that I’d bother sharing what’s essentially an internal policy document on the internet. But a lot of what I want to accomplish is to make it easier for new team members to know what’s going on as they join Undead Labs; if my ideas are too far outsife of what you might call the “techart mainstream” it doesn’t matter if I write them down and blather on about them. The whole idea is not to create something radical and new — it’s to help clarify and crystallize the ideas we all half-way know already.
There’s useful analogy in the way that Python programmers use the word “Pythonic.” It’s an almost mystical quality — and, like many mystical experiences, the search for it often ends in controversy and feuding. Even though “Pythonic” is not easily reducable to a set of Powerpoint bullets it’s still a powerful ideal that has shaped a generation of Python code in both very obvious and very subtle ways. After spending much of the last two years in the depths of the Unreal C++ codebase, I’m extremely aware of the way that programming languages create their own cultures. If you want an object lesson, Just watch some of the best C++ speakers, like Scott Meyers or Herb Sutter and listen to the way they talk abou their language — then contrast it to the way somebody like Raymond Hettinger or Brandon Rhodes talks about Python.
Hence, my immediate instinct to a looming cultural change at the company is to write a doc about coding. But the target isn’t just my own team — it’s all those future teammates out there that will have to learn the way we do things. If we can somehow scrape away the idiosyncracies of one team’s history and get at the common, instinctual basis of TA work then onboarding new people will be a lot easier. They’ll be productive sooner, and we’ll spend less energy trying to change their habits into our habits. Instead of trying to invent a novel new culture, it’s more about trying to clarify and articulate things that most TA’s already know and do on some level.
Python has it’s famous Zen of Python. What would a “Zen of technical art” look like? I don’t really know, but I think the next several months might met me a little closer.
If you’re interested in the questions as well, I’d encourage you to grab that coding document and see how you’d re-write it. Feel free to lodge an issue on the github repo, or to submit a pull request if you think something could be better. For that matter, fork your own version and we’ll see how different teams think this ought to work out. I’ve already gotten a lot of useful feedback both through GitHub and person-to-person; more is always better! One of the things I feel is part of half-unconscious TA culture is a commitment to sharing knowledge.
What do you say? Is that part of how we do things?