Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money

The interface isolation principle is easy to understand if you look at the four principles I wrote earlier. It is somewhat similar to, but somewhat different from, the previous principles, as explained below. Do not know why, every time to learn some design principles, have a bit of impulse to masturbate code.

define

Interface isolation principle: Indicates that customers should not be forced to rely on methods or functions that are useless to them. The dependency of one class on another should be based on the smallest interface.

That is, the interface isolation principle requires programmers to try to break up bloated interfaces into smaller, more specific interfaces that contain only methods of interest to customers. Each class has its own dedicated interface, so don’t try to create a huge interface for all the classes that depend on it to implement.

For Swift, an interface is a protocol.

Focus on

The interface isolation principle is similar to the single responsibility principle in that it improves the cohesion of classes and reduces the coupling between them. The difference is that the single responsibility principle focuses on responsibilities and constraints on classes, and each class has its own responsibilities, while the interface isolation principle focuses on interfaces and focuses more on the isolation of interface dependencies.

The interface isolation principle aims to decouple systems so they can be easily refactored, changed, and redeployed.

So what should we do

  1. Each interface serves only the corresponding module and business.
  2. Only methods needed by the caller are provided, and methods not needed are not provided.
  3. When an interface is too large, we need to break it up into smaller interfaces.
  4. Each interface must assume independent roles. Do not assign different roles to one interface.
  5. Each project or product has selected environmental factors, and the criteria for interface resolution are different depending on the environment.

advantages

  1. Splitting a bloated interface into multiple small-grained interfaces can prevent the proliferation of external changes and improve the flexibility and maintainability of the system.

  2. Interface isolation improves system cohesion, reduces external interactions, and reduces system coupling.

  3. If the interface granularity is properly defined, the system stability can be guaranteed. However, if the definition is too small, it will lead to too many interfaces and complicate the design. If the definition is too large, flexibility is reduced and customization services cannot be provided, bringing unpredictable risks to the overall project.

  4. The use of multiple specialized interfaces also provides a hierarchy of objects, since the overall interface can be defined through interface inheritance.

  5. Reduces code redundancy in project engineering. A large interface that is too large often places a lot of unnecessary methods inside it, forcing redundant code to be designed when implementing the interface.

example

Let’s say we have an IT protocol that includes methods to write code, document, and manage.

/// IT protocol protocol ITProtocol {/// writeCode func writeCode() /// / writeCode func writeCode() /// /// /Copy the code

We have a coder class, and a project manager class, both following IT protocols.

// Programmer: ITProtocol { func writeCode() { print("writeCode") } func writeDocument() { print("writeDocument") } func manage() { Print ("not manage")}} // ProjectManager: ITProtocol { func writeCode() { print("not writeCode") } func writeDocument() { print("writeDocument") } func manage() {  print("manage") } }Copy the code

At this time we have a company class, companies want to hire employees, through the ITProtocol protocol to hire.

/// call // call // call // call // ITProtocol) { it.writeCode() it.writeDocument() it.manage() } }Copy the code

If the company wants to hire a coder, call the output code:

var company = Company()
var programmer = Programmer()
company.employ(it: programmer)
Copy the code

Output result:

writeCode

writeDocument

not manage

The company wants to hire a project manager, calling the output code:

var company = Company()
var projectManager = ProjectManager()
company.employ(it: projectManager)
Copy the code

Output result:

not writeCode

writeDocument

manage

On the surface we did, but we felt that some classes were outputting some unwanted methods. The Programmer class hired by the company does not need to manage the manage() method, and the ProjectManager class does not need to write the writeCode() code.

So in our OC, we can make what methods are optional, so that’s one way to do it. But if there are many ways, we still need to split the protocol.

We develop protocols to write code functionality. Management protocols are designed to manage functionality.

We can design it like this:

/// DevelopmentProtocol: // DevelopmentProtocol: Protocol ManageProtocol: ITProtocol {/// manage func ()}Copy the code

Got 3 protocols, abstract parent IT protocol, development protocol, management protocol. If we only need the development of the function in the development protocol to achieve, only management needs the function in the management to achieve, if the development management are used, we will be in the IT protocol to achieve.

In this case, we only need to implement our own functions as long as the Programmer follows the DevelopmentProtocol and the ProjectManager follows the ManageProtocol.

// Programmer: DevelopmentProtocol {func writeCode() {print("writeCode")} func writeDocument() {print("writeDocument")}} // Project Manager class ProjectManager: ManageProtocol { func writeDocument() { print("writeDocument") } func manage() { print("manage") } }Copy the code

We call the code:

var company = Company()
var programmer = Programmer()
company.employ(devIt: programmer)

var projectManager = ProjectManager()
company.employ(manageIt: projectManager)
Copy the code

Output result:

writeDocument

writeCode

writeDocument

manage

In this way, we are equivalent to our own class associating its own methods, and irrelevant methods are no longer associated. This is done by dividing the protocol into more detailed protocols, which is the interface isolation principle.

And, of course, there’s a little bit of refinement here, and the document function here is that if we do the same thing, we can do it this way

Extension ITProtocol {/// writeDocument() {print("writeDocument")}}Copy the code

It depends on the output content of the function. If the function of writing documents is available to everyone, but each implementation of this function is different, we will still implement it in the corresponding class.

Let’s say we have a TestClass class that has testA, testB, testC methods in it, and we have another class that calls a TestClass object, testA needs to be true, and then calls testB, If testB is true, call testC to return the result.

Class TestClass {func testA() -> Bool {true} func testB() -> Bool {true} func testC() -> String {" success "}} func test() { let t = TestClass() if t.testA() { if t.testB() { t.testC() } } }Copy the code

Is there any problem with this implementation? It seems there is no problem. In fact, I only want one result for this test method, and I don’t care about testA, testB, testC, so we can just encapsulate it in TestClass.

class TestClass { private func testA() -> Bool { true } private func testB() -> Bool { true } private func testC() -> String {" success "} func testABC () -> String {if testA() {if testB() {return testC()}} return ""}} func test() {let t = TestClass() t.testABC() }Copy the code

TestA, testB, and testC will not be exposed, but testA, testB, and testC will not be exposed.

This is to improve cohesion and reduce external interactions. Make the interface do the most with the fewest methods.

conclusion

We say we want to split interfaces as small and specific as possible, but there are limits. Refinement of interfaces can improve programming flexibility, but if it is too small, it can result in too many interfaces and complicate the design. So do it in moderation.

Please feel free to discuss in the comments section. The nuggets will draw 100 nuggets in the comments section after the diggnation project. See the event article for details