刚读完Greg Young的这篇文章,他在谈论微软推荐使用哑数据传输对象的模式.他暗示,在Java社区中,事情正朝着另一个方向发展.
我的问题是你的实体对象应该有多少逻辑?我工作的理念(C#shop)是,如果你不能序列化它,不要把它放在实体中.
马特,
我会说你的商店正在编写程序代码.我想清楚地表明,使用过程代码编写了许多大型系统(包括我曾经使用过的许多系统)都没有错.有时间和地点.
现在,程序代码在域模型中没有位置.如果你想使用一个更好的程序风格,但使用类似表模块或活动记录模式的方式.我认为在指导中如此具有破坏性,而不是缺乏OO,而是使用具有程序逻辑的域模型.
这导致人们花费大量资源来构建域层(阻抗不匹配,思考处理时间来构建聚合,隔离,无处不在的语言等),而不会获得域层(通常可维护性)否则将提供的任何好处.换句话说,虽然您可以满足您的功能要求,但最终会花费大量预算而几乎没有回报.
现在回到"行为",我想关注面向对象的问题,而不是"领域驱动设计"的观点.对象通常会封装某些状态,并且通常会暴露某些行为.
快速重申:封装状态,暴露行为
那么一个对象应该有什么样的行为?简而言之,它应该是对它所封装的状态进行操作的行为.在理想的行为OO世界中,状态永远不会从仅对象行为中暴露出来.如果我们开始看到如下代码,请在战术上放入代码:
Customer c = GetCustomerFromRepository(); c.Status = CustomerStatuses.Deleted; c.LastUpdated = DateTime.Now; c.UpdatedBy = GetCurrentUser(); CustomerRepository.Save(c);
我们有SRP违规...此代码是应该是客户对象行为的代码,因为客户对象的"责任"是.
封装有关客户的状态并公开行为.
因此,我们可以看到使用Customer.Delete()方法会更好.(是的,这是一个我知道的坏例子......)
现在我们也可以通过使用TDD来实现这一点.对于我们来说,使用行为所提供的接缝进行测试比接触所有状态的接缝要容易得多.原因是我不需要在测试中复制逻辑.客户端代码不关心删除的工作方式......它只关心客户公开行为.因此在我们的测试中,而不是断言c.State == CustomerStates.Deleted和c.UpdatedBy == GetCurrentUser()等等,我们只是断言使用模拟在客户接缝上调用了delete方法.
现在回到标题.应该在业务对象中的逻辑量是在其封装其状态的责任范围内的逻辑量.有时这很多,有时候不是.有些地方你也想要使用服务......一个很好的例子是协调给定行为的许多域对象之间的交互,但即使在这里,服务也应该调用域对象上的行为.
这有助于澄清一些事情吗?
格雷格