【发布时间】:2019-05-03 16:28:01
【问题描述】:
上下文:
我是一名 Java 程序员,正在阅读 Bob 大叔敏捷软件开发。关于 ISP 接口隔离原则,有一个我理解为的论点:
让我们拥有:
interface Service {
function doA();
}
class ServiceImpl implements Service {...}
class ServiceClient {
// ServiceImpl is injected; eg either through constructor or setter
private Service service;
function useOnlyDoA() {
service.doA();
}
}
现在,如果接口服务发生变化,例如添加方法doB(),然后添加所有依赖类,例如ServiceClient 必须重新编译,即使他们不使用添加的方法! (真的吗??)
- Java 是这样吗?
- c++ 是这样吗?
- 对于其他哪些语言是正确的,对于哪些不是?
我坚信关于 java 如果ServiceClient 在包中,例如client.jar,接口Service在service.jar和ServiceImpl在impl.jar,那么client.jar如果不使用Service接口的新方法就不用重新编译重建,可以使用以及service.jar 和impl.jar 的新版本。在我看来,事情在java中是这样发展的。
它是其他语言,例如 c++ 还是其他一些语言?
可能在 c++ 中更多的东西被破坏了,例如 https://stackoverflow.com/a/4033900/1423685
说清楚:
我不是要重新编译实现更改接口的类(这很明显,它的类必须实现新添加的方法)。 但是我问我是否必须重新编译使用这个接口的类 ServiceClient,即使类没有使用新添加的方法。可能在 c++ BC 中发生更改,并且客户端确实必须重新编译,但在我看来,在 java 中不是。
编辑:
我在 java 中实现了一个测试。 4 罐:
- interface.jar - 包含接口
public interface Service - implementation.jar - 包含
public class ServiceImpl implements Service - 上面两个罐子变了
- 即使上面改变了,下面的两个罐子也没有改变
- interfaceclient.jar - 依赖于interface.jar,包含类
ClientOfService以Service作为构造函数参数,在doA()方法中使用此服务 - application.jar - 依赖于以上所有 jars。主方法中的 App 类创建 ServiceImpl 实例并将其作为 arg 传递给 ClientOfService 的构造函数,然后在 ClientOfService 上调用一个方法,该方法从 Service:
public static void main(String[] args) { Service service = new ServiceImpl(); ClientOfService clientOfService = new ClientOfService(service); System.out.println("App.main() :: calling clientOfService.doWorkCallingDoAFromService"); clientOfService.doWorkCallingDoAFromService(); System.out.println("App.main() :: end of main"); }调用方法 doA()
更改interface.jar和implementation.jar后App中的main运行成功(我添加了一些未使用的方法并删除了一个旧方法)。
所以挑战是如何改变接口(当然不改变doA() 方法声明)和实现来阻止它成功运行?可能吗?如果是这样,怎么做?
【问题讨论】:
-
请注意,ISP 不仅仅是重新编译。未使用的接口方法可能需要客户端不需要的传递依赖项。
标签: java c++ oop interface solid-principles