Chuyển đến nội dung chính

S.O.L.I.D Principles


These principles, when combined together, make it easy for a programmer to develop software that are easy to maintain and extend. They also make it easy for developers to avoid code smells, easily refactor code, and are also a part of the agile or adaptive software development.

Single Responsibility Principle

  • One class should have one and only one responsibility.
  • Write, maintain and change for one purpose.
  • Flexibility to make changes in the future without worrying the impacts of changes for another entity.
Example:
However, the logic of determining whether the employee is promoted due this year is actually not a responsibility which the employee own.
Generate employee report is not responsibility of the Employee.
→ Employee class should have the single responsibility of maintaining core attributes of an employee so we should write one different class for report generation, so that any change in report generation should not affect the ‘Employee’ class.

Open - Closed Principle

  • A class should be open for extension but closed for modification.
  • You can add new features through inheritance but should not change the existing classes.
Example: Now take the same ‘ReportGeneration’ class as an example of this principle.
too much ‘If’ clauses are there and if we want to introduce another new report type like ‘Excel’, then you need to write another ‘if’. This class should be open for extension but closed for modification. But how to do that!!
So if you want to introduce a new report type, then just inherit from ReportGeneration. So ReportGeneration is open for extension but closed for modification.

Liskovs Substitution Principle

  • Child class should not break parent class’s type definition and behavior. 
  • If the class that is extended is poorly done, your code should not be broken
Example: To illustrate this completely, we will go with a classic example because it is highly significant and easily understandable.
We start with a basic geometrical shape, a Rectangle. It is just a simple data object with setters and getters for width and height. 
In real life, in geometry, a square is a particular form of rectangle. So we could try to implement a Square class that extends a Rectangle class. It is frequently said that a child class is a parent class, and this expression also conforms to LSP, at least at first sight. 
But is a Square really a Rectangle in programming?
A square is a rectangle with equal width and height, and we could do a strange implementation like in the above example. We could overwrite both setters to set the height as well as the width. But how would that affect client code?
An exception is thrown to us when we run the test with an instance of Square().
So, our Square class is not a Rectangle after all. It breaks the laws of geometry. It fails and it violates the Liskov Substitution Principle.

Interface Segregation Principle

  • Any client should not be forced to use an interface which is irrelevant to it.
Example: You realize that most likely every view might need to be clicked on. Therefore, being a good Java citizen you create an interface called OnClickListener that is nested in the View class that looks like this:
I’m sure that looks vaguely familiar, right? :)
As time progresses you find out that you need a listener for long press event and double click event. The interface is still rather small so you decide to add another method to it. Can’t hurt anything, right?
This interface is becoming a problem – it’s becoming generic and polluted.
I want to attach a click listener to a button (Android app), so I write it up like this:
Those last two methods, onLongClick and onDoubleClick are not doing anything. Sure, we could put some code there, but what if I don’t need it? Most likely I’m only worried about a click, not the double click, not the long press.
The client should only have to implement interfaces that it needs and no more.

Dependence Inversion Principle

  • Not to write any tightly coupled code because that is a nightmare to maintain.
  • Depend on adstractions, not on concretions.
  • If a class depends on another class, then we need to change one class if something changes in that dependent class. We should always try to write loosely coupled class.
Example: 
Now Notification class totally depends on Email class, because it only sends one type of notification. If we want to introduce any other like SMS then? We need to change the notification system also. And this is called tightly coupled.  What can we do to make it loosely coupled?

So, SOLID principle will help us to write loosely coupled code which is highly maintainable and less error prone.

Nhận xét