我同意,对接口进行编程是一种很好的做法。在大多数情况下,Java“接口”在这个意义上意味着语言构造接口,因此您可以编写接口和实现类,并且在大多数情况下使用接口而不是实现类。
我想知道这是否也是编写域模型的好习惯。因此,例如,如果您有一个域类Customer并且每个客户可能都有一个Orders列表,那么您通常还会编写接口ICustomer和IOrder。客户也会有一份IOrders而不是Orders的列表吗?或者你是否会在域模型中使用接口,只要它真的是由域驱动的,例如,你有至少两种不同类型的订单?换句话说,您是否会因为域模型中的技术需求而使用接口,或者仅当它真正适合于实际域时才使用接口?
答案 0 :(得分:26)
编写接口“只是因为”让我感到浪费时间和精力,更不用说违反了KISS原则。
当它们在表示相关类的常见行为时非常有用,我写它们,而不仅仅是一个花哨的头文件。
答案 1 :(得分:12)
不要过度设计您的系统。如果你发现你有几种类型的订单,并认为为Orders声明一个接口是合适的,而不是在需要时重构它。对于域模型,特定接口在开发生命周期内会发生很大变化的概率很高,所以很早就编写接口很有用。
答案 2 :(得分:8)
接口是隔离组件的绝佳方式,用于单元测试和一般依赖关系管理。说,我经常更喜欢抽象类,所以至少有一些常见的行为被卸载,而不是强迫接口带来的一些重复。现代IDE可以快速轻松地生成界面,因此它们不会 做很多工作: - )
答案 3 :(得分:5)
不,我只使用域对象上的接口来保持松散耦合。对我来说,使用接口开发自己的代码的主要方面是我可以在进行单元测试时轻松创建模拟。我没有看到模仿域对象的重点,因为它们没有服务层或DAO层类所具有的相同依赖性。
这当然不意味着偏离在域对象中使用接口。适当时使用。例如,最近我一直在开发一个webapp,其中不同类型的域对象对应于用户可以留下评论的永久链接页面。因此,每个域对象现在都实现了“可注释”接口。然后将所有基于注释的代码编程到Commentable接口而不是Domain Objects。
答案 4 :(得分:4)
我建议保持精益和敏捷 - 在你需要之前不要做任何事情,然后让IDE在你需要的时候为你做重构。
在IDEA / eclipse中,当你决定需要一个具体的类时,将它变成一个接口是非常微不足道的。
答案 5 :(得分:4)
实际上,这个问题是关于“针对接口编程”的常见误解的一个例子。
你知道,这个 是一个非常好的原则,但不意味着许多人认为它意味着什么!
“编程到一个接口,而不是一个实现”(来自GoF一书)意味着,并不是说你应该为所有事情创建单独的接口。如果您有一个ArrayList
对象,则将变量/ field / parameter / return类型声明为List
类型。然后客户端代码只处理接口类型。
在Joshua Bloch的“Effective Java”一书中,原则在“项目52:通过接口引用对象”中更清楚地表达出来。它甚至用粗体字母说:
通过类而不是类来引用对象是完全合适的 如果没有合适的接口,则接口。
对于单元测试,情况完全取决于所使用的模拟工具的功能。使用我自己的工具JMockit,我可以像使用接口和依赖注入的代码一样轻松地编写单元测试,就像使用从被测试代码中实例化的最终类的代码一样。
所以,对我来说,答案是:始终使用已存在的接口,但如果没有充分的理由,请避免创建新接口(并且 testability 本身不应该一个)。
答案 6 :(得分:2)
在需要之前编写接口(用于测试或架构)是一种过度杀伤力。
此外,手动编写界面是浪费时间。您可以使用Resharper的重构“Pull Members”让它在几秒钟内创建特定类的新界面。与IDE集成的其他重构工具也应该具有类似的功能。
答案 7 :(得分:1)
我通常只使用在较小项目上有意义的接口。但是,我的最新工作有一个大型项目,几乎每个域对象都有一个接口。它可能有点过头了,这肯定很烦人,但我们测试和使用Spring进行依赖注入排序的方式需要它。
答案 8 :(得分:1)
我们主要用Wicket,Spring和Hibernate编写Web应用程序,我们使用Spring Beans的接口,例如服务和DAO。对于这些类,接口完全有意义。但是我们也为每个域类使用接口,我认为这只是过度杀伤。
答案 9 :(得分:1)
即使您非常确定只有一个具体类型的模型对象,使用接口会使模拟和测试变得更容易(但是现在有一些框架可以帮助您自动生成模拟类,即使是具体的Java类 - Mockito,JTestR,Spring,Groovy ......)
但我更经常使用接口来提供服务,因为在测试过程中模拟它们更为重要,而对接口进行编程可以帮助你思考封装等内容。
答案 10 :(得分:1)
如果您将域类用于单元测试,那么编写域类的接口是有意义的。我们在单元测试中使用Mock对象。因此,如果您有一个域对象的接口,并且您的域对象本身尚未就绪,但您的客户端可以借助模拟对象测试其对接口的使用。
Intefaces还测试您的域模型的多个接口实现。所以,我不认为它总是矫枉过正。
答案 11 :(得分:1)
我认为针对接口编程的主要原因是可测试性。因此,对于域对象 - 只需坚持使用POJO或POC#Os :)等,即只是让您的类不添加任何特定的框架,以防止它们出现差异构建和运行时依赖性等等。 不过,为DAO创建接口是一个好主意。
答案 12 :(得分:1)
我们从一切中提取接口只是因为它有助于测试(模拟)和AOP之类的东西。 Eclipse可以自动执行此操作:Refactor-> Extract Interface。
如果您以后需要修改该类,可以使用Refactor-> Pull Up ...将您需要的方法提取到界面上。
答案 13 :(得分:1)
*我这样做是因为我需要它来创建我的域对象的代理。
答案 14 :(得分:0)
这是另一件要记住的事情,我已经参与其中,特别是对于生成的域和DAO对象。很多接口都太具体了。说很多域对象都有ID和状态字段,为什么它们不共享一个公共接口?这让我感到沮丧,这是一种不必要的扁平(继承智能)域模型。