域实体应该作为接口(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特定的实现,目前还没有更好的示例。

最佳答案

我对此的感觉是,除非您有非常有说服力的理由认为您需要在数据库中的某个时候支持多种实现,否则域对象(而不是域实体,因为该标题暗示与数据库有关)。 future 。

考虑领域模型(Domain Model)是人类模型。从字面上看,业务/服务/文档是域。我们大多数人都在为单一业务或目的开发软件。如果域模型发生更改,那是因为业务规则已更改,因此旧的域模型不再有效-没有理由让旧的域模型与新的域模型并存。

辩论显然不是黑白的。您可能正在开发在多个客户端站点上高度定制的软件。您可能确实确实需要同时实现不同的业务规则集,同时真正需要将它们放入统一的体系结构中。但是,至少从我的经验来看,这些情况是异常(exception)而不是规则,尽管我通常不喜欢该用语,但在这种情况下,您应该自己思考YAGNI

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

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

您希望作为接口(interface)公开的某些类型的对象是:

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

  • 那绝不是一个完整的列表,但它应该在这里阐明基本原理,即最适合接口(interface)抽象的事物是:
  • 取决于可能无法控制的因素。
  • 将来可能会改变;和
  • 是水平要素(在应用程序/体系结构的许多部分中使用)。

  • 域类将被广泛使用,但不适合前两个类别中的任何一个。它不可能更改,并且您几乎可以完全控制设计。因此,除非类本身将承担间接依赖关系(在任何可能的情况下都应避免这种情况),否则我不会花费额外的精力为域模型中的每个类创建接口(interface)。

    07-24 09:44
    查看更多