选项 2 肯定会导致程序代码。
可能更容易开发,但更难维护。
现在在现实世界中,这是一项纯粹的管理任务
“管理”任务应该是私有的,并通过公共的、完全“域的”操作调用。最好 - 仍然用易于理解的代码编写,这些代码是从域驱动的。
正如我所看到的 - 问题是这UndoLastStatus
对领域专家来说毫无意义。
他们更有可能在谈论制作、取消和填写订单。
这些方面的东西可能更适合:
class Order{
void CancelOrder(){
Status=Status.Canceled;
}
void FillOrder(){
if(Status==Status.Canceled)
throw Exception();
Status=Status.Filled;
}
static void Make(){
return new Order();
}
void Order(){
Status=Status.Pending;
}
}
我个人不喜欢使用“状态”,它们会自动共享给所有使用它们的东西——我认为这是不必要的耦合。
所以我会有这样的事情:
class Order{
void CancelOrder(){
IsCanceled=true;
}
void FillOrder(){
if(IsCanceled) throw Exception();
IsFilled=true;
}
static Order Make(){
return new Order();
}
void Order(){
IsPending=true;
}
}
为了在订单状态更改时更改相关内容,最好的办法是使用所谓的域事件。
我的代码看起来像这样:
class Order{
void CancelOrder(){
IsCanceled=true;
Raise(new Canceled(this));
}
//usage of nested classes for events is my homemade convention
class Canceled:Event<Order>{
void Canceled(Order order):base(order){}
}
}
class Customer{
private void BeHappy(){
Console.WriteLine("hooraay!");
}
//nb: nested class can see privates of Customer
class OnOrderCanceled:IEventHandler<Order.Canceled>{
void Handle(Order.Canceled e){
//caveat: this approach needs order->customer association
var order=e.Source;
order.Customer.BeHappy();
}
}
}
如果 Order 变得太大,您可能想看看有界上下文是什么(正如 Eric Evans 所说 - 如果他有机会再次写他的书,他会将有界上下文移到最开始)。
简而言之 - 它是一种由域驱动的分解形式。
想法相对简单 - 从不同的观点(即上下文)拥有多个订单是可以的。
例如 - 来自购物上下文的订单,来自会计上下文的订单。
namespace Shopping{
class Order{
//association with shopping cart
//might be vital for shopping but completely irrelevant for accounting
ShoppingCart Cart;
}
}
namespace Accounting{
class Order{
//something specific only to accounting
}
}
但是通常足够多的域本身可以避免复杂性,并且如果您足够仔细地听它,它很容易分解。例如,您可能会从专家那里听到诸如 OrderLifeCycle、OrderHistory、OrderDescription 之类的术语,您可以利用这些术语作为分解的锚。
注意:请记住 - 我对您的域的了解为零。
我使用的那些动词很可能对它完全陌生。