Writing maintainable code can be challenging especially to newer developers, because they won’t have experience with coming back to code later or having to review somebody else’s changes. In this blog post, I provide 5 Tips on How to Write More Maintainable Code.
What is Maintainable Code?
Maintainable code is basically the amount of time it takes a developer to make a change and the amount of risk that the change could break something.
If you were looking for some sort of formula, I would say it’s MaintainableCode = TimeToImplement / Risk
Why should code be maintainable?
More maintainable code allows for easier changes which results in faster changes and a lot less risk. More maintainable code + tests = faster changes which fewer bugs.
5 Tips To Write More Maintainable Code
As a software developer with 10+ years of experience in multiple languages, I’ve gathered a lot of understanding of what makes code more and more difficult to understand.
A lot of these tips have been documented hundreds if not thousands of times before, if you want to be a good developer you need to start following these sorts of ideas.
Write Code that is Easy to Read
Reading code can be a challenging task – remember the time when you were learning how to read and how you struggled with each new word and then eventually each new sentence and so on. As you gain experience as a developer, you gather an incredible amount of intuition about what code will do. Easy to read code is code that is easier to guess what it’s going to do. It’s a bit more than long descriptive variable names, short methods, etc.
So, what does this mean? It means that we need to write for the experience levels of our readers and also focus on doing the right things. If your company is a startup or hires a lot of junior developers you need to be cognizant of the fact that junior developers will find it difficult to follow lots of small methods, and variables like “NumberOfPoints” instead of “intPoints” or “points”.
This is a balancing act, and it can be really tough – it means we need to gradually introduce change. It means that we need to follow the conventions if it’s not a greenfield project, and slowly introduce refactorings overtime instead of doing massive rewrites every time we commit changes. If your fellow programmers aren’t used to concepts like dependency injection it probably wouldn’t be a good practice to start just adding it everywhere.
Note: some languages are easier to follow than others, but this advice should work for most languages.
Follow a convention
Code should be consistent in style to make it easier to follow and easier to change. If there’s a common standard for a language, it should be followed, and where possible it should be automatically checked each time a file is saved.
Following the idioms of the language is also a good idea as this will dramatically help onboard each new developer that gets added to the project. Do not try and blindly force a language to follow the idioms of another language. For example, a lot of companies developing mobile apps expect their Android Code to work like their iOS Code – but they are very different languages and environments.
Give Meaningful Names
Descriptive variable names can go along way in making things easier to read and to understand. Public methods that are getting called by other methods should have obvious parameter names and they should ideally be in an obvious order.
Where possible, use enumerations or constants instead of checking if a String is equal to another string. For example, in code that controls what navigation a user has based on their role, you should have the Roles as Enumerations instead of just checking is User.Role === ‘Admin’ everywhere. It might even make sense to instead have a method that returns a boolean based on the Role, so you only have to change one place if suddenly the “Admin” role changes to “System Admin”.
Write Small Classes and Functions
Long functions have the potential to make code very difficult to understand. Long functions or long classes are usually a symptom of far too much responsibility. Martin Fowler in his book “Refactoring: Improving the Design of Existing Code” explains a lot of different techniques for making functions and classes smaller. Common and relatively easy refactorings to do can be moving the logic from switch statements into multiple functions.
For Example, say I had a switch statement that had a dozen or so lines per case statement. I should be able to move quite a bit of that code into little functions that my large function can call. Eventually, maybe I can move some if this logic into separate classes that implement interfaces and a factory could return the correct one.
Write Testable Code
It’s been long said that the sooner an error can be found the cheaper it is to fix. Automated testing can help significantly reduce the costs to make changes and help more it far more obvious when there are problems. In my blog post, Best Practices for Writing Tests I cover a lot of different practices for writing tests and why it’s so vital.
Comments Should add Value
In my blog post, Clean Code – Are Comments Required? I cover when comments should be written and when they shouldn’t be. In general, I think commenting adds a lot of value if it explains why something has been done a certain way and if the comments are kept up to date. Comments that long and provide no value should be avoided as they’ll end up adding to the confusion and mess.
Code Complete, The Clean Coder, and the Pragmatic Programmer all provide a ton of good tips and explanations of these concepts. A junior programmer can gain a tremendous of amount of knowledge from studying any of these books.