In object oriented programming there are some rules which help to keep development less messy and maintenance of developed systems easier and cheaper. One of such set or rules are SOLID principles:
S – Single Responsibility Principle
O – Open-Closed Principle
L – Liskov Substitution Principle
I – Interface Segregation Principle
D – Dependency Inversion Principle
Single Responsibility Principle
Well, basically it means that a class should be responsible for a single task. It sounds more or less like one-method-class, and in fact it is. For instance, if you send some data to back end for processing, and there are several tasks needed to be done before the data is returned, all the tasks should be performed by separate classes. This is the main reason why simple plugins come with large amount of separate files/classes, where every one does a bit of job. It is not always a good idea to keep business complex logic scattered allover several classes. The remedy for this problem, especially for large projects, can be that you use dependency injection and interfaces – you use other classes single-task classes, or interfaces in side a “main” class.
Probably the best approach to a class which violates the Single Responsibility Principle is to find what is the class’ main task, and leave only the method responsible for the task, and all other methods outsource to external classes. Let’s say, we have User class which – except saving user data to database, also validates user data input. The data validation can easily be moved to separate class.
A class should be open for extension and closed for modification, which means that this way we can avoid editing/modify code. Usually, what we can do, is to use Interfaces, which can handle to-be-modified future functionality outside the main class.
Interfaces implemented by different classes should return the same type of value (arrays, OR integers, OR strings etc).
Interface Segregation Principle
Client must not be forced to implement interface that it doesn’t use – classes should know only what is needed to do a task. In practical terms it means, that interfaces have to be very specific, without any unnecessary contracts. So, many client specific interfaces are better than one general-purpose interface.
Let’s assume, that there is an interface with 3 methods. And some class implements that interface, BUT uses only 1 of the methods, because – for some reason – two other methods are not needed. Such situation violates the Interface Segregation Principle. Solution is to split methods between interfaces so that classes using the interfaces don’t violate the principle. And this is possible, rather easily, because a class can implement many interfaces, so in the worst case scenario we could have an interface with one method only. The rule of thumb is: avoid fat interfaces.
Dependency Inversion Principle
High level modules shouldn’t never depend on low level modules, instead both high and low level can depend on the same abstraction (and the abstraction – details of connection to a specific database for instance – can be located in an Interface). Or, in other words: class should depend on abstractions, not concretions.