This time I will bring you an analysis of the use cases of the PHP Interface Isolation Principle (ISP), and what are the precautions for using the PHP Interface Isolation Principle (ISP). The following is a practical case, let's take a look.
When designing an application, if a module contains multiple sub-modules, then we should be careful to abstract the module. Assuming that the module is implemented by a class, we can abstract the system into an interface. But when adding a new module extension, if the module to be added only contains some submodules of the original system, then the system will force us to implement all methods in the interface, and we will have to write some dumb methods. Such interfaces are called fat interfaces or polluted interfaces. Using such interfaces will introduce some inappropriate behaviors into the system. These inappropriate behaviors may lead to incorrect results and may also lead to a waste of resources.
1. Interface Segregation
The Interface Segregation Principle (ISP) states that clients should not be forced to implement something they do not know how to do The interface used should group the methods in the fat interface, and then replace it with multiple interfaces, each interface serving a submodule. Simply put, it is much better to use multiple specialized interfaces than a single interface.
The main points of ISP are as follows:
1) The dependence of one class on another class should be based on the smallest interface.
ISP can achieve the goal of not forcing customers (interface usage methods) to rely on methods they do not use. The implementation class of the interface should only present a single-responsibility role (following the SRP principle)
ISP can also reduce the mutual impact between customers---when a customer requires new responsibilities (requires changes) and forces the interface to change, the possibility of affecting other customer programs is minimal.
2) The client program should not rely on interface methods (functions) that it does not need.
The client program should depend on interface methods (functions) that it does not need. What does it depend on? Depends on the interface it requires. Provide whatever interface the client needs, and eliminate unnecessary interfaces. This requires refining the interface to ensure its purity.
For example, when inheriting, the subclass will inherit all available methods in the parent class; and some methods in the parent class may not be needed in the subclass. For example, ordinary employees and managers both inherit from the employee interface. Employees need to write work logs every day, but managers do not. Therefore, work logs cannot be used to block managers, that is, managers should not rely on the method of submitting work logs.
It can be seen that ISP and SRP have some overlap in concepts. In fact, many design patterns are conceptually overlapping, and it is even difficult to tell which design pattern a piece of code belongs to.
ISP emphasizes that the interface has as few commitments to the client as possible, and it must be specific. When the requirements of a certain client program change and force the interface to change, the possibility of affecting other client programs is small. This is actually a problem of interface pollution.
2. Pollution of the interface
Overly bloated interface design is pollution of the interface. The so-called interface pollution is to add unnecessary responsibilities to the interface. If the developer adds a new function to the interface just to reduce the number of interface implementation classes, this design will cause the interface to be continuously "polluted" and "fat" .
"Interface isolation" is actually the principle of customized service design. Use multiple inheritance of interfaces to combine different interfaces to provide external combination functions --- to achieve "services on demand".
The interface needs to be dismantled, but it cannot be dismantled too finely. There must be a standard, which is high cohesion. The interface should have some basic functions and can uniquely complete a basic task.
In practical applications, you will encounter the following problems: For example, if I need a DAO implementation that can adapt to multiple types of databases, then I should first implement an interface for database operations, which stipulates some databases Basic methods of operation, such as Connecting to the database, adding, deleting, modifying, checking, closing the database, etc. This is a minimally functional interface. For some methods that are unique to MySQL but do not exist in other databases or are of different nature, such as MySQL's pconnect method that may be used in PHP, other databases do not have the same concept as this method, so this method does not exist. It should appear in this basic interface, so what basic methods should this basic interface have? PDO has told you so.
PDO is an abstract database interface layer, which tells us what basic methods a basic database operation interface should implement. The interface is a high-level abstraction, so the methods in the interface should be universal, basic, and not easy to change.
There is another question, how should those unique methods be implemented? According to the ISP principle, these methods can exist in another interface, allowing this "heterogeneous" to implement both interfaces at the same time.
For interface pollution, you can consider these two processing methods:
Use delegation to separate interfaces.
Use multiple inheritance to separate interfaces.
In the delegation mode, two objects participate in processing the same request. The object accepting the request delegates the request to another object for processing, such as strategy mode, proxy mode, etc. The concept of delegation is applied in both.
Let’s take a look at the examples
Have you ever encountered a very “fat” interface?
For example: there is an interface related to animals, the code is as follows:
<?php interface Animal{ public function walk(); public function speak(); }
Dog is a specific implementation of this interface:
<?php require_once "animal.php"; class Dog implements Animal{ public function walk(){ echo "dogs can walk"; } public function speak(){ echo "dogs can speak"; } }
ok, now We want to create a fish that can swim, what should we do? We must modify the interface, which will also affect the implementation of the dog class, and fish also needs to implement the walk and speak methods, as shown in the following code:
Animal interface class:
<?php interface Animal{ public function walk(); public function speak(); public function swim(); }
dog class:
<?php require_once "animal.php"; class Dog implements Animal{ public function walk(){ echo "dogs can walk"; } public function speak(){ echo "dogs can speak"; } public function swim(){ } }
fish class:
<?php require_once "animal.php"; class Fish implements Animal{ public function walk(){ } public function speak(){ } public function swim(){ echo "fish can swim"; } }
At this time, the Animal interface class shows the characteristics of a "fat" interface. The so-called fat interface actually means that the interface defines methods that are not required by all implementation classes. Just like the Animal interface class, some animals cannot swim, some animals cannot walk, and some animals cannot fly. If these methods are written in an Animal interface class, then later expansion and maintenance will be a disaster.
So, how to solve the above problems?
It’s very simple, just refine the interface and split the Animal interface class into three interface classes:
animalCanWalk interface class:
<?php interface animalCanSpeak{ public function speak(); }
AnimalCanSwim interface class:
<?php interface AnimalCanSwim{ public function swim(); }
animalCanSpeak interface class:
<?php interface animalCanSpeak{ public function speak(); }
After defining these interface classes, the implementation of dog and fish will be much easier.
<?php require_once "animalCanSpeak.php"; require_once "animalCanWalk.php"; class Dog implements animalCanSpeak,animalCanWalk{ public function walk(){ echo "dogs can walk"; } public function speak(){ echo "dogs can speak"; } }
<?php require_once "animalCanSwim.php"; class Fish implements AnimalCanSwim{ public function swim(){ echo "fish can swim"; } }
To summarize :
The concept of Interface Segregation Principle (ISP): Use multiple specialized interfaces instead of a single total interface, that is, the client should not rely on Those interfaces it doesn't need.
When using the interface isolation principle, we need to pay attention to controlling the granularity of the interface. The interface cannot be too small. If it is too small, it will lead to a proliferation of interfaces in the system, which is not conducive to maintenance; the interface should not be too large or too small. A large interface will violate the interface isolation principle, have poor flexibility, and be very inconvenient to use. Generally speaking, the interface only needs to contain methods customized for a certain type of user, and clients should not be forced to rely on methods they do not use.
I believe you have mastered the method after reading the case in this article. For more exciting information, please pay attention to other related articles on the php Chinese website!
Recommended reading:
Detailed explanation of PHP dependency inversion case
Detailed explanation of the steps to create a Composer package in PHP
The above is the detailed content of PHP Interface Isolation Principle (ISP) use case analysis. For more information, please follow other related articles on the PHP Chinese website!