There’s a recent trend in the software industry that I’m watching with a little concern. Countless new tools for static code analysis and “automated software review” are popping up on the market and being in a technology leadership position at a successful startup myself, I’m now getting pitched for this stuff on a regular basis. Even though I’m absolutely dedicated to code quality, I’m very skeptical at these tools – because, in my humble opinion, they are trying to solve the wrong problem. There’s an uncomfortable truth that I’d love to tell all companies seriously seeking to relieve their code quality pains by using these methodologies:
You probably have too much code.
The problem at the root of this issue is a decades-old industry focus and incentivization on producing code, not on taking it away. If you give a problem to a developer, there’s a usual and deeply embedded Pavlov reflex of solving it by writing or adding code. It’s what a software developer is paid for anyway, right?
Less is more
All these are signs of a dangerous culture that encourages software bloat, steadily leading to slowed software development up to a state of total unmaintainability. If you don’t believe me, go take a look at the 3.5 gigabyte (!) binary of SAP BusinessObjects Explorer. I’ve seen so many companies grinding to a halt by throwing software layers on top of each other, that I’ve coined a name for it: Death by Abstraction.
Why you need less code
Less code –> less errors. Period.
There are recent studies showing once and for all that the density of software errors is most strongly correlated by the number of lines in the module, regardless of the language used. Having less code makes projects stabler, leads to better test coverage and simplifies operations. It also helps to use a language that is as terse as possible (we love Coffeescript).
Code doesn’t just have to be written – it has to be read as well. Reading and understanding code takes time, lots of it. (Paradoxically, large, complex and fragmented code bases tend to have a lot of large, complex and fragmented documentation to read on top.)
Time however is usually one of the most valuable and rare ressources in the software industry.
Having less code helps you onboarding new developers on a project and getting productive way faster, and in the same way also helps with turnover. Most importantly, it prevents complexity by “code fear”: If people can’t understand other peoples’ code, they tend to abstract it away. This is the exact reason monstrosities like CORBA were born in the first place, feeding the code-adding cycle once again. I’ve been in companies where projects had to be abandoned because of people being scared to touch a recently “disappeared” employee’s source code. Writing less codes helps preventing such disasters in the first place.
How to get and write less code
Incentivise and encourage a “taking away” mentality
I can’t overstate how important it is to continuously fight against the code-adding mentality itself that still resides in most developer’s heads. Put into your core values, acceptance criteria and processes that taking code away is just as important (if not even slightly more) than writing it. Every net code line and file added is a maintenance liability.
If you are designing a software component to solve all of your current and future problems at once, you’re setting yourself up for failure. Solve the problem at hand and nothing more – if in doubt, you ain’t gonna need it.
Clearly separating your problem domain and constraints enables you powerful shortcuts. If a part of your internal tools does not need to be in the customer facing dashboard, you can save yourself half the development time by getting away without pixel-perfect design mockups, OAuth authentication, less QA, less testing… you get the idea.
Generalization is usually the enemy of lean software. One of the best strategies is to force yourself to generalize “on demand”. Start with all assumptions and shortcuts neccessary to make your life easier right now and follow the old adage “One, Two, Three, Refactor”. Don’t worry too much about “later” – more often than you think, you’ll come up with an even more elegant solution anyway.
Challenge frameworks, libraries and abstraction layers
Separation of Concerns is incredibly important – but so is keeping a code base maintainable. Coming from a Java shop with nightmares of SOA done wrong, we had a grand vision of a one-page dashboard in Backbone and Chaplin.JS served by a fancy Collection+JSON API as Broadway.JS application on top of a Sequelize ORM.
In the end we saw we had so many dependencies and “magic” happening behind the scenes that displaying simple things from the database in the dashboard took ages in development – we realized we had made a 2013 version of the same mistakes in overengineering we were committed to not repeat. We threw out nearly everything and now use pure Backbone.JS on a lean, hand-built JSON API, tripling development efficiency.
Don’t believe in hypes. Believe in simplicity.
Take a step back
If you regularly look at the big picture and question the compartment and component borders inside of peoples’ heads, you’ll often find that modules do duplicated work, can be merged or could be thrown away altogether. Be bold and go for it when there’s an opportunity.
Fight complexity all the way
The sooner you realize that code is as much a part of the problem as a part of the solution, the sooner you can start coding less. If the solution to your problem can fit into a plain old class, don’t encapsulate it with the newest MVC framework or instantiate an AbstractSingletonProxyFactoryBean around it “just because”. Seriously, keep it as simple as possible – but not simpler.
I may be a heretic here, but if you look objectively at the Gang of Four patterns, you’ll realize that most of them were designed to lessen the pain of adding more code to a project involving many developers by adding more code. And that’s okay, remember they come from an era without Git, TDD and Continuous Integration. They can be powerful at times, but they often serve as fuel for the vicious and self-serving cycle of software bloat. Use them wisely, but not for their own sake just or to look professional.
I’m a big believer in Continuous Rewriting and it also seems to pick up adoption lately. If instead of going all the way, you start out with a prototype that’s meant to be thrown away, you achieve a lot of important goals:
- You free your mind from having to deliver the final solution and iterate fast, casually adding tests as you go.
- You protect yourself from abstracting too much and prevent adding “fixtures” for possible future use.
- You will have solved (a part of) the problem with working code and have validated the technical feasability of all aspects.
- You learn a lot about the stuff that works and scales and the stuff that doesn’t.
Now if you have separated your problem domain properly and have tests for business rules, it’s easy to take all the knowledge you’ve gained to not just refactor and extend the component but to completely rewrite it, simplifying the internal design to the maximum. This way, we have rewritten our core matching component three times already – from 3000 lines of Java to 600 lines of Python to 200 lines of Coffeescript, while still adding functionality and scalability by a factor of 200.
Pair programming and code reviews
Pair programming and code reviews are the best tools to prevent people from reinventing the wheel, continuously update each other on best practices, simplify code and reduce clutter. Both techniques directly as well as indirectly lead to less code – they guarantee that someone else will understand and have read the code and reduce “code fear” by an order of magnitude. If you find you often don’t have the time to do pair programming and code reviews, you probably should do more of it.
I’m curious, so be sure to let me know in the comments!