Software design

Article Image
A proper software design is easy and inexpensive to change, unlocking agile development.
Any software you write will constantly be changing. Once in production, feedback from the users and change requests from the stakeholders will pour in. A proper software design is easy and inexpensive to change, unlocking agile development.

You'll never create a perfect software design, but you must constantly seek to improve it. Empower your people to challenge you. Take time to review the code. People are good at finding fault with other people's work, so code review should be a constant process performed by the whole team. It should be tactical rather than detailed. The evolution of software design must continue throughout the development process. There are certain concepts you should keep in mind whenever you're working on a software design:

KISS (Keep it simple and stupid)
Inherent complexity is a part of life, and the domain model you translate into the software will be complex. If we add accidental (code) complexity to it, we create a perfect storm. The more complex code, the more difficult and costly it will be to change. Simple code fails less, and it is easier to understand. A good software design hides the inherent complexity without creating accidental complexity.

However, simplicity is truly the ultimate sophistication. To strive towards it, we must stick to the rules. Remember that you never finish software; you can only abandon it. Refactor your code whenever you get a chance, and never miss an opportunity to simplify it. Remember Einstein: "Everything should be made as simple as possible, but not simpler."

Write unit tests first
Writing unit tests will force you to write modular code and only the modules that you need at that moment. They will force you to write single responsibility methods. Writing proper simple classes and methods with only one function is much more complicated than it seems. Code is constantly tugging at us, demanding complication, offering an illusion of simplicity today in exchange for the complexity tomorrow. Unit tests, written first, are your primary weapon to keep it in check.

Tracing bullets

If you need to create five classes used by a top-class, never write all five immediately. Write one and write the top class that uses it. That is your tracing bullet. Use whatever you learn while testing that class to write the rest of them.

Don't repeat yourself. 
Duplicating code duplicates effort. It is easy to copy/paste code. It is also self-defeating, as it repeats your action in the future when you must change that piece of code. Nothing adds more complexity than duplicated code. Every time you notice the duplication, take the time to refactor it; your future self will thank you. Refactor when you can or must, but never miss a chance to remove duplication. Keep things DRY (Don't Repeat Yourself).

Commit code often and integrate early
Integration testing is critical. The software usually contains many moving parts that need to work in unison. You can't avoid inherent complexity, but you can minimize it by committing your code often and integrating early. Use automated testing combined with the tracing bullet methods to ensure things are working end-to-end. It will enable you to find the problems early in the process and prevent them from infecting the rest of your development. You must have CI/CD, a method to frequently deliver apps to testing and customers by introducing automation into the stages of app development. Continuous integration, delivery and deployment should be your mantra.

Do make mistakes
Make sure you learn from your mistakes and don't be afraid to make them. Without eliminating what doesn't work, you'll never find out what does. We are scientists. Trial and error are principal weapons in our armoury.

Postpone everything you can
It is far more difficult to backtrack once you decide and act. Things get entangled, and it is far more difficult to correct a wrong decision. Postpone decisions as much as possible, or at least until you've found the "key". It will usually be straightforward once you find the right way (Occam's Razor). To be able to postpone decisions, you must have the proper agile procedures in place, and you must have eliminated waste [see the article on removing waste]

Don't write comments
If you feel the need to comment on your code for posterity, your code is too complex. Instead of writing comments, refactor the code, modularise it, and write unit tests. Unit tests are the best code comments.