接口隔离原则背后的原因是什么?

发布于 2024-07-05 20:08:42 字数 52 浏览 11 评论 0原文

接口隔离原则 (ISP) 指出,许多客户端特定接口比一个通用接口更好。 为什么这很重要?

The Interface Segregation Principle (ISP) says that many client specific interfaces are better than one general purpose interface. Why is this important?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

疯到世界奔溃 2024-07-12 20:08:42

ISP 很重要。

ISP 的基本思想:客户端不应该被迫依赖它不使用的方法。

这个原则似乎更符合逻辑。 理想情况下,客户端不应实现客户端不使用的方法。

请参阅以下SE问题的代码示例:

接口隔离原则-程序到一个接口

优点:

  1. 灵活性:在没有 ISP 的情况下,您有一个通用 FAT 接口和许多实现它的类。 假设您有 1 个接口和 50 个类。 如果接口发生变化,所有 50 个类都必须更改其实现。

    使用 ISP,您可以将通用 FAT 接口划分为细粒度的小接口。 如果小粒度接口发生变化,只有实现该接口的类会受到影响。

  2. 可维护性和易用性:由于更改仅限于细粒度接口而不是通用 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:

  1. 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.

  2. 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.

蓝天 2024-07-12 20:08:42

界面隔离是 SOLID 原则上的“I”,在深入研究第一个之前,让我们先解释一下后者的含义。

SOLID 可以被认为是专家提出的一组最佳实践和建议(意味着它们之前已经被证明),以便为我们如何设计应用程序提供可靠的基础。 这些实践致力于使我们的应用程序更易于维护、扩展、调整和扩展。

为什么我应该关心 SOLID 编程?

首先,你必须意识到你不会永远停留在原地。 如果我们使用标准和众所周知的架构,我们可以确定我们的代码将很容易被我们之后的其他开发人员维护,并且我确信您不会想要处理修复没有的代码的任务。没有应用任何已知的方法,因为它很难理解。

接口隔离原则。

知道我们知道SOLID原则是什么,我们就可以更详细地了解接口隔离原则,但是接口隔离到底说了什么?

“不应强迫客户实施不必要的方法
他们不会使用”

这意味着有时我们倾向于使用很多方法来创建接口,这在一定程度上可能是好的,但是这很容易被滥用,并且我们最终可能会得到实现空方法或无用方法的类,这当然给我们的应用程序添加额外的代码和负担。
想象一下,您在单个接口中声明了很多方法,如果您喜欢视觉辅助,那么一个正在实现接口的类,但实际上需要它的几个方法,它看起来像这样:

在此处输入图像描述

另一方面,如果您正确应用接口隔离并将接口拆分为较小的子集,您可以确保实现仅需要的接口:

< img src="https://i.sstatic.net/M0eWu.png" alt="在此处输入图像描述">

看! 好多了! 执行这一原则将使您具有低耦合性,这有助于更好的可维护性和对变化的高抵抗力。 因此,您可以在真正需要时真正利用接口的使用并实现方法。
现在让我们看一个不太抽象的例子,假设你声明了一个名为Reportable的接口

public interface Reportable {

        void printPDF();
        void printWord();
        void printExcel();
        void printPPT();
        void printHTML();


}

,并且你有一个客户端,只会以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?

“Clients should not be forced to implement unnecessary methods which
they will not use”

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:

enter image description here

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:

enter image description here

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

public interface Reportable {

        void printPDF();
        void printWord();
        void printExcel();
        void printPPT();
        void printHTML();


}

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.

北方。的韩爷 2024-07-12 20:08:42

ISP 声明:

不应强迫客户依赖
他们不使用的方法。

ISP 涉及重要特征 - 内聚耦合
理想情况下,您的组件必须是高度定制的。 它提高了代码的健壮性和可维护性。

实施 ISP 可为您带来以下好处:

  • 凝聚力 - 更好的可理解性、稳健性
  • 耦合 - 更好的可维护性,高抗变化能力

如果你想了解更多关于软件设计原理的知识, 获取一份副本
敏捷软件开发、原则、模式和实践一书。

ISP states that:

Clients should not be forced to depend
on methods that they do not use.

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:

  • High cohesion - better understandability, robustness
  • Low coupling - better maintainability, high resistance to changes

If you want to learn more about software design principles, get a copy
of Agile Software Development, Principles, Patterns, and Practices book.

浮华 2024-07-12 20:08:42

这一原则主要有两个目的:

  • 使代码更具可读性和可管理性。

  • 促进类的单一责任(高内聚)。 当然,为什么一个类应该有一个没有行为影响的方法呢? 为什么不直接删除它呢。 这就是 ISP 的意义

设计人员在关注 ISP 时必须问几个问题:

  • 通过 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

  • What does one achieve with ISP
  • How to I analyse an already existing code for any ISP violations

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

牵你的手,一向走下去 2024-07-12 20:08:42

原因之一是,拥有许多接口且每个接口的方法数量最少,可以更轻松地实现每个接口并正确实现它们。 大的界面可能会不守规矩。 此外,在场景中使用集中接口使代码更易于维护,因为您可以看到正在使用对象的哪个方面(例如,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).

想挽留 2024-07-12 20:08:42

关于该主题的 Robert Martin 的论文给出了很少被提及的解释:

客户端在接口上施加的向后力。

如果两个类直接依赖于第三个类的两种不同方法,则前两个类中的任何一个的更改影响另一个类的可能性就会增加。

假设我们有三个类:RedGreenBlue

RedGreen 都依赖于 Blue,但各自依赖于不同的方法。 这意味着 Red 依赖于 Blue 的一种方法,但不使用另一种方法。 同样,Green 依赖于Blue,但仅使用一种方法,而不使用另一种方法。

违反原则的是 RedGreen,因为它们都依赖于一个类 - Blue - 但 至少使用其中一种方法。

这可能会产生什么问题?

  • 我需要更改Red,并且还更改Blue以适应Red的需求。
  • 我没有更改 BlueGreen 所依赖的特定方法,但尽管如此,Green 仍依赖于 Blue我更改了蓝色,这仍然会影响绿色
  • 因此,我对 Red 的更改有可能影响 Blue,因为它们导致我更改了两者都依赖的类。

这就是“向后的力量”。 我们有时会因为客户的需要而更改课程。 如果该类有不同的客户使用它来做不同的事情,我们就有影响他们的风险。

如上所述,接口隔离原则的简单定义是:

任何客户端都不应被迫依赖于它不使用的方法。

结合这一点和 Robert Martin 论文中的上述观点,很明显,许多对 ISP 的解释实际上是在谈论其他原则。

  • 具有大量方法的类或接口是不可取的,但这并不是专门因为 ISP 的原因。 他们可能违反单一责任。 但 ISP 违规并不在大接口或大类中,而是在依赖大接口的类中(如果它们不使用大接口的所有方法)。 如果他们使用所有方法,听起来仍然很混乱,但这与 ISP 无关。
  • 实现接口但对某些方法抛出异常的类是不好的,但这也不是 ISP。 ISP 是关于依赖接口的类,而不是实现接口的类。

如果我们谷歌“接口隔离”,大多数包含代码示例的顶级结果都展示了没有完全实现接口的类,这不是 ISP 的重点。 有些人甚至错误地重申了这一原则:

接口隔离原则规定客户端不应被迫实现他们不使用的接口

……但这不是原则。 定义文件提到这些担忧是违反 ISP 的副作用,但指出它们是违反里氏替换的。

此外,每次将新接口添加到基类时,该接口都必须
在派生类中实现(或允许默认)。 事实上,相关的做法是将这些接口作为 nil 虚函数而不是纯虚函数添加到基类中; 特别是这样派生类就不必承担实现它们的负担。 正如我们在本专栏的第二篇文章中了解到的,这种做法违反了里氏替换原则 (LSP),导致维护和可重用性问题。

更重要的是,客户端不应该实现它的方法不使用甚至没有意义。 接口的客户端不实现他们使用或不使用的方法 - 他们使用它的方法。 List 的客户端不实现 List 的方法和属性。 它调用List的方法和属性。

我并不是要夸大地引用这篇论文,就好像它是圣书或其他什么东西一样。 但是,如果我们要使用文章中描述的原理的名称(文章本身的名称),那么我们还应该考虑该文章中包含的实际定义和解释。

Robert Martin's paper on the subject gives an explanation that's mentioned less often:

The backwards force applied by clients upon interfaces.

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, and Blue.

Red and Green both depend Blue, but each depends on a different method. That means that Red depends on one method of Blue but doesn't use the other method. Likewise, Green depends on Blue, but only uses one method, not the other.

The violation of the principle is in Red and Green because each depends on a class - Blue - but doesn't use at least one of its methods.

What problem does this potentially create?

  • I need to change Red, and I also change Blue to accommodate the needs of Red.
  • I haven't changed the specific method within Blue that Green depends on, but nonetheless, Green depends on Blue and I have changed Blue, which could still impact Green.
  • Therefore, my changes to Red have the potential to impact Blue 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:

no client should be forced to depend on methods it does not use.

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.

  • Classes or interfaces with lots of methods are undesirable, but not specifically because of the ISP. They might violate Single Responsibility. But the ISP violation is not in the big interface or big class - it's in the classes that depend on on the big interface if they don't use all of its methods. If they use all of the methods it still sounds messy, but that has nothing to do with the ISP.
  • Classes that implement an interface but throw exceptions for certain methods are bad, but that's not the ISP, either. The ISP is about classes that depend on interfaces, not classes that implement interfaces.

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:

The Interface Segregation Principle states that clients should not be forced to implement interfaces they don't use

...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.

Moreover, each time a new interface is added to the base class, that interface must be
implemented (or allowed to default) in derived classes. Indeed, an associated practice is to add these interfaces to the base class as nil virtual functions rather than pure virtual functions; specifically so that derived classes are not burdened with the need to implement them. As we learned in the second article of this column, such a practice violates the Liskov Substitution Principle (LSP), leading to maintenance and reusability problems.

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 of List<E>. It calls the methods and properties of List<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.

神经暖 2024-07-12 20:08:42

它简化了任何一个客户端将使用的接口,并消除了他们可能在不需要的接口部分上开发的依赖关系。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文