接口应该知道域对象吗?

时间:2010-03-05 16:13:14

标签: oop dns interface

在我的系统中,我有两个不同的项目,一个定义其接口,另一个定义其域对象。到目前为止,我设法让接口定义独立于域对象,但我现在感觉需要将某些域对象包含在接口中定义的方法的参数中,或者作为返回值。

我是否应该抵制并尝试保持接口独立于域对象,或者这是一个毫无根据的问题?

编辑 - 在发布问题之后,我考虑为每个域对象定义一个接口,这样他们可以保持分离 - 不知道它是否过度或者是否需要付出代价才能保持独立。

编辑#2 - 我被要求举一个例子,所以我会尽量保持简单。我有一个处理图像转换的过程,我的一个域对象是一个包含分辨率,页面列表,哈希等信息的类。让它称为DocumentInfo。我有一个使用DocumentInfo来执行GeneratePdfFromTiff等操作的类;我首先将GeneratePdfFromTiff定义为IImageHandler的接口方法,然后由ImageHandler实现。

问题是 - GeneratePdfFromTiff的一个参数是DocumentInfo。这里我在接口级别定义的方法必须知道在域级别定义的DocumentInfo。这是我所关注的那种依赖。

4 个答案:

答案 0 :(得分:3)

这是一个艰难的,我会试一试。问题为+1。

域模型应该知道如果他们在我认为的现实世界中这样做,那么如何与彼此的内部工作进行交互。当然,这在很大程度上取决于您的确切域模型,因为同一事物的不同模型会产生非常不同的表示。

每个域模型类的接口问题在于,您的域模型本身已经是现实的特定视图,就像接口一样。接口仅在该特定域内有效。您不能将相同的ICar用于交通规划,家庭收入计算器和汽车空气动力学优化。

因此,我怀疑隔离它们的依赖关系是非常有用的。

据我所知,接口主要(总是?)公开,这会引起访问问题。接口不应公开有关实现的详细信息,但域模型类包含实际的实现。因此,您不必“只访问某些值”,而是必须为每个细节创建另一个抽象机制。例如,您无法访问系统中的任何ID,用户等。你需要一个抽象的ID类型,一个ID提供者等等。我相信这在大型真实世界模型中可能非常麻烦。

当然,某些“自然域边界”仍然应该被隔离。如果您构建社交文本编辑器,那么传统文本编辑器中也会出现的所有域类都应该与社交网络相关的项目完全隔离。因此,文本编辑器应该只知道IUser。但我想我不会告诉你任何新的东西......

这恐怕不太令人满意,但似乎走路本质上是一条细线。

答案 1 :(得分:2)

我会牢记使用该界面的软件工程师的利益。尝试解耦可以使代码更抽象,通常更难以使用。这意味着需要编写更多的代码来“完成工作”,而且代码需要更多的努力来编写。

Pardoxally,由于额外的复杂性,它也会变得更难以改变,因为更多的代码行依赖于您的域的可见界面。这与您可能想要实现的目标相反,因为解耦应该有助于使系统更易于理解和维护(除其他外)。

但它确实在很大程度上取决于你打算暴露什么类型以及向谁展示。你能举一些例子吗?

答案 2 :(得分:1)

你可能真的需要。如果您的域模型引用了接口库,则无法从接口库中引用域模型,因为这将创建循环引用。

即使不是这种情况,从服务引用域模型会在接口和域模型之间创建硬耦合。这意味着实现或引用接口的任何人也会引用域模型。你可能不希望这样。

我会建议您从那些想要与接口一起使用的域对象中提取接口。

如果您已经有一个名为Foo的类,则从中提取并连接IFoo,并在其他界面中使用它:

public interface IMyService
{
    public IBar DoStuff(IFoo foo);
}

一旦开始使用域对象作为接口,您将发现可能有更多地方可以用接口替换具体类。每次你这样做,你的代码变得更强松散耦合,这是一件好事。它使您的代码更易于维护,并且更易于适应变化。

提取界面时,请记住必须执行深度提取

如果Foo看起来像这样

public class Foo
{
    public Baz Baz { get; }
}

界面应如下所示:

public interface IFoo
{
    IBaz Baz { get; }
}

public interface IBaz {}

(如果你用不同的语言写的话,请为C#代码道歉......)

答案 3 :(得分:1)

我建议为具有行为的域类定义接口,但不要为简单的容器类或值类型定义接口。

如果GeneratePdfFromTiff仅将DocumentInfo视为parameter object,并且文档信息类没有任何逻辑,那么它应该只是一个可公开访问的类型。

如果文档信息类执行计算或做任何其他有趣的事情,那么绝对值得提取一个接口。 (由于马克在答案中提到的所有优秀理由。)