Why should we place interfaces with classes that u

2019-04-06 20:15发布

问题:

I was going through an article by Robert C. Martin and at one place he gave a example like this:

The first image shows that there's a cyclic dependency between the two packages. To remove this dependency a new interface is added in the second image. B implements the interface and Y uses it. And Martin makes the following point:

Interfaces are very often included in the package that uses them, rather than in the package that implements them.

My question is, why should we arrange interfaces this way? What is the reasoning behind packaging interfaces this way? According to Common Closure Principle classes that change together should stay together. Is an interface closer to its implementer or its user, in terms of change???

回答1:

Technically, the user is no closer to the interface than the implementor. In terms of change both will need to change when the interface changes.

However, why would the interface change?

The user calls to an interface so it can be independent of whatever implementor is available. Therefore the definition of the interface is dictated by the needs of the user.

As the user dictates the definition of the interface, there is no point changing the interface if the user doesn't need it. An implementor requiring a change to the interface to accommodate the implementation should send up red flags. Why does it need more or different information from the user? What use is that to the user?

Also, the implementor "merely" depends on the interface in as much as it needs to provide implementations for each of the methods in the interface. But it is free to provide empty stubs, in essence delivering a NOP to its clients.

So, the user's needs drive changes to the interface and changes to the interface drive changes to the implementor(s). As such the user is functionally much closer to the interface than the implementor. Which makes a good case to declare the interface with the user and not the implementor.



回答2:

It should first be said that there's no one way to skin a cat.

This particular methodology is useful when splitting up a project up between multiple project teams or creating a system with decoupled sub-systems. The interface serves as a "contract" between two sub-systems. By the placing the interface on "their turf", the consuming party has a better guarantee that the interface will remain unchanged, unless the implementing party contacts the consuming party to request such a change.



回答3:

Usually we use interfaces as a protocol between a server and a client so that the client knows what services are available but there's a side effect for this approach , the client will be dependent to the server and therefore if something changed in server side that affects the given interface the client should change too. So there's this principle among the SOLID principles , invented by Robert C. Martin, and that's "Dependency Inversion Principle" or "DIP" , that as it name implies says we should invert the dependency between client and server in order to avoid client changes in future.In this approach client says what it's going to need via an interface and server should implement it to serve what it needs, therefore no changes in server side make us to change the client.



回答4:

There's no reason to implement an interface until there's something that needs it. YAGNI.



回答5:

This is an issue of resolving cyclic dependencies between components AB and XY. None can be compiled without the other. AB is referencing XY and XY is referencing AB.

Robert C. Martin is appying the InversinOfControl pattern to resolve this

Now XY is referencing ABInterface. ABInterface does not need to know XY at all.

Your are right, this violates cohesion (you called it Common Closure Principle)

It also contradicts the KeepItSimple principle. The simplest solution would have only one monolitic component ABXY that is much harder to maintain.