Clever vs. Simple Code

Summary:

As projects have become more complex, it becomes necessary to make the code simpler in response. Here’s how that concept helps Combustion move more quickly for both individual developers as well as the entire team.

Post:

Developers are clever. And some developers love to show through their code just how clever they are by doing the most work possible in as few lines and characters as they can. But as projects become more complex, the opposite becomes important–code should be as simple and verbose as it can be.

Now to clarify, “simple” code doesn’t mean “simple” results. At Combustion, we’re developing a number of single page applications that each communicate with multiple services, with an emphasis on fault tolerance and recovery. But the goal is that someone who has a general understanding of the patterns we use in applications can work on something we developed months ago and make changes without needing assistance the entire way. Or–more likely–that our developers aren’t frustrated trying to understand what they coded just a couple of months ago.

Overly complex code is not easily testable; therefore, the code cannot be easily maintainable. Even if you’re not writing unit tests (which you should be if possible), the more things that are happening in any single block of code, the more outcomes you have to test any time you modify that block of code. New bugs become much more likely. Maintaining the code base becomes an ever increasing chore.

Simplifying code can take on many forms. At a micro level, it can be making sure to use accurate variable names instead of “x”. For modules, it can mean separating reused or complicated blocks of code into smaller, testable methods and utilizing functional programming concepts. At the application level, however, simplicity in code is driven by the application’s architecture.

Nearly all applications are based around consuming, processing, manipulating, and saving data. So on a large-scale project, we start by designing the data model and the necessary API endpoints to support the front end. Once the initial data model is complete and API contracts have been negotiated, both parties can work independently and know exactly what to code to. If something changes or a new requirement reveals itself during development, we take the time to renegotiate the contract and make sure that everyone involved knows the impact.

This structure also allows the front end, back end, and database to be independent components. By separating responsibilities, work is never duplicated but instead is distributed intelligently. The API can support multiple distinct applications. The front end application can logically separate how the data is loaded from how the data is consumed. And the overall application design is consistent with our other projects.

A code base that is difficult to understand may result in increased “job security”–but that “security” is handcuffed to always working on that code base. And the more time a developer–and by extension, the developer’s company–spends in maintenance, the less time that company spends creating new features, working on new projects, and moving forward.