当我读到DDD的时候,人们总是说它是关于行为的,用另一种方式说,动作比可以执行的。
我怀疑该由谁来发起行动。
假设我有一个关于订单的有界上下文(BC)。举个例子,我只讲几条规则。
通常,在我看到的示例中,是在创建订单的应用层中,然后在数据库中持久化,如下所示:
public class CreateOrderApplicationService
{
public Order CreateOrder(long paramIdEmployee)
{
Order myOrder = Order.Create(paramIdEmployee);
_repository.Add(myOrder);
_repository.Commit();
}
}但是,我认为订单本身是不能创建的,事实上,在规则和无处不在的语言中,说员工收到订单,员工创建订单……依此类推,或者至少它暗示着它总是一个人,一个用户,一个雇员或另一种人做某事。或者系统的另一个进程,可以看作是另一种用户。
因此,从这个角度来看,我认为另一个解决办法可能是:
public class CreateOrderApplicationService
{
public Order CreateOrder(long paramIdEmployee)
{
Employee myEmpolyee = _repository.GetEmployee(paramIdEmployee);
Order myOrder = myEmpolyee.CreateOrder();
_repository.Commit();
}
}
public class Employee
{
long Id;
List<Order> Orders;
public Order CreateOrder()
{
Order myOrder = Order.Create(Id);
Orders.Add(myOrder);
return Order;
}
}注意:这里,我从order存储库中获得了employee,因为如果我没有错,通常的做法是为每个有界的上下文创建一个存储库,因此在我的有界上下文中需要一个employee。无论如何,该示例试图显示,我从存储库(无论从哪一个存储库中)获取员工来执行创建订单的操作。
在这种情况下,员工只是将订单的创建委托给order实体,但它是操作的起点。
但是在这个解决方案中,确实,所有的行为和所有有界的上下文都需要一个人实体,所有的行为都将通过实体人来完成,这似乎是一个奇怪的解决方案。但从另一个角度来看,似乎很直观的是,任何行动都是由一个人执行的,而在无处不在的语言中,据说是雇员创建了订单,而不是说订单是创建的(一般情况下)。
所以,对于那些从DDD开始的人来说,可能有点混乱,因为取决于使用无处不在的语言的方式,解决方案可能是不同的,或者导致以不正确的方式思考,或者导致使用技术解决方案,在这种情况下,谁开始行动,从专家的方式,而不是技术人员,只是关于问题解决的专家。
总之,我想知道通过用户启动每个操作的解决方案是否是个坏主意。
谢谢。
发布于 2023-03-25 11:37:23
DDD并不规定这样的细节,即使它会,它也不是你必须盲目遵循的“法律”。我建议不要再去想一些教条会说些什么,而应该多想想什么才是最有意义的。代码行
Order myOrder = Order.Create(paramIdEmployee);当Order构造函数只需要雇员ID时,就可以了,并且
Employee myEmployee = _repository.GetEmployee(paramIdEmployee);
Order myOrder = myEmployee.CreateOrder();当订单创建所需的不仅仅是员工的id,而是必须首先检索的Employee对象的更多数据时,就可以了。当整个用例需要一个带有新添加的order对象的对象myEmployee时,这也是可以的。
但是,当您在订单创建之后放弃myEmployee时,这就变得不必要地过于复杂了。首先从repo查询employee对象(这可能会导致数据库或网络查询)也不是很有效,只是为了传递您手头已有的ID。
回到你关于“谁开始行动”的问题上--我认为要做到这一点,你必须后退一步,看看一个完整的用例。例如,让我们假设这是一些GUI应用程序,它的开头是一个真实的人(比如一个公司的雇员)坐在电脑前,试图“创建一个真正的订单”。然后,当该用户按下UI中的某个按钮时,这将从表示层启动一条消息,该消息可能通过其他层传递,并最终调用CreateOrderApplicationService。由于用户以某种方式连接到系统,因此在调用CreateOrderApplicationService时,可能已经存在一个employee对象,该对象可以传递到服务调用中,然后如下所示:
public class CreateOrderApplicationService
{
public Order CreateOrder(Employee employee)
{
Order myOrder = employee.CreateOrder();
_repository.AddOrder(myOrder);
_repository.Commit();
}
}但是详细地说,整个用例的工作方式可能不同,在创建订单时,employee对象可能并不总是在手上,在这种情况下,简单的Order.Create方法可能是最简单(因此也是很好)的解决方案。
发布于 2023-03-25 15:49:42
在DDD中,我们并不是在模拟现实世界。该模型应该能够解决手头的业务问题。虽然这确实应该使用与领域专家协作创建的语言来完成,但这并不意味着领域概念之间的关系应该完全符合现实!
在专注于订单处理的模型(BC)中,我们真的需要员工集合吗?或者,仅仅知道是哪个员工创建了这个订单就足够了吗?在这种情况下,一个简单的employeeId就足够了。
所以,虽然您是正确的,在现实世界中,订单不会自己创建,而在为解决特定业务问题而创建的模型中,称为Order.Create(employeeId)的工厂方法是完全可以接受的。
发布于 2023-03-26 04:20:09
据我所知,这里没有很好的权威答案.
我可以认为,订单本身是无法创建的,事实上,在规则和无处不在的语言中,据说员工收到订单,员工创建订单……
一个有趣的视角是由Udi大汉编写的:
顾客不是凭空出现的。
他当时的立场是,你会用你已经知道的东西来创造新的东西。
按照他描述的模式,您将得到雇员的内存表示,然后将创建订单并将其添加到适当集合的问题委托给该代码。
尽管如此,我还没有发现像其他DDD作者/影响者/实践者一样表达类似的想法。Udi似乎是在他自己的岛上。
https://softwareengineering.stackexchange.com/questions/444691
复制相似问题