SOLID is a term describing a collection of design principles for good code that was invented by Robert C. Martin, also known as Uncle Bob.
Single Responsibility Principle
Just because you can add everything you want into your class doesn’t mean that you should. Thinking in terms of responsibilities will help you design your application better. Ask yourself whether the logic you are introducing should live in this class or not. Using layers in your application helps a lot. Split big classes in smaller ones, and avoid god classes. Last but not least, write straightforward comments. If you start writing comments such as in this case, but if, except when, or, then you are doing it wrong.
You should make all member variables private by default. Write getters and setters only when you need them. I’ve already covered this point in a previous article, as the ninth rule of the Object Calisthenics is related to this principle.
Liskov Substitution Principle
Let’s take an example. A rectangle is a plane figure with four right angles. It has a width, and a height. Now, take a look at the following pseudo-code:
rect = new Rectangle();
rect.width = 10;
rect.height = 20;
assert 10 == rect.width
assert 20 == rect.height
We simply set a width and a height on a Rectangle instance, and then we assert that both properties are correct. So far, so good.
Now we can improve our definition by saying that a rectangle with four sides of equal length is called a square. A square is a rectangle so we can create aSquare class that extends the Rectangle one, and replace the first line above by the one below:
rect = new Square();
According to the definition of a square, its width is equal to its height. Can you spot the problem? The first assertion will fail because we had to change the behavior of the setters in the Square class to fit the definition. This is a violation of the Liskov Substitution Principle.
Interface Segregation Principle
Interface Segregation Principle or ISP states that many client-specific interfaces are better than one general-purpose interface. In other words, you should not have to implement methods that you don’t use. Enforcing ISP gives you low coupling, and high cohesion.
When talking about coupling, cohesion is often mentioned as well. High cohesion means to keep similar and related things together. The union of cohesion and coupling is orthogonal design. The idea is to keep your components focused and try to minimize the dependencies between them.
Note that this is similar to the Single Responsibility Principle. An interface is a contract that meets a need. It is ok to have a class that implements different interfaces, but be careful, don’t violate SRP.
Dependency Inversion Principle
Abstractions should not depend upon details;
Details should depend upon abstractions.
This principle could be rephrased as use the same level of abstraction at a given level. Interfaces should depend on other interfaces. Don’t add concrete classes to method signatures of an interface. However, use interfaces in your class methods.
Note that Dependency Inversion Principle is not the same as Dependency Injection. Dependency Injection is about how one object knows about another dependent object. In other words, it is about how one object acquires a dependency. On the other hand, DIP is about the level of abstraction. Also, a Dependency Injection Container is a way to auto-wire classes together. That does not mean you do Dependency Injection though. Look at the Service Locatorfor example.
Also, rather than working with classes that are tight coupled, use interfaces. This is called programming to the interface. This reduces dependency on implementation specifics and makes code more reusable. It also ensures that you can replace the implementation without violating the expectations of that interface, according to the Liskov Substitution Principle seen before.
As you probably noticed, avoiding tight coupling is the key. It is present in a lot of code, and if you start by focusing on fixing this alone, you will immediately start writing better code.
If I may leave you with only one piece of advice, that would be to use your brain. There are a lot of principles in software engineering. Even if you don’t understand all these principles, always think before writing code. Take the time to understand those that you don’t understand.
Honestly, writing SOLID code is not that hard.