c# - 域实体应该作为接口(interface)还是作为普通对象公开?

标签 c# domain-driven-design

域实体应该作为接口(interface)还是作为普通对象公开?

用户界面:

public interface IUser
{
    string FirstName { get; set; }
    string LastName { get; set; }
    string Email { get; set; }
    Role Role { get; set; }
}

用户实现(在 LinqToSql 数据访问层中实现):

public class User : IUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public Role Role { get; set; }
}

用户实现(在 NHibernate 数据访问层中实现):

[NHibernate.Mapping.Attributes.Class]
public class User : IUser
{
    [NHibernate.Mapping.Attributes.Property]
    public string FirstName { get; set; }

    [NHibernate.Mapping.Attributes.Property]
    public string LastName { get; set; }

    [NHibernate.Mapping.Attributes.Property]
    public string Email { get; set; }

    [NHibernate.Mapping.Attributes.Property]
    public Role Role { get; set; }
}

这仅说明了一些 DAL 特定实现,目前没有更好的示例。

最佳答案

我对此的感觉是域对象(不是域实体,因为该标题暗示与数据库有关)不应该是接口(interface),除非您有非常令人信服的理由相信您会需要在未来的某个时候支持多种实现。

考虑领域模型是人体模型。从字面上看,业务/服务/文档就是域。我们大多数人都在为单一业务或目的开发软件。如果域模型发生变化,那是因为业务规则发生了变化,因此旧的域模型不再有效 - 没有理由保留旧模型,与新模型一起运行。

辩论显然不是非黑即白的。您可能正在开发在多个客户站点高度定制的软件。您可能确实需要同时实现不同的业务规则集,并且同时真正需要将它们放入一个统一的架构中。但是,至少根据我的经验,这些情况是异常(exception)而不是规则,虽然我一般不喜欢这个词,但在这种情况下你应该自己思考,YAGNI .

数据访问是您需要更好抽象的公共(public)领域 (persistence ignorance)。在您的示例中,您的模型类具有 NHibernate 属性。但是添加持久化属性使它不再是真正的域类,因为它引入了对 NHibernate 的依赖。 NHibernate 和 Fluent NHibernate 支持使用外部映射声明而不是数据类上的属性来映射 POCO,这往往是使用 NHibernate 或 EF4 等 ORM 时的首选方法,因为它打破了持久性模型和领域模型之间的依赖关系。

如果不支持这些映射方法,并且您不得不使用属性,那么我可能确实建议改用接口(interface),但今天的 ORM 比这更复杂,使用反射和动态代理以及方法拦截来完成大部分繁重的工作,因此您无需在此处创建自己的抽象。

想要作为接口(interface)公开的一些对象类型是:

  • 存储库,负责加载/保存域对象;
  • 程序的插件/扩展;
  • View/presenter 模型,以便可以插入不同的 UI;
  • 具有多种实现的抽象数据类型(数组、列表、字典、记录集和数据表都是序列 AKA IEnumerable);
  • 具有许多可能算法(排序、搜索、比较)的抽象操作;
  • 通信模型(基于 TCP/IP 的相同操作、命名管道、RS-232);
  • 任何特定平台,如果您计划部署到多个平台 (Mac/Windows/*nix)。

这绝不是一个完整的列表,但它应该阐明这里的基本原则,即最适合接口(interface)抽象的事物是:

  1. 取决于您可能无法控制的因素;
  2. 将来可能会发生变化;和
  3. 是横向特征(用于应用/架构的许多部分)。

领域类将被广泛使用,但不属于前两类;它不太可能改变,而且您几乎可以完全控制设计。因此,除非类本身具有间接依赖性(这种情况您应该尽可能避免),否则我不会花费额外的精力为领域模型中的每个类创建接口(interface)。

关于c# - 域实体应该作为接口(interface)还是作为普通对象公开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2352654/

相关文章:

C# 收集内存泄漏对象的垃圾

c# - 带验证的 MVC 自定义路由

c# - 在图像文件中定位点的最佳算法是什么?

model - 在编写测试之前设计模型或编写设计模型的测试是正确的 TDD 实践吗?

c# - 存储库、工厂和层次结构数据

C#密码加密

c# - 为什么我在使用线程的并发 HTTP 连接上受限

oop - DDD : Modeling M:N relation between two roots where the relation itself carries semantic meaning

c# - 分离领域模型和数据模型

design-patterns - DDD 选择聚合根