面向服务的体系结构和域驱动设计

nul*_*ter 20 soa design-patterns domain-driven-design

我总是以SOA类型的方式开发代码.今年我一直在努力做更多的DDD,但我一直觉得我没有得到它.在工作中,我们的系统是负载平衡的,并且设计为不具有状态.该架构是:

网站

===物理层==

主要服务

==物理层==

服务器1 /服务2 /服务3 /服务4

只有服务器1,服务2,服务3和服务4可以与数据库通信,主服务根据订购的产品调用正确的服务.每个物理层也是负载平衡的.

现在,当我开发一项新服务时,我尝试在该服务中考虑DDD,即使它并不真正感觉它适合.

我使用良好的DDD原则,如实体,值类型,存储库,聚合,工厂等.

我甚至尝试使用ORM,但他们似乎并不适合无状态架构.我知道有很多方法,例如使用IStatelessSession而不是NHibernate的ISession.但是,ORM只是觉得它们不适合无状态架构.

我注意到我真的只使用了DDD教给我的一些概念和模式,但整体架构仍然是SOA.

我开始认为DDD不适合大型系统,但我认为一些模式和概念确实适合大型系统.

就像我说的,也许我只是没有抓住DDD或者我可能不在分析我的设计?也许通过使用DDD告诉我的模式和概念我使用DDD?不确定这篇文章是否真的有问题,但在尝试找出DDD在整个系统中的适用位置以及它的真实可扩展性时,我有更多的想法.事实是,我认为我甚至不知道DDD是什么?

Rog*_*son 23

我认为一个常见的误解是SOA和DDD是两种相互冲突的风格.

国际海事组织,它们是两个共同发挥作用的概念; 您可以创建一个封装域概念的域模型,并通过服务将入口点公开到该模型中.

我也没有看到ORM和服务有什么问题,你可以轻松地使用每次服务调用的session/uow.只需将您的服务操作建模为原子域命令.

一个天真的例子:

[WebMethod]
void RenameCustomer(int customerId,string newName)
{
    using(var uow = UoW.Begin())
    {
        var customerRepo = new CustomerRepo(uow);
        var customer = customerRepo.FindById(customerId);
        customer.Rename(newName);
        uow.Commit();
    }
}
Run Code Online (Sandbox Code Playgroud)

也许您面临的问题是您创建了像"UpdateOrder"这样的服务,它接受订单实体并尝试在新会话中更新它?

我试图避免这种服务,而是将它们分解为更小的原子命令.

每个命令都可以作为操作公开,或者您可以使用单个服务操作接收命令组,然后将这些命令委托给命令处理程序.

IMO,这样你可以更好地揭露你的意图.


Nat*_*hes 9

关于领域驱动设计最重要的事情是全局的想法:

  • 无处不在的语言,
  • 战略决策,通过在核心领域工作来增加价值(并使自己与其他讨厌的系统隔离),以及
  • 通过将基础架构与业务逻辑分离来制定可测试的,灵活的设计的方法.

这些广泛适用,是最有价值的作品.

有很多关于工厂,服务,存储库,聚合等的设计模式的东西,我把它作为一个有经验的开发人员给另一个人的建议,而不是福音,因为它的大部分可能因语言和框架而异你正在使用.imho他们往往被过分强调,因为像我们这样的程序员是以细节为导向的,我们对这种东西着迷.那里也有宝贵的东西,但需要保持透视.因此,有些内容可能与您无关,或者在您使用它时可能会对您产生影响.

所以我会说这不是一个清单,你可以通过确保你使用所有的模式,这是一个关注的问题,看看这是如何改变你开发软件的方法.如果你从模式中汲取一些好的技巧,那也很棒.

特别是关于SOA的事情,我开发了将所有状态推迟到数据库的应用程序,这些数据库使用了持久性无知的域对象.为必须模拟daos和反馈东西的服务编写测试是苦差事,我可以在域对象中添加的逻辑越多,我在服务中的模拟就越少,所以我倾向于更喜欢这种方法.


Jos*_*gle 8

DDD引入了一些概念,在构建SOA时实际上可能会让您感到困惑.

我必须完全同意另一个答案,即SOA服务公开充当原子命令的操作.我相信一个非常干净的SOA使用消息而不是实体.然后,服务实现将利用域模型来实际执行操作.

然而,DDD中有一个称为"域服务"的概念.这与应用程序服务略有不同.通常,"域服务"是在与域模型的其余部分相同的普遍存在的语言中设计的,并且表示不完全适合实体或值的业务逻辑.

域服务不应与应用程序服务混淆.实际上,可以很好地实现应用服务,使得它使用域服务.毕竟,应用程序服务可以完全封装SOA中的域模型.


Dim*_*mos 6

我在这方面真的很晚,但我想在其他人的非常好的答案中添加以下内容。

  • DDD 与 SOA 没有任何冲突。相反,DDD 可以帮助您维护更好的面向服务的架构。SOA 提倡服务的概念,这样你就可以在你的系统之间定义更好的边界(哦,上下文边界也是 DDD 的概念!)并提高对它们的理解。
  • DDD 不是应用一组模式(例如存储库、实体等)。DDD 主要是尝试为您的软件建模,以便所有概念(即面向对象编程中的类)直接与业务概念保持一致。

您还应该查看此视频(尤其是最后 5 分钟),其中 Eric Evans 正好讨论了这个主题。


我什至尝试过使用 ORM,但它们似乎不适合无状态架构。

我没有任何方便的参考资料来支持这一点。但是,您是对的,ORM 也不太适合 DDD。这是因为,他们试图以错误的方式弥合对象-关系阻抗失配。他们迫使软件走向一个贫乏的领域模型,其中类最终成为“普通数据持有者”。

我开始认为 DDD 不适合大型系统,但我确实认为某些模式和概念确实适合大型系统。

在我上面链接的视频中,您还可以找到 Eric 解释 DDD 概念可以在非常大规模的系统中“中断”。例如,想象一个零售系统,其中每个订单都是一个包含可能数以千计的订单项目的集合。如果您想严格按照 DDD 计算订单的总金额,您必须将所有订单项加载到内存中,这与利用您的存储系统(例如,使用巧妙的 SQL 语句)相比效率极低。因此,应始终牢记这种权衡,DDD 不是灵丹妙药。

就像我说的,也许我只是没有掌握 DDD 或者我过度分析了我的设计?

对不起,我得再引用一次埃里克·埃文斯的话。正如他所说,DDD 不适合完美主义者,这意味着可能存在理想设计不存在的情况,您可能不得不采用解决方案,这在建模方面更糟糕。要了解更多相关信息,您可以查看这篇文章