Writing GOOD Code
All developers want to write good code. But what is good code? Good code is often defined in terms of architecture, patterns, tools and languages used. All this complexity does not necessarily equate to good code. In fact, it might indicate the exact opposite.
Good code, in essence, is code that delivers the functionality the business requires. It really is that simple. The one big caveat is that it must continue to do so over time. For most developers the functionality required by the business is an ever changing, living, beast. So, this leads to the conclusion that good code is code that can adapt and change easily to shifting requirements.
How do you make code adaptable when you can’t predict the future? The first principle is to not try to predict the future, because you are likely to get it wrong. Resist the urge to over engineer your solution. Past experience can, and should, guide you in structuring your code based on the known system requirements, but resist over investing, up front, in structure over function. Begin building what you are sure of.
Correct Code
When writing code, the foremost challenge is creating correct code. Code that does what it is supposed to do. The following are developer challenges that can lead to incorrect code.
- Don’t know the requirements – if the developer does not have a clear idea of what the business requires, then it is very unlikely the code will operate correctly. This is usually indicative of a failure of process.
- Don’t know the existing code – if developers have not spent the time to understand the current system, before they try to make changes to it, then they are very likely to make mistakes. This can be driven by unrealistic deadlines or lack of care. Being inquisitive is a great characteristic for a developer. Don’t just myopically stare at the piece of code right in front of you – look around, explore.
- Don’t know the tools or frameworks – a developer needs to know their tools and environment very well. An inexperienced developer, who is unwilling to ask for guidance, will often use tools in a way they were never intended to be used. This will lead to the code not performing as expected, either immediately, or over time as the tools change. Spend the time to skill up and know your tools.
- Don’t know the delivery platform – the most common delivery platform is the ubiquitous web browser. Web browsers are so diverse in implementation that this can be quite difficult to master. Delivering a consistent and functional interface over all major browsers on desktop, laptop, tablet, and mobile is very challenging for even the most experienced developer. There is no substitute for testing – don’t guess.
Knowledge is the best antidote to bad code.
Strong Code
Writing code that does what it should do is the starting point, but it is just the first bar. Code must also be strong. By this, I mean it must do what it is supposed to do, and do it consistently over time, in a way that lets the user be productive. A system that is buggy and slow doesn’t help anyone.
- Dependencies – no developer starts from scratch and writes the whole system themselves anymore. Like it or not, we are often just assembling Lego pieces, and writing the code to hold it all together. Whether this is frameworks or libraries or third-party systems we end up with a huge chain of dependencies. Each one pulling in several more and we have no idea of the veracity of each element. What hope do we have in vouching for the system as a whole? Keep your dependency list as short as possible. Stick with the tried and true.
- Performance – if a system works, but only extremely slowly, then it is not a useful tool for the business. Even worse, if it fails with a timeout on an irregular basis. There are many causes of bad performance, but suffice it to say, good performance is critical to writing good code. Performance should be built in from the start, not added as an afterthought.
- Platforms – after you’ve written you code it needs to run somewhere. Once again, you are probably dependant on factors outside of your control. This includes, in most instances, cloud hosting services. Choices made here, can have an impact on the robustness of your solution. Free is not always cheap.
In all these areas, strength often comes from simplicity.
Flexible Code
If a system does what it needs to, and does it consistently, and in a timely manner, then what else do we require? You need code you can maintain efficiently. The long-term usefulness of the system requires constant updates to keep it relevant to the changing nature of your business. Not all businesses are rapidly evolving, but it would be very rare to have a completely static system for any length of time.
- Discoverability – finding the code you are looking for within a large solution can be half the battle. Code that is logically organised into projects and folders can really help. Naming conventions are hugely important. You should be able to tell from the name and context what type of object it is. An IDE that allows you to navigate between references and definitions is a great time saver.
- Understandability – reading code should not be a chore. Naming of variables and functions should not be cryptic. Names are key to understanding code functionality – take the time to choose names that are meaningful and accurate. Layout and structure your code so reading it flows naturally and it is not too dense or too sparse. Keep the logic as simple as possible. Don’t introduce complexity for the sake of it.
- Consistency – do the same things, the same way, across the system. This means that after you have come to terms with one module, you can very quickly pick up another one, because they all follow the same pattern. This is a huge time saver and stops bugs creeping in through false assumptions. Coding patterns are a great way to ensure consistency. Code patterns should be used to simplify code – to solve problems. Patterns should not make code unnecessarily complex.
- Reuse – do it once then reuse it. Do not duplicate the same piece of logic all over your system. This makes future updates much simpler, and less risky. When the same thing is done two slightly different ways, nobody has any idea which one is correct.
These things are easy to do when your system is new and shiny, but make sure that you constantly refactor over time, so tech debt does not build up.
Simple Code
The above guidelines might sound like coding 101, but writing good code is often a matter of reminding yourself of the basics. Unchecked complexity is often the enemy of progress. Reinforce and simplify the foundations so your code stands the test of time.
Bit Wrangler
6 年I'm always surprised at how little Real understanding there is amongst devs of the basics encapsulated in the SOLID acronym. We are pressured to learn frameworks with little to no time allocated, but aren't given time to really understand how to Craft good code in these frameworks.?