
I often see developers who have not heard about the principles of SOLID (we
talked about them in detail here - Per.) Or object-oriented programming (OOP), or heard, but do not use them in practice. This article describes the benefits of the principles of OOP, which help the developer in his daily work. Some of them are well known, others are not very good, so the article will be useful for both beginners and experienced programmers.
We remind: for all readers of "Habr" - a discount of 10,000 rubles when enrolling in any Skillbox course for the promo code "Habr".
Skillbox recommends: Educational online course "Java-developer" .
DRY (Don't Repeat Yourself)
Quite a simple principle, the essence of which is clear from the title: "Do not repeat." For the programmer, this means the need to avoid duplicate code, as well as the ability to use abstraction in the work.
')
If the code has two repeating sections, they should be combined into one method. If a hard-coded value is used more than once, it is worth converting it to a public constant.
This is necessary in order to simplify the code and make its support easier, which is the main task of OOP. You should not overuse the union either, since the same code will not pass the test with both OrderId and SSN.
Change encapsulation
Software products of most companies are constantly evolving. So, the code needs to be changed, it needs to be supported. You can simplify your life with encapsulation. This will allow you to more effectively test and maintain the existing code base.
Here is one example .
If you are writing in Java, then
by default assign private methods and variables .
Principle of openness / closeness
This principle can be easily remembered by reading the following statement: "Program entities (classes, modules, functions, etc.) should be open for expansion, but closed for change." In practice, this means that they can allow to change their behavior without changing the source code.
The principle is important when changes in the source code require its revision, unit testing and other procedures. The code that obeys the principle of openness / closeness does not change with the extension, so there are far fewer problems with it.
Here is an example of code that violates this principle.

If you need to change something in it, it will take a lot of time, since you will have to change all parts of the code that have a link to the desired fragment.
By the way, openness-closeness is one of the principles of SOLID.
The principle of sole responsibility (SRP)
Another principle from the SOLID set. It states that "there is only one reason leading to a change in class." The class solves only one problem. It may have several methods, but each of them is used only to solve a common problem. All methods and properties should only serve this.

The value of this principle is that it weakens the connection between the individual software component and the code. If you add more than one functionality to a class, this introduces a link between the two functions. Thus, if you change one of them, there is a great chance to spoil the second one related to the first one. This means an increase in testing cycles in order to identify all the problems in advance.
Principle of dependency inversion (DIP)

The above is a sample code where AppManager depends on an EventLogWriter, which, in turn, is closely related to AppManager. If you need another way to show the notification, be it push, SMS or email, you need to change the class AppManager.
The problem can be solved with DIP. So, instead of AppManager, we request an EventLogWriter, which will be entered using the framework.
DIP makes it possible to easily replace individual modules with others, changing the dependency module. This makes it possible to change one module without affecting the others.
Composition instead of inheritance

The main ways to reuse code two are inheritance and composition, and each has its own advantages and disadvantages. Usually preference is given to the second, since it is more flexible.
The composition allows you to change the behavior of the class at run time by setting its properties. When implementing interfaces, polymorphism is used, which gives a more flexible implementation.
Even “Effective Java” Joshua Bloch (Joshua Bloch) advises to prefer composition rather than inheritance.
Barbara Liskov (LSP) substitution principle
Another principle from the SOLID toolkit. It states that subtypes must be replaceable for the supertype. That is, the methods and functions that work with the superclass should be able to work with its subclasses without any problems.
LSP is associated with both the principle of shared responsibility and the principle of sharing responsibility. If a class provides more functionality than a subclass, then the latter will not support certain functions, violating this principle.
Here is a snippet of code that contradicts the LSP.

The area method (Rectangle r) calculates the Rectangle area. The program will fall after running Square, since Square here is not a Rectangle. According to the LSP principle, functions that use references to base classes should be able to use objects of derived classes without additional instructions.
This principle, which is a specific definition of a subtype, was proposed by Barbara Liskov in 1987 at a conference in the main report entitled “Data Abstraction and Hierarchy” - hence its name.
Interface Separation Principle (ISP)
The next principle is SOLID. According to it, an interface that is not used should not be implemented. Following this principle helps the system to remain flexible and suitable for refactoring when making changes to the logic of work.
Most often, this situation occurs when the interface contains several functionalities at once, and the client needs only one of them.
Since writing the interface is a difficult task, after completing the work, changing it without disturbing anything will be a problem.
The advantage of the ISP principle in Java is that you first need to implement all the methods, and only then can they be used by the classes. Therefore, the principle makes it possible to reduce the number of methods.

Programming for an interface, not an implementation
Here everything is clear from the name. The application of this principle leads to the creation of a flexible code that can work with any new interface implementation.
You should use the interface type for variables, return types, or the type of the method argument. An example is using SuperClass, not SubClass.
I.e:
List numbers = getNumbers ();But not:
ArrayList numbers = getNumbers ();Here is the practical implementation of what is stated above.

Delegation principle
A common example is the equals () and hashCode () methods in Java. When you want to compare two objects, this action is delegated to the appropriate class instead of the client.
The advantage of the principle is the absence of code duplication and relatively simple behavior change. It also applies to the delegation of events.

All these principles allow us to write more flexible, beautiful and reliable code with high connectivity and low gearing. Of course, the theory is good, but for the developer to really use the knowledge gained, practice is needed. The next step after mastering the principles of OOP can be the study of design patterns to solve common problems of software development.
Skillbox recommends: