Agile Software Development: principles, patterns and practices--the 12th ISP: The principle of interface isolation

Source: Internet
Author: User

12th ISP: Interface Isolation principle

Client programs should not be forced to rely on methods that are not used.

This principle is used to deal with the shortcomings of the "fat" interface. If the interface of a class is not introverted, it means that the class has a "fat" interface. In other words, the "fat" interface of a class can be decomposed into multiple sets of methods. Each group of methods serves a different set of client programs. In this way, some client programs can use a set of member functions, while other client programs can use the member functions of other groups.

ISPs admit that some objects do require a non-reserved interface, but ISPs recommend that customers should not see them as a single class presence. Instead, the client program should see multiple abstract base classes with a restrained interface.


12.1 Interface Contamination

If the subclass's interface has a method that the subclass does not need, it says that the interface is contaminated. Adding a method to an interface is only a benefit to one of its subclasses. If this is the case, then each time the subclass needs a new method, the method is added to the base class. This will further contaminate the interface of its base class and make it "fat".

Each time a method is added to a base class, the method must be implemented (or a default implementation is defined) in the derived class. In fact, a specific related practice that allows derived classes to implement these methods is to combine these interfaces into a single base class and provide a degenerate implementation of the methods in the interface in this base class. However, this practice violates the LSP and can lead to problems with maintenance and reuse.


12.2 Separating the customer is the separation interface

Client programs should not be forced to rely on methods that are not used. If customers are forced to rely on methods that they do not use, then these client programs face changes due to changes in these unused methods. This inadvertently results in a coupling between all client programs. In other words, if a client program relies on a class that contains a method that it does not use, but other client programs use that method, the client program is affected when other client programs require this class to change. We want to avoid this coupling as much as possible, so we want to classify the interfaces.


Class 12.3 Interface and Object interface

The client of an object does not have to access it through the interface of the object, or it can be accessed through a delegate or through the base class of the object.


12.3.1 using a delegate to detach an interface

The "delegation" here is not the delegate of the "delegate type", which is easy to produce ambiguity in the original translation. In fact, the adapter is used to decouple the client program and interface.

However, the solution is somewhat less elegant. Every time you want to register a request, you have to create a new object.


12.3.2 using multiple inheritance to detach interfaces

Usually I will choose this solution first. The adapter scheme is used only if the conversion made by the adapter object is necessary, or when different transformations are required.


Example of 12.4 ATM user interface

ATM (cash machine) requires a very flexible interface. Its output information needs to be translated into different languages. The output information may be displayed on the screen, or in a Braille writing pad, or through a speech synthesizer. This requirement can be achieved by creating an abstract class:

It is also possible to encapsulate different transactions (storage, withdrawals, transfers) performed by each ATM as derived classes of class transaction:

Note that this is exactly what the LSP tells me we should avoid. The way the UI is used by each office, and no other action classes are used, so changes to any one of the transaction's derived classes will force a corresponding change to the UI, which also affects all other transaction derived classes and all other classes that depend on the UI interface. This design has rigidity and fragility.

In this case, the ATM UI interface needs to be categorized:

Thus, each time a new derived class of the transaction class is created, the abstract interface UI needs to add a corresponding base class, and therefore the UI interface and all its derived classes must be changed. However, these classes are not widely used. In fact, they may be used only by main or by processes that start the system and create specific UI instances. As a result, the impact of adding new UI base classes is minimized.

See the following code:

 Public Interfacetransaction{voidExecute ();} Public Interfacedepositui{voidrequestdepositamount ();} Public classdeposittransaction:transaction{Privatedepositui Depositui;  Publicdeposittransaction (Depositui UI) {Depositui=UI; }     Public Virtual voidExecute () {/*Code*/Depositui.requestdepositamount (); /*Code*/    }} Public Interfacewithdrawalui{voidrequestwithdrawalamount ();} Public classwithdrawaltransaction:transaction{PrivateWithdrawalui Withdrawalui;  Publicwithdrawaltransaction (Withdrawalui UI) {Withdrawalui=UI; }     Public Virtual voidExecute () {/*Code*/Withdrawalui.requestwithdrawalamount (); /*Code*/    }} Public Interfacetransferui{voidrequesttransferamount ();} Public classtransfertransaction:transaction{PrivateTransferui Transferui;  Publictransfertransaction (Transferui UI) {Transferui=UI; }     Public Virtual voidExecute () {/*Code*/Transferui.requesttransferamount (); /*Code*/    }} Public InterfaceUi:depositui, Withdrawalui, transferui{}

Each transaction must somehow be aware of its specific UI version. This problem is resolved by having each transaction pass a reference to its UI specific to it at the time of construction. This allows us to use the following code:

// Global object; void f () {    new  deposittransaction (Gui);}

While this is convenient, it also requires that each transaction have an integer corresponding to the reference member of the UI. In C #, a more tempting approach is to put all the UI components into a single class, as follows:

 Public classuiglobals{ Public StaticWithdrawalui withdrawal;  Public StaticDepositui Deposit;  Public StaticTransferui transfer; Staticuiglobals () {UI Lui=NewAtmui ();//Some UI ImplementationUiglobals.deposit =Lui; Uiglobals.withdrawal=Lui; Uiglobals.transfer=Lui; }}

However, this approach has a negative effect. That is, the Uiglobal class relies on Depositui, Withdrawalui, and Transferui. The Uiglobal class re-binds our disconnected interfaces.

Each principle must be applied with care and cannot be overused. If a class has hundreds of different interfaces, some of which are separated according to the client program, others are separated by version, then the class is hard to figure out, and this kind of hard-thinking is very frightening.


12.5 Conclusion
Fat classes can cause unhealthy and harmful coupling relationships between their client programs. When a client program asks for a change to the Fat class, it affects all other client programs. Therefore, client programs should rely solely on the methods they actually invoke. This goal can be achieved by decomposing the fat-like interface into multiple user-specific interfaces. Each client-specific interface declares only those functions that are called by its specific client or client group. The Fat class can then inherit all the client-specific interfaces and implement them. This relieves the dependencies between the client program and the methods that they do not call, and makes the client program independent of each other.

Excerpt from: "Agile Software Development: principles, patterns and Practices (C # Edition)" Robert C.martin Micah Martin

Reprint please specify the source:

Jesselzj
Source: http://jesselzj.cnblogs.com

Agile Software Development: principles, patterns and practices--the 12th ISP: The principle of interface isolation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.