AnemicDomainModel - 需要更简单的解释

Can*_*ell 1 domain-driven-design

我今天读了这篇文章,并试图澄清一些事情.本文是否意味着模型对象应包含业务逻辑?例如,让我们说有一个Student对象,我们通过Hibernate从数据库中检索它.本文是否说Student对象应该包含业务逻辑,而不是只有getter和setter?

Mar*_*ius 6

无视这一日期,马丁福勒所说的今天和八年前一样重要.Fowler没有声明你应该将持久性混合到域对象中,恰恰相反:

"同样值得强调的是,将行为放入域对象不应该与使用分层将域逻辑与持久性和表示责任等事物分离的可靠方法相矛盾."

你应该再读一遍这篇文章,因为这篇文章很好地描述了这种反模式,但我会在你所要求的背景下为你总结它:

如果要创建域模型,是的,您的域对象应该包含业务逻辑和状态,并且域实体状态的更改应该通过传达业务含义的方法来完成.贫血领域模型是一种反模式,因为你会产生额外一层课程的成本,但你并没有从中获益.为什么要在使用活动记录样式方法(数据集等)时传达与完全相同的意图时,必须使用域图层对数据库进行映射?所以文章并没有说你应该有一个"学生对象",但它说如果你这样做,你应该明确地将状态添加到该类.

如果您不对域进行建模,那么文章中关于没有一组对象来表示您的模型的观点可能会因为当前可用的技术而有点混乱.有很棒的工具可以毫不费力地在一组POCO和数据库(Nhibernate,EF,Simple Data,Massive,Dapper等)之间移动数据,所以在回顾中我会说你最终会得到一组在今天的大多数解决方案中,"实体"真正的区别在于它是仅仅是数据库模型还是真实的域模型.

我将向您展示域入口点(命令处理程序)与域模型之间的交互示例.下面显示的方法位于命令处理程序中,该命令处理程序使用更改域中某些内容的请求.请注意,您的域代码层只是获取域实体并在域上调用一个方法?这一点非常重要,因为我们正在建模的工作流程完全封装在域中,而不是在您的域代码中或其他任何地方:

    public void Handle(AddEmailAddressForAlerts command)
    {
        var agent = _repository.GetAgent(command.AgentKey.AgentId);
        agent.AddEmailAddressForAlerts(new EmailAddress(command.EmailAddress));
    }
Run Code Online (Sandbox Code Playgroud)