域驱动设计 – 将现实世界的逻辑放入DDD域层中
尽管已经长期研究域驱动设计,但仍然有一些基础知识,我只是想出来。
似乎每次我尝试设计一个丰富的域层时,我仍然需要很多域名服务或一个厚实的应用层,而且我最终会出现一堆没有真实逻辑的近似贫乏的域实体,除了“GetTotalAmount”等。关键的问题是实体不知道外部的东西,而且对实体注入任何东西都是不好的做法。 让我举一些例子: 用户注册服务。用户被保存在数据库中,生成并保存文件(用户帐户需要),并发送确认电子邮件。 具有确认电子邮件的例子已经在其他主题中进行了大量讨论,但没有得到真正的结论。有些建议将逻辑放在应用程序服务中,从基础结构层注入一个EmailService和FileService。但是,那么我会在域外有业务逻辑吗?其他人建议创建一个可以注入基础架构服务的域服务,但是在这种情况下,我需要在域层(IEmailService和IFileService)内部具有基础设施服务的接口,这不是太好(因为域层无法参考基础设施层)。而其他人建议实施Udi Dahan’s Domain Events,然后让EmailService和FileService订阅这些事件。但这似乎是一个非常宽松的实现 – 如果服务失败会发生什么?请让我知道你认为这是正确的解决方案。 一首歌从数字音乐商店购买。购物车已清空。购买持续存在。付款服务被称为。发送电子邮件确认。 好的,这可能与第一个例子有关。这里的问题是谁负责协调交易?当然,我可以把所有的东西放在MVC控制器中,注入服务。但是如果我想要真正的DDD,所有的业务逻辑都应该在域中。但哪个实体应该有“购??买”方式? Song.Purchase()? Order.Purchase()? OrderProcessor.Purchase()(域服务)? ShoppingCartService.Purchase()(应用服务?) 这是一个我认为在域实体中使用真实业务逻辑很困难的情况。如果注入任何东西不是很好的做法,那么他们怎样才能做其他的事情,而不是检查自己的(和它的聚合)的状态? 我希望这些例子足以显示我正在处理的问题。
您可以在这里申请Dependency Inversion Principle。定义一个域接口,如下所示: void ICanSendConfirmationEmail(EmailAddress address,...) 要么 void ICanNotifyUserOfSuccessfulRegistration(EmailAddress address,...) 接口可以被其他域类使用。在基础架构层实现此接口,使用真正的SMTP类。在应用程序启动时注入此实现。通过这种方式,您在域代码中表示业务意图,您的域逻辑不直接引用SMTP基础架构。这里的关键是接口的名称,它应该基于无所不在的语言。
使用OOP最佳做法分配责任(GRASP和SOLID)。单元测试和重构将给您一个设计反馈。编排本身可以是薄应用层的一部分。从DDD Layered Architecture:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |