What are the 10 OOP design principles

SOLID - The 5 principles for object-oriented software design

Stefan Dirschnabel May 2nd, 2018

When it comes to software design, the wheat is separated from the chaff. No framework, no tool in the world can replace the ability to design software in an engineering way. Get rid of the latest framework hype! Explore the SOLID principles with us in this six-part series of articles. Step by step we discover the depths of object-oriented software art together. We get to know the principles of software design and clean code development using practical examples. Liskov's principle of substitution gives us a first example.

Introductory example

SOLID, these are five principles for the design and development of maintainable software systems. Knowledge of and about these principles should be part of the foundation of every software developer. Do you still doubt whether you can benefit from the SOLID principles? Take a look at the following code example:

public static void CalculateArea (Rectanle rectangle) {rectangle.Height = 5; rectangle.Width = 10; var area = rectangle.Area (); Console.WriteLine (area); Console.ReadLine (); }

The method CalculateArea () is very easy. It calculates the area of ​​a rectangle by setting the height and width and then the method Area of the rectangle calls:

public class Rectanle {public virtual int Width {get; set; } public virtual int Height {get; set; } public int Area () {return Width * Height; }}

What result would you expect? This question is regularly answered with 50. As we can see, the method is Area () correctly implemented and multiplied height by width. The school math from fourth grade only allows 50 as a result. However, our example gives the result 100. 100? Impossible. How can that be? Since the previous code is obviously correct, the problem must lie elsewhere. Our CalculateAreaMethod is called like this:

public static void Main (string [] args) {var square = new Square (); CalculateArea (square); }

As we can see, a square will appear CalculateArea to hand over. CalculateArea expects a rectangle - and a square is a rectangle. From their microscopic point of view, it works CalculateArea-So method is correct. And also the Main-Routine has no error. However, when the width of the square is set, the height is also set:

public override int Width {get {return base.Width; } set {base.Width = value; base.Height = value; }}

Just before calling Area () so width and height are equal to ten. By the way, our square is derived from rectangle, so it doesn't even have to implement the method for calculating area:

public class Square: Rectanle {public override int Height {get {return base.Height; } set {base.Height = value; base.Width = value; }} public override int Width {get {return base.Width; } set {base.Width = value; base.Height = value; }}}

In this admittedly constructed, but also impressive example, the Liskov substitution principle [1] was violated - more on this in due course. The example is typical of the SOLID principles. From a microscopic point of view, a certain source code fragment seems correct. However, problems arise in interaction with other classes.

Why do we need the SOLID principles?

The Rectangle Square-Example has shown: Viewed individually, many parts of the program work without errors. Conceptual problems can arise with three classes.

Expandability

In larger software projects, there is a multitude of semantic or structural code units (components, libraries, classes, methods, etc.). It is the (sometimes complex) interaction of these code units that, if the design is incorrect, makes extensions difficult or even leads to errors that are difficult to diagnose. In order to develop future-proof and sustainable software products, you should therefore model your classes and their interaction in such a way that expansions can be carried out easily and without errors. The five SOLID principles give us important assistance here. These five principles are:

  • Single Responsibility Principle (SRP)
  • Open Closed Principle (OCP)
  • Liskov Substitution Principle (LSP)
  • Interface Segregation Principle (ISP)
  • Dependency Inversion Principle (DIP) (* explanation in next article)

Many of the SOLID principles deal with aspects of aggregation and class composition. The sensible use of inheritance, or its resolution through composition, is an important aspect of the SOLID principles.

Reusability

The reusability of program code is often equated with a simple extract method refactoring. However, this addresses reusability on a level with a lot of details. The real reusability of a domain-specific aspect can be promoted, for example, by the Open Closed Principle.

Maintainability

If changes or error corrections are difficult to make, the software system is said to be poorly maintainable. If the implementation of a new user story influences a technically separate user story and thus extensions cannot be carried out in isolation, the maintainability of the program is already influenced.

SOLID helps to reduce such side effects. You should also consider: The SOLID principles cannot work miracles on a technical level. The SOLID principles are also not a panacea when a system suffers from major architectural problems. However, the SOLID principles help to model the technical requirements of your system better (more extensible and thus also more maintainable) by defining principles that developers can use to model classes.

Intelligibility and understanding

Software doesn't always have to be complicated. The SOLID principles help you to make your program code simpler. You contribute to an efficient and understandable handling of technical details and thus place the focus on the subject matter that is important to you. As you will see in the following articles, comprehensibility is automatically a consequence of extensibility and reusability. Many technologies and methodologies of object-oriented programming - such as design patterns or dependency injection (not to be confused with the dependency inversion principle) - are based on the SOLID principles or are promoted through their understanding.

SOLID agility

Do you develop according to an agile process model such as Scrum? Then the SOLID principles gain additional weight. With classic process models such as the waterfall or the V-model, the complete software architecture and a detailed software design are specified first. In theory, expansions should therefore be less frequent than with agile process models (this can also apply to smaller projects).

In very simplified terms, agility means "reacting flexibly and quickly to changed requirements". Agile processes thrive on iterative product development and therefore place increased demands on the expandability of the software model. The software product is expanded with each new iteration. It is not for nothing that Uncle Bob's SOLID principles are called the "Agile Principles of Object Oriented Software" [2]. The SOLID principles create the basis for later extensions and also meet the YAGNI principle (You Aren‘t Gonna Need It). With SOLID you do not create any unnecessary functionality, but provide expansion options through a well thought-out class design.

Software should be as complex as necessary, but as simple as possible.

During our many years of activity, it has been shown that design errors can have a massive impact after only half a man-year of development and can reduce productivity to a minimum. Knowledge of and about the SOLID principles should therefore be part of the basic training of every software developer.

Knowledge for your software quality

After this brief introduction, we will explain all SOLID principles to you in the next five articles using a coherent example. A stereo system serves as the basis for our code example. In each article we identify weaknesses in the software design and suggest a solution. Bit by bit we are getting closer and closer to an expandable and maintainable software solution.

A class diagram illustrates the most important aspects of our example very well:

As with a real stereo system, our stereo system also offers the user various options for interaction: Medium play or pause, stop, (medium) forwards or backwards and change volume. A controller class takes this user input from a user interface. The controller then controls various audio sources (cassette, CD, radio). The controller also allows switching between audio sources by connecting the audio stream supplied by a medium to the loudspeaker.

Conclusion

Even when implementing small software projects, the interaction of several classes can become a major obstacle. Experience and knowledge of the SOLID principles provide a remedy. Software doesn't have to be complicated. At BinaryGears we have even made the simplicity of software our company slogan: Software made simple. Software should be as complex as necessary, but as simple as possible. The SOLID principles help you to design complexity in an uncomplicated manner.

The knowledge imparted in our next articles allows you to benefit from a number of advantages: The SOLID principles make extensions easy, the reusability of software parts improved and productive software development possible in the first place. The SOLID principles fit perfectly with agile processes and lay the foundation for iterative product development.

In the next article, you will learn one possible implementation of the stereo system example and one of the most important principles in object-oriented design: the Dependency Inversion Principle. We recommend: Read all of the following articles, as the various SOLID principles are interrelated. Push your skills and become a software design guru!

Read the article on the Dependency Inversion Principle here

Stefan Dirschnabel

Stefan Dirschnabel has been a software architect, trainer and consultant for many years, specializing in Microsoft.Net and the web. His focus is clean code development and advice on a clean development process.
>> Read more
You might also be interested in