At some point in your life, you decided that you wanted to become a programmer. Maybe you became a self-taught programmer, or perhaps you went to college. It doesn't really matter; your first step was learning how to write some code. After some time, you got your first job, and you realized that writing code is only the easy part of being a software engineer. The tricky part is writing good code. There are many different points of view about what "good code" means.
In this post, I'm going to focus on maintainability. We can define good code as code that is easy to maintain. So after learning how to code, your next goal will be to learn algorithms, design patterns, principles, and best practices. These concepts will help you to write code that is easy to maintain.
Algorithms can help us to solve some common performance problems. For example, if you need to implement a search feature, in specific scenarios, it might be faster to use a balanced tree than using an array or a list. Learning about data structures and algorithms is useful because it will give you more options to achieve better performance, if needed, when implementing a feature.
Here is my first important point, algorithms and data structures are very useful, but they make things more complex. An array is easier to understand that a balanced tree or a graph. You should only explore using a more complex data structure when there is an actual need for it.
A design pattern is a general repeatable solution to a commonly occurring problem in software design. A design pattern isn't a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations. An example of a design pattern is Event Sourcing. Just like algorithms, design patterns are beneficial and can help us to solve problems in a well-known manner. However, applying the wrong design pattern to the wrong problem can be even more harmful than not using it at all. Once more, make sure that there is an actual need for it.
DRY stands for "Don't Repeat Yourself," and it is a fundamental principle of software development aimed at reducing repetition of information. The DRY principle is stated as, "Every piece of knowledge or logic must have a single, unambiguous representation within a system.".
Here is where things start getting interesting; the DRY principle sounds like an excellent idea. However, the DRY principle can also be a big problem when we apply it dogmatically.
Dogmatically: Inclined to lay down principles as undeniably true.
I want to argue that all the software algorithms, design patterns, and principles can become anti-patterns and bad practices when we treat them as dogma.
We need something to remind us of this problem. I personally use something that I like to call "The Yin-Yang" principle.
Before I explain what this is all about, here is a little bit of background information about the Yin-Yang:
Yin and yang (or yin-yang) is a complex, relational concept in Chinese culture that has developed over thousands of years. Briefly put, the meaning of yin and yang is that the universe is governed by a cosmic duality, sets of two opposing and complementing principles, or cosmic energies that can be observed in nature.
The yin-yang symbol (also known as the Tai Chi symbol) consists of a circle divided into two halves by a curved line. One half of the circle is black, typically representing the yin side; the other is white, for the yang side. A dot of each color is situated near the center of the other's half. The two halves are thus intertwining across a spiral-like curve that splits the whole into semicircles, and the small dots represent the idea that both sides carry the seed of the other.
The white dot in the black area and the black dot in the white area connote coexistence and unity of the opposites to form the whole. The curvy line signifies that there are no absolute separations between the two opposites. The yin-yang symbol, then, embodies both sides: duality, paradox, unity in diversity, change, and harmony.
In my opinion, the KISS principle is the most crucial principle in software architecture, and perhaps the only exception to the Yin-Yang principle.
KISS, an acronym for "keep it simple, stupid," is a design principle noted by the U.S. Navy in 1960. The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.
The idea of the Yin-Yang principle is that on one side, we have the KISS principle, and on the other side, we have a given principle, for example, the DRY principle. Both principles need to co-exist in harmony. If the DRY principle takes too much priority, we can end up adding abstractions to avoid repetition. However, maybe this is not a good idea. The wrong abstraction is often harder to maintain than code duplication. If the KISS principle takes too much priority, we might end up with excessive code duplication.
We can also have an algorithm or data structure on one side and the KISS principle on the other side. Is this data structure the best way to solve our performance problem? How much complexity is it going to introduce? Could we use other solutions (e.g., Caching)? Which solution is going to have the best balance between complexity and results.
The same applies to design patterns. If we are going to introduce complexity, we should have a very valid excuse.
It is important to don't forget about requirements as well. Users will ask for all kinds of things but just because a user ask for it it doesn't mean that it is a good idea. You should wonder if the user demand is enough to justify the increase in complexity. Every new feature adds an extra bit of complexity to the system. Maintaining software is basically a constant battle against complexity.
As developers, we learn about design patterns, algorithms, data structures, and best practices because we want to go a good job. However, sometimes we forget that these are just recommendations and that violating them doesn't always mean that we are not doing a good job.
Please remember, design patterns, algorithms, data structures, and best practices can all become anti-patterns. Remember to stay pragmatic and avoid dogmas in Software.
Pragmatic: Dealing with things sensibly and realistically in a way that is based on practical rather than theoretical considerations.
Use the Yin-yang principle to remember that whatever you do needs to co-exist in your codebase in harmony with the KISS principle.