Software Development Principles — it is a number of specific rules and recommendations, which engineers need to be followed during program implementation if they want to write beautiful, understandable and maintainable code. There is no magic wand, by which you can transform a mix of variables, classes, and functions into the ideal code, but there are some tips and hints, which can help the engineer to determine if he doing things right.
Let's look at this base recommendations. Some of the principles below are Python-specific, but most are not.
Measure twice and cut once
I think this is the most important principle of all. If you learn just one principle from this post - it should be this. We,
developers/devops/architects/managers people struggle from lack of attention, from stupid mistakes and typos, from personal problems, from bad mood and cold coffee. That all is irrelevant - you need to solve a problem. For me as an engineer, this principle means choosing the right problem to solve, choosing the right approach to the problem, choosing the right tools to solve the problem, confidence in built solution.
But this confidence cannot go from the code itself, it should go from all kind of tests, from running them often, from building the right solution for the problem and so on. This is Engineering as it is. I think I myself is not ready to describe it in the right words.
Don’t Repeat Yourself (DRY)
It's a pretty simple, but very useful principle, which says that repeating the same code in different places is a bad idea. This is primarily due to the need to further maintain and modify the code. If some code snippet duplicates in several places within the program then there is a high probability of two disastrous situations:
- Making even small corrections into source code, you need to change the same code in several places. It will require additional time, effort and attention(sometimes that is not easy)
- The first item follows the second. You or another developer from your team may accidentally miss one of the fixes and face subsequent errors in the application. That errors may be frustrating because you heard that such a bug was already been fixed.
In this regard, there is a recommendation - if any code is found in the listing more than two times, then it should be placed in a separate method. This is a general recommendation, in fact, you need to think about creating a separate method, even if you meet the repetition a second time.
It is a very common idea that came into programming from philosophy. The principle got its name from english monk William of Ockham. This principle says: «Entities are not to be multiplied without necessity». In engineering, this principle is interpreted as follows - no need to create extra entities without the need for them. So, you always need to think first about the benefits of adding one more method/class/tool/process/etc. After all, if you add one more method/class/tool/process/etc and don't get any benefits but increasing complexity then what's the point?
Keep It Simple Stupid (KISS)
It is a very similar principle with the one above but it has a slightly different meaning. This principle says that code should be simple, without any complicated structures if possible, otherwise it will overcomplicate debugging and maintenance of the code. In addition, it will be more difficult for another programmer to understand the code logic, which in turn will also require additional time and effort. Therefore, always try to use simple constructions as possible which solves the problem without numerous branching, deep nesting, overengineered class structures. By doing this you will simplify life for yourself and for your colleagues because complexity breeds bugs. Remember what Pieter Hintjens said: "Simplicity is always better than functionality."
You Aren’t Gonna Need It (YAGNI)
A problem which a lot of programmers suffer. The desire to implement at once all necessary (and sometimes even unnecessary) functionality from the very beginning of the development process. That is when the developer from the very beginning adds all possible methods to the class and implements them, while in the future it may even never use them. Therefore, according to this recommendation, implement only what you need in the first place, and in the future, if necessary, increase the functionality. So you will save efforts, time and nerves on debugging code that is not really needed.
Big Design Up Front
Before starting to develop functionality it is necessary to think first about application architecture and design the entire information system up to fairly small details, and only then proceed to implement according to a previously prepared plan. The principle has the right to exist, but recently there is quite a lot of his criticism. This is primarily due to the obsolescence of the plan during design and development. In this connection, you still have to make subsequent changes. But it also has irrefutable advantages, with the proper design you can significantly reduce the cost of further debugging and fixing bugs. In addition, such information systems are usually more concise and architecturally correct.
Avoid Premature Optimization
"Premature optimization is the root of all evil (or at least most of it) in programming" - Donald Knuth
Optimization is a very right and necessary process that allows you to speed up the work of the program, as well as reduce the consumption of system resources. But everything has its time. If optimization is carried out in the early stages of development, then it can do more harm than good. This is primarily due to the fact that the development of optimized code requires more time and effort of the developer and it may be more complex. In this case, quite often it is necessary to first verify the correctness of the chosen development approach. Therefore, at first, it is more profitable to use simple, but not the most optimal approach. And in the future, assessing how much this approach slows down the work of the application, move to a faster or less resource-intensive algorithm. In addition, for the time while you initially implement the most optimal algorithm, the requirements may change and the code will go to the garbage. So there is no need to spend time on premature optimization.
Principle Of Least Astonishment
This principle means that your code should be intuitive and obvious, and not surprise another developer during code review. For example, if the method called "make cookies", but as a result, you get a potato than this code is bad (obviously).
“SOLID” is actually a group of object-oriented design principles. Each letter in “SOLID” represents one of the principles, which are:
- Single responsibility states that every module or class should have responsibility for a single part of the functionality provided by the software and that responsibility should be entirely encapsulated by the class;
- Open-closed states that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification;
- Liskov substitution states that the inherited class should complement, not replace, the behavior of the base class;
- Interface segregation states that no client should be forced to depend on methods it does not use;
- Dependency inversion says that programmer should work at the interface level and not at the implementation level.
When applied together, these principles help a developer create code that is easy to maintain and extend over time.
Law of Demeter
The main idea of this principle is to divide the areas of responsibilities between classes and encapsulate the logic inside the class, method or structure. From this principle we can highlight several recommendations:
- Classes or entities should be independent
- Need to try to reduce the number of connections between different classes(aka coupling)
- Related classes should be in the same module/package/directory (aka cohesion)
By following this principle, the application becomes more flexible, understandable and maintainable.
Fellow developers let’s be engineers! Let’s think about design and build robust and well-implemented systems, rather than growing organic monsters. Listed principles are highly correlated and connected in there essence. Of course, I didn't create them, but a small reminder does not hurt, at least my memory is definitely not perfect.