DDD原则和小巧玲珑库

问题描述 投票:-1回答:2

我设立在我申请洋葱架构和DDD模式的解决方案。

其中一个DDD原则,鼓励域实体只有私人制定者和私人默认的构造函数,以确保您不能处于无效状态创建域实体。

存储库包含关于域实体,这是从/到数据库映射到的数据的操作。我一直在尝试以下两种方法:

  1. 在一个纯粹的方式域实体:没有默认构造函数,没有公开制定者;验证在构造(多个)进行;这可以确保你不能处于无效状态创建一个域实体。副作用是,它是很难取消实现他们在读操作的仓库;因为你需要反思,以便能够创建实例和地图属性;和使用中需要短小精悍请求动态映射到实际域实体。如果我会直接映射到这个域的实体,而无需使用动态的,小巧玲珑的抛出一个异常,没有公共的构造。
  2. 在一个非纯粹的路域实体:你让一个默认的构造函数,所有的setter方法是公开的;这样你就可以创建不在在给定时间点有效的实体。在这种情况下,你需要手动调用validate()方法,以确保它们是有效的,然后再继续。这使得dematerilizing在库要容易得多,因为你不需要思考,也不动力学数据库映射到模型。

这两种方法的工作,但是,与选项2的资料库变得非常简单,因为它们含有少了很多自定义映射代码,并没有反射显然会更高性能的为好。当然,DDD不是以纯粹的方式应用。

前一个决定什么,我会在我的项目中使用,一个问题:是否有任何其他微ORM框架,有可以处理私有构造函数和setter方法,使映射数据库的那种“纯”领域的实体不进行额外支持自定义映射逻辑是什么? (无EF也不NHibernate的,我想要的东西轻量级)。

或其他技术解决方案,以保持“纯”模型实体结合容易库映射方法?

编辑:我实现了解决方案是以下。

首先,构造函数和setter域中实体都是“内部”,这意味着它们不能被消费者域模型的设定。但是,我用“InternalsVisibleTo”允许数据访问层直接访问它们,所以这意味着从数据库非物质化是很容易与短小精悍(无需中级车型)。从应用层,我只能使用域的方法来直接改变域实体,而不是性能。

其次,从我的应用层构建新的域的实体,我说一口流利的建设者,以帮助建筑领域的实体,所以现在我可以构建他们像:

 User user = new UserBuilder()
        .WithSubjectId("045454857451245")
        .WithDisplayName("Bobby Vinton")
        .WithLinkedAccount("Facebook", la => la.WithProviderSubjectId("1548787788877").WithEmailAddress("[email protected]"))
        .WithLinkedAccount("Microsoft", la => la.WithProviderSubjectId("54546545646").WithEmailAddress("[email protected]"))

当构造器“构建”实体,验证完成后为好,这样你就可以永远处于无效状态创建一个实体。

c# architecture domain-driven-design dapper
2个回答
2
投票

其中一个DDD原则,鼓励域实体只有私人制定者和私人默认的构造函数,以确保您不能处于无效状态创建域实体。

这是不完全正确。是的,丰富的域模型通常不暴露setter方法,但那是因为他们不需要setter方法。你告诉模型如何在更高的抽象水平做,并允许它来确定自己的数据结构应当如何修改。

同样,也有经常情况下是有意义的公开默认的构造函数:如果你认为一个聚合为一个有限状态机,那么默认的构造函数是一种方法来初始化它的“启动”状态的总和。

所以通常你在以下两种方法之一重建而成:要么你初始化它在默认状态下,然后发送了一堆邮件,或者你使用Factory模式,如在蓝皮书描述。

这意味着其间的额外的映射,这使得代码更复杂

也许吧,但它也可以确保您的域名代码更少依赖于ORM的魔力。特别是,它意味着你的域逻辑可以在比什么是用来做持久性“容易”的不同的数据结构进行操作。

但它不是免费的 - 你必须在代码中如何获取值出聚合根和回数据库(或进入ORM实体,作为数据库的代理)来形容。


1
投票

关键是,你不使用小巧玲珑与您的域实体合作,而是你用它来与POCO实体存储库层内。您的仓库方法将通过转换POCO实体(即小巧玲珑的用于数据访问)域实体返回域实体。

© www.soinside.com 2019 - 2024. All rights reserved.