Here at Cemplicity, we like to keep things simple. In fact, we’re so keen on simplicity that it’s one of our core values.
Yeah, I know. Corporate values. We’ve all worked at places with carefully curated mottoes and philosophies hung in prominent positions that bear no relation to what really happens. But we really do strive for simplicity in all of our processes. Today I’ll be taking a look at why our development team value keeping it simple.
Simple systems are easy to understand.
If you’ve read my previous posts about how we transform post-its into code, you’ve got a pretty good idea of how we get our work done. Seriously, there’s not much more. Simple, huh?
Our development team may be small and mighty, but it won’t be for long. Well, the team will always be mighty, but a time will come when we won’t be able to call it small. The first days, weeks and even months of a job are always stressful, so anything we can do to reduce the cognitive load for new starters is good. The thing is, we’re all new starters even if we’ve been here for ages – if you haven’t worked on a particular area of code for a while, it’s quite likely you’ll be doing a Gandalf impression next time you stumble across it.
There’s no way to avoid the learning curve when encountering new code (or re-encountering something old and classic). But if the code is written in a relatively plain and simple style, hopefully the learning curve isn’t so steep.
Simple systems are easy to change.
“Everything changes and nothing remains still … and … you cannot step twice into the same stream”
Good old Heraclitus wasn’t wrong. Our code base changes every day. Sometimes code that once solved a problem just doesn’t any more because something else has changed: perhaps the original requirements are no longer relevant, or we’ve found a better way of doing things. Libraries, tools and frameworks need to be updated. And every now and then some bug creeps in and needs to be exterminated.Whatever the reason, a change needs to be made, which will take some time. Exactly how much time depends on how simple the surrounding code is. Though we strive for simplicity, we don’t always succeed. If a change has to be made in code that is already simple, it could be completed, tested and in production in a few hours. But our sea of simple code is not without a few Scyllas (and perhaps a Charybdis or two). That’s why we keep the ropes and life-jackets close at hand. Changes in the more complex regions of our code tend to take days, not hours. But there’s a bright side: if we find ourselves in a complex area of code, we always try and make it a little simpler for next time.
Changes in code that was already simple tend to be small. Which means less code to review, less testing required and a smaller blast radius if something goes wrong.
Simple systems are easy to scale
When you look across the codebase, we’re thinking more. More customers, which means more load on our servers and more records in the database. More developers, which means more tests and more lines of code. And more challenges, which could mean more complexity, no matter how much we struggle against it.
We can’t predict exactly how our systems (or our team) are going to need to change in the future. But if we assume we’ll need ‘more of everything’, then it’s a good idea to make sure everything we have now is simple. If a system can be decomposed into a collection of small components, we have more options when all the dials go into the red and the disks start filling up. Perhaps we can scale horizontally, adding more of one particular component to avoid some performance bottleneck. Perhaps we need to scale vertically, swapping out some software component or server for a more powerful alternative. A simple architecture should help us response to scaling pressure whenever, and wherever, it appears.
Simple isn’t simple
Simple doesn’t always mean small. Any particular piece of code should be as small as possible, but no smaller. I’ve found when simplifying code there’s an event horizon beyond which the code you thought was so easy to understand suddenly becomes far more complex. Perhaps you started breaking a block of code into a series of small functions, then noticed some commonality in those functions so created a few more so as not to repeat yourself. But in doing so, did you remove the essential meaning of the original? While each individual function is small, when the next developer comes along to maintain this code, are they going to need to construct a complex mental model to replace the context that the larger original provided? Every person is different: the next developer might not construct the same mental model – even if the next developer is you.
You’re never going to reach a point where all your code is clean, your test coverage is perfect and your documentation is unambiguous. And even if you could, Heraclitus would suggest your current state of perfection is only temporary. Or to put it another way:
Trying to keep things simple is a constant struggle and you’ll never reach the end of it. But it’s a lot better than the alternative.