Rodrigo Rosenfeld Rosas
How to write maintainable code?
I have been willing to write such an article for a long time and finally found some inspiration and time for doing it.
Working software does not suffice
No software is finished. Even Vi, which was created in 1976, is not finished. If no one is working in some software anymore it just means it is not being maintained or has been replaced by another one. That means your code will be changed or entirely replaced.
Unless you're expecting your software to be replaced soon, you should consider writing maintainable code. It's very important to your code to be readable and maintainable because most of the time developers will spend reading it. So, while knowing well your editor is important, you should consider spending more time refactoring your code to make it more readable than finding new ways of writing efficiently using your editor because a clean source code will save you much more time than any editor key mapping. But also, a good editor/IDE will also help you to refactor your code.
You should really apply the good advices present in all books about Agile Software Developing since it is the only way I know of writing software that actually works in the real world. I'll not talk about Agile in this article, since it is out of the scope and there are also great books out there about this subject. I'm assuming that the reader is familiar with the subject though for better understanding this article. Here are the software writing guidelines that I'm talking about, although I won't explain the reasoning behind them, as they are a bit long and all books and articles on the subject will explain them:
- Don't write code for the future
- Write automated tests that cover your requirements
- Continuous refactoring (will be extended in this topic)
- Continuous integration
- Continuous delivering
Since you'll be writing code for today's usage, sometime you'll face the situation where you need to write a new feature that shares lots of implementation details of a prior feature. You shouldn't be copying and pasting code from the prior feature. This seems obvious but if I didn't often find code written that way I wouldn't be talking about this. WARNING: whenever you find yourself copying and pasting some code, even for different projects, you should think twice. Most probably you should separate the common part in another method, class or library. Some languages will require some boilerplate code, but make sure you're copying and pasting only the necessary boilerplate if that's your case.
The commonest reason why developers don't rafactor their code is because they're afraid of breaking some critical production system. This is often related to the lack of a good suite of automated tests. Specially if your application is a critical production system, it should be covered by tests. The more you copy and paste code, the harder it will be to evolve the code base and understand it.
The same bug will also happen in multiple places in the source code and even if you fix it in some part of the code, the bug will show up again on Friday, 5pm, and you'll have to cancel your weekend planned schedule to work hard to find a hidden bug that was already fixed in other part of the code but you don't know that because you were not the one that fixed it. And people will be asking you why does it take so long for fixing the application under production in the most critical time where it shouldn't really fail while presenting it to a big potential client corporation!
Automated test writing
TODO: talk about test simplicity, coverage, documentation tool and careless about TDD or testing after. TODO: talk about test priorizing. TODO: talk about mocks and importance of speed and isolation of concerns
Keep your code minimal
You should really keep your code minimal to be polite with the other developers that will work in your code some time later. Maybe that developer will be you again. Having small methods, classes and files will help reading the code without the need of scrolling the text. Also, some editors like Vim allow you to display multiple source files at the same time. Having small methods will help you to understand the overall code.
TODO: talk about spending time thinking in good names
TODO: talk about how comments can be avoided with clean code
Choose a good language if possible
TODO: Compare C++ and Java to dynamic languages like Ruby, Python or Groovy TODO: talk about tradeoffs and performance concerns vs development speed TODO: talk about legacy Java code and JRuby, Groovy, Scala, Clojure and JPython. TODO: also talk about network-based API integration
Adopt great frameworks and libraries
Keep It Super Simple - the KISS principle
TODO: Avoid uncommon solutions and complicated architectures
Avoid proprietary or language-specific solutions
TODO: Give preference to common network based APIs
Understand the Single Responsibility Principle (SRP)
TODO: you can apply or not but it's important to understand it
Don't bother too much about the Open/Closed Principle (OCP)
TODO: explain differences between writing end-software and libraries and talk about tests here
Take decisions by yourself (avoid just following well-stablished patterns)
TODO: talk about Java, setters/getters, private/protected/public, interfaces and its abuse
Use dependency-resolving tools
Use the best VCS tool you can find
TODO: and invest time learning it
Coding style examples
Early interruption pattern (or handle exceptions first)
TODO: return if exceptional_case
Don't handle exceptions at all if possible
TODO: talk about the try-catch approach and the type of applications (libraries, unsaved data) as well as about tests.
Don't catch each exception for general algorithm
Avoid deeply nested constructions
TODO: talk about nested if's, while's and alternatives like catch-throw
Sort method caveat
TODO: talk about <=> and how to deal with its lack in some languages. Sort should return -1, 0 or 1. TODO: talk about wrong usage of sort for getting max and min.
Switch-case and handling by hashes (or maps)
TODO: talk about synchronized methods
Performance and Scalability
TODO: talk about language vs architecture, and concerning before due time or without benchmark/profiling.
TODO: talk about simple web APIs and queuing systems for integrating applications in possibly different languages. TODO: Avoid writing language or vendor specific solutions
TODO: It does happen in Java. Talk about unbounded in-memory cache.