最近,我开始了一个带有现有数据库(Oracle)和MVC 4的项目。但代码中没有“策略”。只有DB -> ORM ->控制器。因此,我试图在开发中添加一些耀斑,并练习一些DDD开发技术。
我定义了几个聚合根,每个根都有一个存储库,负责保存它们和删除(以及它们的子类)等等。其中一个聚合根引用另一个聚合根,并通过它处理它的“子对象”。
示例:
A Client has one or more purchase orders which has Line Items,
if a client wants to add a line item to the purchase order,
it has to go through the purchase order.那很好..。客户聚合根,采购订单聚合根。
现在,一些服务也出现了,比如一个修改定购订单状态的服务,它从定购订单AR中消除了负担,而且它又干净又有目的(它可以被其他“东西”用来更新购买订单的状态),(也许这应该是定购订单AR的一部分?一个次要的细节.)
存储库目前正在做的工作是持久化数据库中的数据,并用数据“填充”AR。当AR“保存”它时,存储库保存任何需要保存的东西。客户AR使用购买订单库,因此客户端可以加载它可能包含的任何采购订单。希望我在正确的轨道上。
现在,进入MVC。因此,我还得到了一些ViewModels,它基本上是显示需要向用户输出哪些内容的定义。Automapper已经被证明是非常棒的,所以我可以“自动映射”到视图模型。不需要大脑,完美..。
现在,具体的实现细节真的让我失望了..
控制器目前正在通过客户端工厂( Client )工作,该工厂返回一个客户端AR,然后客户机AR可以执行采购订单列表控制器需要执行的任何操作,即管理关联的采购订单(作为一个整体,而不是本例中的采购订单详细信息或数据)。
所以现在我想确定这是正确的..。因为我看到的许多例子都让控制器使用存储库,而不是工厂,但我也看到一些工厂被推荐用于创建AR的。这使我相信,在示例中,控制器处理的是聚合根,但这种方式要求“使用者”必须查询AR才能获得AR:
比如:
Get the Client Aggregate where the ClientID is 15或者更好的是:
get the Client Aggregate, where the ClientID is 15
and where active purchase orders > 0 ...or something..看起来可能是:
ClientAR = ClientRepository.GetClientByIDAndHasActivePurchaseOrders(15);
resultsImLookingFor = ClientAR.PurchaseOrders(); //or something我觉得在这种情况下,存储库会将ClientAR“填充”到我的需要中,所以现在我有了这个ClientAR东西,根据它的使用情况而有所不同,它对我来说很难闻。
使用工厂“感觉更好”,因为我只是从工厂创建一个ClientAR,然后使用它,它不会根据情况而改变。这就是它是..。
ClientAR = ClientFactory.CreateClient(15) // returns a ClientAR
resultsImLookingFor = ClientAR.GetPurchaseOrdersByStatus(statusID);或者我完全错过了,我应该这么做::
ClientAR = ClientRepository.GetClientByID(15, PurchaseOrderSpec)我是不是漏掉了东西的规格方面?(在这一点上,我还没有足够的时间去处理规范,因为我需要让这些东西发挥作用)
我正在努力避免陷入实施细节的泥潭,因为我的老板当然不关心我是如何做到的。到目前为止,通过至少考虑DDD (希望我得到它)来实现一些事情已经被证明是非常好的,因为这种“模式”或“思维方式”产生于这种“模式”或“思维方式”,我想我应该这样说。
那么,我正确地处理了这个问题吗?如果有争议的话,我同意.如果这是完全错误的,那么指导是肯定的,如果我离得太远,如果有充分的理由,建设性的批评不会伤害我的感情。
提前谢谢。
发布于 2013-02-06 04:40:20
因此,我试图在开发中添加一些耀斑,并练习一些DDD开发技术。
对于一个项目来说,Flare通常不是一个理想的质量,可能会适得其反,导致缩略语驱动的开发、恢复驱动的开发等等。DDD也是如此--不要在不了解缺点的情况下尝试应用DDD战术模式。
这些聚合根中的一个引用另一个聚合根
ARs之间的引用应该仅限于标识引用,而不是在可能的情况下对象引用。AR应该定义一个一致性边界,这不一定会导致一个以最自然的方式反映现实的模型。表达客户端和PO之间的关系可以通过身份引用来完成-- PO在其上有一个客户机ID。有关这方面的更多信息,请看一下Vaughn Vernon的有效集料设计。
也许这应该是定购订单AR的一部分?
实体状态的任何修改都应该由实体封装。域服务可以向实体提供功能,如果该功能自然不适合现有实体的话。
存储库目前正在做的工作是持久化数据库中的数据,并用数据“填充”AR。当AR“保存”它时,存储库保存任何需要保存的东西。客户AR使用购买订单库,因此客户端可以加载它可能包含的任何采购订单。希望我在正确的轨道上。
AR或实体或值对象都不应引用存储库或调用其上的任何方法。应用程序服务应该调用存储库。客户端AR不太可能包含POs集合。相反,PO存储库应该提供客户端PO的列表。关系仍然存在,它只是用存储库而不是对象遍历来实现。原因可以追溯到AR是一个一致性边界。
控制器目前正在通过客户端工厂工作
工厂应该只用于创建新实例,而不是访问持久化实例--这就是存储库的目的。您可以通过几种方式构建表示层(MVC)。一个典型的DDD体系结构是拥有控制器引用应用程序服务。应用服务反过来通过协调存储库、工厂、基础设施服务和在ARs上调用行为来实现特定的用例。假设您有一个客户端创建新PO的用例。代码看起来类似于:
public ActionResult CreatePurchaseOrder(CreatePurchaseOrderViewModel viewModel)
{
var poData = viewModel.CreatePurchaseOrderData();
this.purchaseOrderAppService.CreatePurchaseOrder(viewModel.ClientId, poData);
return RedirectToAction("Index");
}
...
public class PurchaseOrderAppService
{
readonly IClientRepository clientDb;
readonly IPurchaseOrderRepository poDb;
public void CreatePurchaseOrder(int clientId, PurchaseOrderData poData)
{
var client = this.clientDb.Get(clientId);
var purchaseOrder = PurchaseOrderFactor.Create(client, poData);
this.poDb.Add(purchaseOrder);
this.poDt.Commit(); // committing of Unit of Work should be moved up to infrastructure level
}
}看看这个DDDSample.Net项目,它包含一个DDD项目的MVC UI实现。
https://stackoverflow.com/questions/14719580
复制相似问题