针对接口编程:您是否为所有域类编写接口?

发布于 2024-07-05 16:25:35 字数 336 浏览 4 评论 0原文

我同意,针对接口进行编程是一种很好的做法。 在大多数情况下,Java 中的“接口”在这个意义上意味着语言构造接口,因此您编写一个接口和一个实现类,并且大多数时候您使用接口而不是实现类。

我想知道这是否也是编写领域模型的好习惯。 因此,例如,如果您有一个域类 Customer,并且每个客户可能有一个订单列表,那么您通常还会编写接口 ICustomer 和 IOrder。 客户还会有 IOrders 列表而不是 Orders 列表吗? 或者您是否会在域模型中使用接口,只有当它确实由域驱动时,例如您至少有两种不同类型的订单? 换句话说,您会仅因为领域模型中的技术需求而使用接口,还是仅在它确实适合实际领域时才使用接口?

I agree, that programming against interfaces is a good practice. In most cases in Java "interface" in this sense means the language construct interface, so that you write an interface and an implementation class and that you use the interface instead of the implementation class most of the time.

I wonder if this is a good practice for writing domain models as well. So, for example if you've got a domain class Customer and each customer may have a list of Orders, would you generally also write interfaces ICustomer and IOrder. And also would Customer have a list of IOrders instead of Orders? Or would you use interfaces in the domain model, only if it is really driven by the domain, e.g. you've got at least two different types of Orders? In other words, would you use interfaces because of only technical needs in the domain model, or only when it is really appropriate with respect to the actual domain?

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

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

发布评论

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

评论(15

苍景流年 2024-07-12 16:25:35

“仅仅因为”编写界面在我看来是浪费时间和精力,更不用说违反 KISS 原则了。

当它们实际上可用于表示相关类的常见行为时,我会编写它们,而不仅仅是作为一个花哨的头文件。

Writing interfaces "just because" strikes me as a waste of time and energy, not to mention a violation of the KISS-principle.

I write them when they are actually useful in representing common behavior of related classes, not just as a fancy header file.

葮薆情 2024-07-12 16:25:35

不要过度设计你的系统。 如果您发现您有多种类型的订单,并且认为为订单声明一个接口是合适的,那么在需要时重构它。 对于领域模型,特定接口在开发生命周期中发生很大变化的可能性很高,因此尽早编写接口几乎没有用处。

Don't over design your system. If you find out that you have several types of Orders and think it's appropriate to declare an interface for Orders than refactor it when the need arises. For domain models, the probability is high that the specific interface will change much over the lifetime of development, so it rarely useful to write an interface early.

梦里°也失望 2024-07-12 16:25:35

接口是隔离组件以进行单元测试和一般依赖关系管理的绝佳方法。 话虽如此,我通常更喜欢抽象类,因此至少有一些常见的行为被卸载在那里,而不是强制接口带来的一些重复。 现代 IDE 可以快速、轻松地生成界面,因此它们不需要太多工作:-)

Interfaces are an excellent way of isolating components for unit testing purposes and general dependency management. Saying that, I often prefer abstract classes so at least some of the common behaviour is offloaded there rather than forcing some of the duplication that interfaces bring. Modern IDEs make it quick and easy to generate interfaces so they aren't that much work :-)

暮年 2024-07-12 16:25:35

不,我只在域对象上使用接口来保持它们的松散耦合。 对我来说,使用接口开发自己的代码的主要钩子是我可以在进行单元测试时轻松创建模拟。 我不认为模拟域对象有什么意义,因为它们不具有服务层或 DAO 层类所具有的相同依赖关系。

这当然并不意味着放弃在域对象中使用接口。 在适当的地方使用。 例如,最近我一直在开发一个网络应用程序,其中不同类型的域对象对应于用户可以在其中留下评论的永久链接页面。 因此,每个域对象现在都实现了“Commentable”接口。 然后,所有基于注释的代码都被编程到可注释接口而不是域对象。

No, I only use interfaces on Domain Objects to keep them loosely coupled. For me the main hook of developing my own code with interfaces is that I can easily create mocks when doing Unit Testing. I don't see the point in mocking Domain Objects as they don't have the same dependencies that a service layer or DAO layer class would have.

This certainly doesn't mean to stray away from using Interfaces in Domain Objects. Use where appropriate. For example, lately I've been working on a webapp where different types of Domain Objects correspond to permalink pages in which users can leave comments. So, each of these Domain Objects now implement the "Commentable" interface. All of the comment-based code is then programmed to the Commentable interface instead of the Domain Objects.

芯好空 2024-07-12 16:25:35

我通常只在小型项目中有意义的情况下使用接口。 然而,我最近的工作有一个大型项目,其中几乎每个域对象都有一个接口。 这可能有点矫枉过正,而且确实很烦人,但我们测试和使用 Spring 进行依赖注入的方式有点需要它。

I usually only use interfaces where it makes sense on smaller projects. However, my latest job has a large project where nearly every domain object has an interface. It's probably overkill and it's definitely annoying, but the way we do testing and use Spring for dependency injection sort of requires it.

怕倦 2024-07-12 16:25:35

我们主要使用 Wicket、Spring 和 Hibernate 编写 Web 应用程序,并使用 Spring Bean 的接口,例如服务和 DAO。 对于这些类,接口是完全有意义的。 但我们也为每个域类使用接口,我认为这有点矫枉过正。

We mostly write web applications with Wicket, Spring and Hibernate and we use interfaces for Spring Beans, e.g. Services and DAOs. For these classes, interfaces make totally sense. But we also use interfaces for every single domain class and I think this is just overkill.

挽梦忆笙歌 2024-07-12 16:25:35

即使您非常确定模型对象只会有一种具体类型,使用接口也会使模拟和测试变得更加容易(但现在有一些框架可以帮助您自动生成模拟类,即使是具体的 Java 类 - Mockito、JTestR、Spring、Groovy...)

但我更经常使用服务接口,因为在测试过程中模拟它们更为重要,并且针对接口进行编程可以帮助您思考封装等内容。

Even if you are pretty sure there is only going to be one concrete type of a model object, using interfaces makes mocking and testing somewhat easier (but these days there are framworks that can help you generate mock classes automatically, even for concrete Java classes- Mockito, JTestR, Spring, Groovy...)

But I even more often use interfaces for services, since it is even more important to mock away them during testing, and programming against interfaces helps you think about stuff like encapsulation.

蓝海似她心 2024-07-12 16:25:35

如果您将域类用于单元测试,则为域类编写接口是有意义的。 我们在单元测试中使用 Mock 对象。 因此,如果您有一个域对象的接口,并且您的域对象本身尚未准备好,但您的客户端可以借助模拟对象来测试其对该接口的使用。

接口还测试领域模型接口的多个实现。 所以,我不认为这总是矫枉过正。

Writing interfaces for domain classes can make sense if you're using it for unit testing. We use Mock objects in unit testing. So, if you have an interface for a domain object and your domain object itself is NOT ready but your client can test its use of the interface by the help of mock objects.

Intefaces also test multiple implementations of your interfaces for your domain model. So, I don't think it is always overkill.

巷雨优美回忆 2024-07-12 16:25:35

我认为针对接口进行编程的主要原因是可测试性。 因此,对于域对象 - 只需坚持 POJO 或 POC#O :) 等,即,只需防止您的类添加任何特定框架,以防止它们具有不同的构建和运行时依赖关系,仅此而已。
不过,为 DAO 创建接口是个好主意。

I think that the main reason for programming against interfaces is testability. Hence, for the domain objects - just stick to POJOs or POC#Os :) etc., i.e., just keep your classes from adding any specific framework so to prevent them from differend build and runtime dependencies and that's all.
Creating interfaces for DAOs is a good idea though.

忆悲凉 2024-07-12 16:25:35

我们从一切事物中提取接口,只是因为它有助于测试(模拟)和 AOP 之类的东西。 Eclipse 可以自动执行此操作:Refactor->Extract Interface。

而如果以后需要修改类,可以使用 Refactor->Pull Up... 将需要的方法拉到接口上。

We extract interfaces from everything just because it assists in testing (mocking) and for stuff like AOP. Eclipse can do this automatically: Refactor->Extract Interface.

And if you need to modify the class later, you can use Refactor->Pull Up... to pull up the methods you need onto the interface.

执手闯天涯 2024-07-12 16:25:35

*我这样做是因为我需要它来创建我的域对象的代理。

*I do it because I need it for creating proxies of my domain objects.

够运 2024-07-12 16:25:35

这是我遇到过的另一件需要记住的事情,尤其是对于生成的域和 DAO 对象。 很多接口都过于具体。 假设很多域对象都有一个 ID 和一个状态字段,为什么它们不共享一个公共接口呢? 这让我感到沮丧,这是一个不必要的扁平(继承方面)域模型。

That's another thing to keep in mind that I've run in to, especially with generated domain and DAO objects. A lot of the interfaces are just too specific. Say a lot of domain objects have an ID and a status field, Why don't they share a common interface? This has caused me frustration, an unnecessarily flat (inheritance-wise) domain model.

哎呦我呸! 2024-07-12 16:25:35

我建议保持精益和敏捷——在需要之前不要做任何事情,然后让 IDE 在需要时为您进行重构。

当您决定需要一个具体的类时,在 IDEA/eclipse 中将一个具体的类转换为一个接口是非常简单的。

然后使用 SpringGuice 如果您有许多接口实现可以注入到您正在使用“new”的代码中的位置

I'd recommend staying lean and agile - don't do anything until you need to do it, then let your IDE do the refactoring for you when you need it.

Its pretty trivial in IDEA/eclipse to turn a concrete class into an interface when you decide you need one.

Then use dependency injection with Spring or Guice if you have many implementations of the interface to inject into the places in your code you're using 'new'

童话里做英雄 2024-07-12 16:25:35

在需要之前编写接口(无论是用于测试还是架构)是一种矫枉过正的行为。

此外,手动编写接口是浪费时间。 您可以使用 Resharper 的重构“Pull Members”,让它在几秒钟内从特定类中创建新接口。 与 IDE 集成的其他重构工具也应该具有类似的功能。

Writing interface before it gets needed (either for testing or architecture) is an overkill.

Additionally, writing an interface manually is a waste of time. You can use Resharper's refactoring "Pull Members" to let it create new interface out of the specific class in a matter of seconds. Other refactoring tools that integrate with IDE should have similar functionality as well.

萌︼了一个春 2024-07-12 16:25:35

实际上,这个问题是对“针对接口编程”的常见误解的一个例子。

你看,这一个非常好的原则,但它并不意味着很多人认为的那样!

“针对接口编程,而不是实现”(摘自 GoF 书籍)就是这个意思,而不是说您应该特意为所有内容创建单独的接口。 如果您有一个 ArrayList 对象,请将变量/字段/参数/返回类型声明为 List 类型。 客户端代码将只处理接口类型。

在 Joshua Bloch 的《Effective Java》一书中,其原理在“第 52 条:通过接口引用对象”中表达得更清楚。 它甚至用粗体字写着:

用类而不是类来引用对象是完全合适的。
如果没有合适的接口存在,则接口。

对于单元测试,情况完全取决于所使用的模拟工具的功能。 使用我自己的工具 JMockit,我可以轻松地为使用接口的代码编写单元测试以及依赖注入,对于使用从被测代码内部实例化的最终类的代码。

因此,对我来说,答案是:始终使用已经存在的接口,但如果没有充分的理由,请避免创建新的接口(并且可测试性本身不应该是一个)。

Actually, this question is an example of the common misunderstanding about "programming against interfaces".

You see, this is a very good principle, but it does not mean what many people think it means!

"Program to an interface, not an implementation" (from the GoF book) means just that, not that you should go out of your way to create separate interfaces for everything. If you have an ArrayList object, then declare the variable/field/parameter/return type as being of type List. Client code will then only deal with the interface type.

In the "Effective Java" book from Joshua Bloch, the principle is expressed more clearly, in "Item 52: Refer to objects by their interfaces". It even says, in bold letters:

It is entirely appropriate to refer to an object by a class rather than an
interface if no appropriate interface exists.

For unit testing, the situation is entirely dependent on the capabilities of the mocking tool used. With my own tool, JMockit, I can write unit tests just as easily for code that uses interfaces and Dependency Injection as for code that uses final classes instantiated from inside the code under test.

So, for me, the answer is: always use interfaces that already exist, but avoid creating new ones if there is no good reason to do so (and testability, by itself, should not be one).

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