信息专家,Tell-Don't-Ask和SRP通常被一起提及为最佳实践.但我认为他们存在分歧.这就是我所说的.
有利于SRP但违反Tell-Don't-Ask&Info-Expert的代码:
Customer bob = ...;
// TransferObjectFactory has to use Customer's accessors to do its work,
// violates Tell Don't Ask
CustomerDTO dto = TransferObjectFactory.createFrom(bob);
Run Code Online (Sandbox Code Playgroud)
有利于Tell-Don't-Ask和Info-Expert但违反SRP的代码:
Customer bob = ...;
// Now Customer is doing more than just representing the domain concept of Customer,
// violates SRP
CustomerDTO dto = bob.toDTO();
Run Code Online (Sandbox Code Playgroud)
请告诉我这些做法如何能够和平共处.
术语的定义,
信息专家:具有操作所需数据的对象应承载该操作.
告诉不要问:不要向对象询问数据以便工作; 告诉对象做这项工作.
单一责任原则:每个对象应具有狭义的责任.
oop single-responsibility-principle tell-dont-ask solid-principles
这是我在DDD Yahoo!上发布的内容重新发布的.组.
一切都相同,你写phone.dial(phoneNumber)或phoneNumber.dialOn(电话)?请记住可能的未来要求(除电话号码外的帐号,除电话外的计算器).
这个选择倾向于说明信息专家,单一责任原则和Tell Do Not Ask的成语是如何相互矛盾的.
phoneNumber.dialOn(电话)支持信息专家和告诉不要问,而phone.dial(phoneNumber)支持单一责任原则.
如果您熟悉Ken Pugh在Prefactoring中的工作,那就是电子表格难题 ; 你添加行或列?
我目前正在努力重写一个应用程序,以使用完全从Domain层抽象数据库的Data Mappers.但是,我现在想知道哪个是处理Domain对象之间关系的更好方法:
在我看来,为了保留'Fat Model,Skinny Controller'的口头禅,域对象必须知道数据映射器(无论是他们自己还是他们可以访问系统中的其他映射器) .此外,似乎选项2不必要地使数据访问层复杂化,因为它跨多个数据映射器创建表访问逻辑,而不是将其限制在单个数据映射器中.
那么,让域对象知道相关数据映射器并直接从域对象调用数据映射器函数是不正确的吗?
更新:这是我可以设想的唯一两个解决域对象之间关系问题的解决方案.任何显示更好方法的例子都是受欢迎的.
在域驱动设计中,您需要一个非贫困域模型,您如何决定在域对象和面向服务的方法中实现什么?
编辑:我用一个例子以不同的方式问这个,并在这里得到更好的答案
假设您有一个域实体用户,并且您希望支持用户将项目添加到购物车的功能.现在,我们要确保购物车中的项目是唯一的,因此我们在User类中创建以下函数:
function AddItemToCart(Item item)
{
// Add business logic to make sure item is unique
}
Run Code Online (Sandbox Code Playgroud)
这非常有效.但是,如果我们现在想要在项目添加到购物车时也通过电子邮件发送给用户呢?我们可以将它添加到AddItemToCart中,但它需要将一些IEmailer依赖项注入User类.
另一种方法是创建一个服务来处理这个事务(例如ShoppingCartService),它将执行业务逻辑并发送电子邮件.然而,这会导致一个相当贫乏的领域(即用户类只不过是getter/setters)