接口隔离原则背后的原因是什么?
接口隔离原则 (ISP) 指出,许多客户端特定接口比一个通用接口更好。 为什么这很重要?
The Interface Segregation Principle (ISP) says that many client specific interfaces are better than one general purpose interface. Why is this important?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
ISP 很重要。
ISP 的基本思想:客户端不应该被迫依赖它不使用的方法。
这个原则似乎更符合逻辑。 理想情况下,客户端不应实现客户端不使用的方法。
请参阅以下SE问题的代码示例:
接口隔离原则-程序到一个接口
优点:
灵活性:在没有 ISP 的情况下,您有一个通用 FAT 接口和许多实现它的类。 假设您有 1 个接口和 50 个类。 如果接口发生变化,所有 50 个类都必须更改其实现。
使用 ISP,您可以将通用 FAT 接口划分为细粒度的小接口。 如果小粒度接口发生变化,只有实现该接口的类会受到影响。
可维护性和易用性:由于更改仅限于细粒度接口而不是通用 FACT 接口,因此代码维护更容易。 不相关的代码不再是实现类的一部分。
ISP is important.
Basic idea of ISP : Client should not be forced to depend on methods it does not use.
This principle seems to be more logical. Ideally client should not implement the methods, which are not used by the client.
Refer to below SE question for code example:
Interface Segregation Principle- Program to an interface
Advantages:
Flexibility : In absence of ISP, you have one Generic FAT interface and many classes implementing it. Assume that you had 1 interface and 50 classes. If there is a change in interface, all 50 classes have to change their implementation.
With ISP, you will divide generic FAT interface into fine granular small interfaces. If there is a change in small granular interface, only the classes implementing that interface will be affected.
Maintainability and Ease of use: Since changes are limited to fine granular interface instead of generic FACT interface, code maintenance is easier. Unrelated code is no longer part of implementation classes.
界面隔离是 SOLID 原则上的“I”,在深入研究第一个之前,让我们先解释一下后者的含义。
SOLID 可以被认为是专家提出的一组最佳实践和建议(意味着它们之前已经被证明),以便为我们如何设计应用程序提供可靠的基础。 这些实践致力于使我们的应用程序更易于维护、扩展、调整和扩展。
为什么我应该关心 SOLID 编程?
首先,你必须意识到你不会永远停留在原地。 如果我们使用标准和众所周知的架构,我们可以确定我们的代码将很容易被我们之后的其他开发人员维护,并且我确信您不会想要处理修复没有的代码的任务。没有应用任何已知的方法,因为它很难理解。
接口隔离原则。
知道我们知道SOLID原则是什么,我们就可以更详细地了解接口隔离原则,但是接口隔离到底说了什么?
这意味着有时我们倾向于使用很多方法来创建接口,这在一定程度上可能是好的,但是这很容易被滥用,并且我们最终可能会得到实现空方法或无用方法的类,这当然给我们的应用程序添加额外的代码和负担。
想象一下,您在单个接口中声明了很多方法,如果您喜欢视觉辅助,那么一个正在实现接口的类,但实际上需要它的几个方法,它看起来像这样:
另一方面,如果您正确应用接口隔离并将接口拆分为较小的子集,您可以确保实现仅需要的接口:
< img src="https://i.sstatic.net/M0eWu.png" alt="在此处输入图像描述">
看! 好多了! 执行这一原则将使您具有低耦合性,这有助于更好的可维护性和对变化的高抵抗力。 因此,您可以在真正需要时真正利用接口的使用并实现方法。
现在让我们看一个不太抽象的例子,假设你声明了一个名为Reportable的接口
,并且你有一个客户端,只会以Excel格式导出一些数据,你可以实现该接口,但你只需要实现excel方法吗? 答案是否定的,即使您不打算使用它们,您也必须为所有方法编写实现代码,这可能会导致大量垃圾代码,从而使代码难以维护。
记住保持简单并且不要重复自己,你会发现你已经在不知不觉中使用了这个原则。
The interface segregation is the “I” on the SOLID principle, before digging too deep with the first, let’s explain what’s does the latter mean.
SOLID can be considered a set of best practices and recommendations made by experts (meaning they have been proved before) in order to provide a reliable foundation in how we design applications. These practices strive to make easier to maintain, extend, adapt and scale our applications.
Why should I care about SOLID programming?
First of all, you have to realize you are not going to be forever where you are. If we use standards and well known architectures, we can be sure that our code will be easy to maintain by other developers that come after us, and I’m sure you wouldn’t want to deal with the task of fixing a code that didn’t applied any known methodology as it would be very hard to understand it.
The interface segregation principle.
Know that we know what the SOLID principles are we can get into more detail about the Interface Segregation principle, but what exactly does the interface segregation says?
This means that sometimes we tend to make interfaces with a lot of methods, which can be good to an extent, however this can easily abused, and we can end up with classes that implement empty or useless methods which of course adds extra code and burden to our apps.
Imagine you are declaring a lot of methods in single interface, if you like visual aids a class that is implementing an interface but that is really needing a couple of methods of it would look like this:
In the other hand, if you properly apply the interface segregation and split your interface in smaller subsets you can me sure to implement those that are only needed:
See! Is way better! Enforcing this principle will allow you to have low coupling which aids to a better maintainability and high resistance to changes. So you can really leverage the usage of interfaces and implementing the methods when you really should.
Now let’s review a less abstract example, say you declared an interface called Reportable
And you have a client that will only to export some data in Excel format, you can implement the interface, but would you only have to implement the excel method? The answer is no, you will have to code the implementation for all the methods even if you are not going to use them, this can cause a lot of junk code hence making the code hard to maintain..
Remember keep it simple and don’t repeat yourself and you will find that you are already using this principle without knowing.
ISP 声明:
ISP 涉及重要特征 - 内聚 和 耦合。
理想情况下,您的组件必须是高度定制的。 它提高了代码的健壮性和可维护性。
实施 ISP 可为您带来以下好处:
如果你想了解更多关于软件设计原理的知识, 获取一份副本
敏捷软件开发、原则、模式和实践一书。
ISP states that:
ISP relates to important characteristics - cohesion and coupling.
Ideally your components must be highly tailored. It improves code robustness and maintainability.
Enforcing ISP gives you following bonuses:
If you want to learn more about software design principles, get a copy
of Agile Software Development, Principles, Patterns, and Practices book.
这一原则主要有两个目的:
使代码更具可读性和可管理性。
促进类的单一责任(高内聚)。 当然,为什么一个类应该有一个没有行为影响的方法呢? 为什么不直接删除它呢。 这就是 ISP 的意义
设计人员在关注 ISP 时必须问几个问题:
为了进一步讨论这一点,我还必须补充一点,这一原则是从最严格的意义上来说,这不是一个“原则”,因为在某些情况下,将 ISP 应用到设计中,不但不会提高可读性,反而可能使对象结构变得不可读,并充斥着不必要的代码。
您可以在 java.awt.event 包中很好地观察到这一点,
更多内容请参见我的博客:http://design-principle-pattern.blogspot.in/2013/12/interface-segregation-principle.html
This principle primarily serves twin purposes
To make the code more readable and manageable.
Promotes single responsibility for classes ( high cohesion ). Ofcourse why should a class have a method that has no behavioural impact ? Why not just remove it. Thats what ISP is about
There are few questions that a designer must ask with concerns to ISP
To take this discussion further, I must also add that this principle isn't a 'principle' in the strictest sense, because under certain circumstances, applying ISP to the design, instead of promoting readability, might make the object structure unreadable and cluttered with unnecessary code.
You may well observe this in the java.awt.event package
More at my blog: http://design-principle-pattern.blogspot.in/2013/12/interface-segregation-principle.html
原因之一是,拥有许多接口且每个接口的方法数量最少,可以更轻松地实现每个接口并正确实现它们。 大的界面可能会不守规矩。 此外,在场景中使用集中接口使代码更易于维护,因为您可以看到正在使用对象的哪个方面(例如,IComparable 接口让您知道该对象仅用于给定场景中的比较)。
One reason is that having many interfaces with a minimal amount of methods for each one makes it easier to implement each interface and to implement them correctly. A large interface can be unruly. Also, using a focused interface in a scenario makes the code more maintanable because you can see which facet of the object is being used (e.g., an IComparable interface lets you know that the object is only being used for comparisons in the given scenario).
关于该主题的 Robert Martin 的论文给出了很少被提及的解释:
如果两个类直接依赖于第三个类的两种不同方法,则前两个类中的任何一个的更改影响另一个类的可能性就会增加。
假设我们有三个类:
Red
、Green
和Blue
。Red
和Green
都依赖于Blue
,但各自依赖于不同的方法。 这意味着Red
依赖于Blue
的一种方法,但不使用另一种方法。 同样,Green
依赖于Blue
,但仅使用一种方法,而不使用另一种方法。违反原则的是
Red
和Green
,因为它们都依赖于一个类 -Blue
- 但不 至少使用其中一种方法。这可能会产生什么问题?
Red
,并且还更改Blue
以适应Red
的需求。Blue
中Green
所依赖的特定方法,但尽管如此,Green
仍依赖于Blue
我更改了蓝色
,这仍然会影响绿色
。Red
的更改有可能影响Blue
,因为它们导致我更改了两者都依赖的类。这就是“向后的力量”。 我们有时会因为客户的需要而更改课程。 如果该类有不同的客户使用它来做不同的事情,我们就有影响他们的风险。
如上所述,接口隔离原则的简单定义是:
结合这一点和 Robert Martin 论文中的上述观点,很明显,许多对 ISP 的解释实际上是在谈论其他原则。
如果我们谷歌“接口隔离”,大多数包含代码示例的顶级结果都展示了没有完全实现接口的类,这不是 ISP 的重点。 有些人甚至错误地重申了这一原则:
……但这不是原则。 定义文件提到这些担忧是违反 ISP 的副作用,但指出它们是违反里氏替换的。
更重要的是,客户端不应该实现它的方法不使用甚至没有意义。 接口的客户端不实现他们使用或不使用的方法 - 他们使用它的方法。
List
的客户端不实现List
的方法和属性。 它调用List
的方法和属性。我并不是要夸大地引用这篇论文,就好像它是圣书或其他什么东西一样。 但是,如果我们要使用文章中描述的原理的名称(文章本身的名称),那么我们还应该考虑该文章中包含的实际定义和解释。
Robert Martin's paper on the subject gives an explanation that's mentioned less often:
If two classes depend directly on two different methods of a third class, it increases the likelihood that changes to either of the first two classes will affect the other.
Suppose we have three classes:
Red
,Green
, andBlue
.Red
andGreen
both dependBlue
, but each depends on a different method. That means thatRed
depends on one method ofBlue
but doesn't use the other method. Likewise,Green
depends onBlue
, but only uses one method, not the other.The violation of the principle is in
Red
andGreen
because each depends on a class -Blue
- but doesn't use at least one of its methods.What problem does this potentially create?
Red
, and I also changeBlue
to accommodate the needs ofRed
.Blue
thatGreen
depends on, but nonetheless,Green
depends onBlue
and I have changedBlue
, which could still impactGreen
.Red
have the potential to impactBlue
because they've led me to change a class that both depend on.That's the "backwards force." We sometimes change a class because of the needs of its clients. If that class has different clients that use it for different things, we risk impacting them.
As stated, the simple definition of the Interface Segregation Principle is:
Between that and the above point from Robert Martin's paper, it's apparent that many explanations of the ISP are in fact talking about other principles.
If we Google "interface segregation", most of the top results that include code samples demonstrate classes that don't fully implement interfaces, which is not the point of the ISP. Some even incorrectly restate the principle:
...but that is not the principle. The defining paper mentions such concerns as a side-effect of violating the ISP, but indicates that they are Liskov Substitution violations.
What's more, to say that a client should not implement methods it does not use doesn't even make sense. The clients of an interface do not implement the methods they use or do not use - they consume its methods. A client of
List<E>
does not implement the methods and properties ofList<E>
. It calls the methods and properties ofList<E>
.I don't mean to pompously cite the paper as if it's holy writ or something. But if we're going to use the name of the principle described in the article (the name of the article itself) then we should also consider the actual definition and explanation contained in that article.
它简化了任何一个客户端将使用的接口,并消除了他们可能在不需要的接口部分上开发的依赖关系。
It simplifies the interface that any one client will use and removes dependencies that they might otherwise develop on parts of the interface that they don't need.