10 principles of object-oriented programming that every developer should be aware of

Original author: Javin Paul
  • Transfer


I quite often come across developers who have not heard about the principles of SOLID (we talked about them in detail here . - Transl.) Or object-oriented programming (OOP), or heard, but do not use them in practice. This article describes the benefits of OOP principles that help a developer in his daily work. Some of them are well known, others are not very well, so the article will be useful for both beginners and experienced programmers.

We remind you: for all readers of “Habr” - a discount of 10,000 rubles when registering for any Skillbox course using the “Habr” promo code.

Skillbox recommends: The Java Developer Online Education Course .

DRY (Don't Repeat Yourself)


A fairly 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 into a public constant.

This is necessary in order to simplify the code and make its support easier, which is the main task of OOP. Combining the union is also not worth it, because the same code will not pass verification with both OrderId and SSN.

Encapsulation of change


The software products of most companies are constantly evolving. So, you need to make changes to the code, it needs to be supported. You can simplify your life with encapsulation. This will allow more efficient testing and maintenance of the existing code base. Here is one example .

If you write in Java, then by default assign private methods and variables .

The principle of openness / closeness


This principle can be easily remembered by reading the following statement: "Software entities (classes, modules, functions, etc.) must be open for expansion, but closed for change." In practice, this means that they can allow you to change their behavior without changing the source code.

The principle is important when changes to the source code require revision, unit testing, and other procedures. Code that obeys the principle of openness / closeness does not change during expansion, so there are much 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 sections of the code that have a connection with the desired fragment.

By the way, openness-closedness is one of the principles of SOLID.

Single Responsibility Principle (SRP)


Another principle from the SOLID suite. He states that "there is only one reason leading to a change in class." A 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 serve only 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 connection between the two functions. Thus, if you change one of them, there is a great chance to spoil the second, associated with the first. And this means an increase in testing cycles in order to identify all problems in advance.

Dependency Inversion Principle (DIP)




The above is an example code where the AppManager depends on an EventLogWriter, which in turn is closely related to the AppManager. If you need another way to show a notification, be it push, SMS or email, you need to change the AppManager class.

The problem can be solved using DIP. So, instead of AppManager, we request an EventLogWriter, which will be introduced using the framework.

DIP allows you to easily replace individual modules with others, changing the dependency module. This makes it possible to change one module without affecting the rest.

Composition instead of inheritance


There are two main ways to reuse code - this is inheritance and composition, and each has its own advantages and disadvantages. The second is usually preferred because it is more flexible.

Composition allows you to change the behavior of a class at runtime by setting its properties. When implementing interfaces, polymorphism is used, which gives a more flexible implementation.

Even “Effective Java” by Joshua Bloch advises giving preference to composition rather than inheritance.

Barbara Lisk Substitution Principle (LSP)


Another principle from the SOLID toolkit. It states that subtypes must be replaceable for a supertype. That is, methods and functions that work with a superclass should be able to work with its subclasses without problems.

LSP is connected both with the principle of single responsibility, and with the principle of division of responsibility. If a class provides more functionality than a subclass, then the latter will not support some functions, violating this principle.

Here is a piece of code that contradicts the LSP.



The area (Rectangle r) method calculates the area of ​​the Rectangle. The program will crash after executing Square, since Square is not a Rectangle here. 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)


Another SOLID principle. According to him, 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 an interface is a difficult task, after completion of work, changing it without breaking anything will be a problem.

The advantage of the ISP principle in Java is that all methods must be implemented first, and only then can they be used by classes. Therefore, the principle makes it possible to reduce the number of methods.



Programming for an interface, not an implementation


Everything here is clear from the name. Application of this principle leads to the creation of flexible code that can work with any new interface implementation.

Use the interface type for variables, return types, or the type of the method argument. An example is the use of SuperClass, not SubClass.

That is:

List numbers = getNumbers ();

And not:

ArrayList numbers = getNumbers ();

Here is a practical implementation of what is said above.



Delegation principle


A common example is the equals () and hashCode () methods in Java. When it is required to compare two objects, this action is delegated to the corresponding class instead of the client.

An advantage of the principle is the absence of code duplication and a relatively simple change in behavior. It is also applicable to event delegation.



All these principles allow writing more flexible, beautiful and reliable code with high connectivity and low gear. Of course, the theory is good, but for the developer to really begin to 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:


Also popular now: