Domain driven design 一切似乎都是一个聚合的根
我想在一家餐馆里做菜单组成的模型。我仅围绕3个概念创建了一个非常小的有界上下文:Domain driven design 一切似乎都是一个聚合的根,domain-driven-design,Domain Driven Design,我想在一家餐馆里做菜单组成的模型。我仅围绕3个概念创建了一个非常小的有界上下文:菜单,类别,产品 菜单由不同的产品组成,每个菜单中的每个产品都被归入某个类别(例如,“参赛者”、“第一道菜”、“第二道菜”、“甜点”…) 问题是,在我看来,一切似乎都是一个实体 例如,删除菜单时,不会删除任何产品或类别。其他3个概念也会发生同样的情况 关于UI,菜单将像层次结构一样使用: Menu1 Category1 Product1 Product2 Categor
菜单
,类别
,产品
菜单由不同的产品组成,每个菜单中的每个产品都被归入某个类别(例如,“参赛者”、“第一道菜”、“第二道菜”、“甜点”…)
问题是,在我看来,一切似乎都是一个实体
例如,删除菜单时,不会删除任何产品或类别。其他3个概念也会发生同样的情况
关于UI,菜单将像层次结构一样使用:
Menu1
Category1
Product1
Product2
Category2
Product3
Product4
我想知道如何建模。我应该把它们做成3块吗?那么,为了像上面的层次结构一样被消费,一个用户应该如何组成一个菜单呢
谢谢。如果您有一个菜单作为当前安排的聚合根目录,那么如果您想在不同的菜单上重复使用相同的产品,会发生什么情况?从聚合根外部,您将无法保存对它的引用 相反,我认为将菜单和产品(问厨师他会如何称呼食物或菜单项!)作为聚合根是很好的,因为它们都存在并且有自己的特性(随着时间的推移,你可能会有不同的菜单,一个菜单可能由其他菜单上使用过的食物组成) 将类别作为价值对象可能更合适(同样,也许厨师会称之为课程?)-您有多少类别(我相信这些课程可能是固定的)?类别是否有自己的生命周期和身份?每个产品上的可枚举项可以很好地满足这一要求 你还提到删除。。。这听起来像是一个技术基础设施术语。这有两个问题:
public Object HandleGetMenuCommand(
string menuName,
IMenuRepository menuRepository,
ProductRepository productRepostiory)
{
Menu menu = menuRepository.Get(new MenuId(menuName));
List<ProductIds> productsInMenu = menu.Products;
List<Products> products = productRepostiory.GetMany(productsInMenu);
List<string> categories = ... // get a list of unique categories from products
// now assemble products by category...
foreach(var category in categories)
{
var productsInCategory in products.Find(x => x.Category == category);
foreach(var product in productsInCategory)
{
// add this to a list...
}
}
var clientData = new {
name = menu.Name,
// add in the products that were assembled by category above
}
return clientData;
}
公共对象HandleGetMenuCommand(
字符串menuName,
IMenuRepository menuRepository,
产品存储库(ProductRepository)
{
Menu Menu=menureposition.Get(新的MenuId(menuName));
列出产品菜单=菜单.产品;
列出产品=ProductRepository.GetMany(productsInMenu);
列表类别=…//从产品中获取唯一类别的列表
//现在按类别组装产品。。。
foreach(类别中的var类别)
{
var productsInCategory在products.Find中(x=>x.Category==Category);
foreach(productsInCategory中的var产品)
{
//将此添加到列表中。。。
}
}
var clientData=new{
name=menu.name,
//添加按上述类别组装的产品
}
返回clientData;
}
我认为您试图在DDD中投入太多的精力,而不是仅仅通过观察“现实世界”来关注这个领域的简单性。请让我先用一种简单的OO方法,然后再谈谈如何使用DDD来看待它。
所以你想要菜单,这样餐馆的顾客可以看菜单,选择他们想吃的任何东西。让我们假设现在每个工作日只有一份午餐、晚餐的菜单。
餐厅经理应该能够创建此菜单,并随时更改它。
这是我们的第一个用例
menu = new Menu("monday lunch", starters, mainEntrees, desserts, drinks);
其中每个参数都是值对象列表(乍一看)。
只要看看现实世界,菜单就是对你在餐馆里能吃到的食物的描述,这些描述是不可变的对象(价值对象),到目前为止,我们不需要任何其他东西。
目前,我们只有一个聚合根,即菜单。它具有全局标识,并对一组对象进行分组,并且具有不变量。我将使用哪个类来建模主菜、甜点?字符串…到目前为止,一个字符串实例就足够了。
菜单呢?我们可以有很多菜单,一个是星期一的,一个是星期二的,一个是星期五晚上的等等,每个菜单都有自己的全球标识,所以我们可以确定菜单的位置。
如果餐厅经理想增加一种新的甜点呢
menu = menuRepository.get(menuId);
menu.add(aDessert);
够了。
到目前为止,我们只有一个菜单聚合根及其存储库。
我想这是你问的
然而,我认为你错过了价格。菜单上的每一行都有价格,不同菜单上的两个相同的甜点如果是午餐或晚餐可能有不同的价格,因此更现实的方法似乎是:
menu = new Menu("monday lunch", starters, mainEntrees, desserts, drinks);
其中,开胃菜、主菜、甜点、饮料都是MenuLine类型的集合。
现在,如果客户告诉服务员给他带点吃的东西,会发生什么?需要创建一个新订单,以保持客户要求的进度,以便稍后创建发票。
此订单需要知道客户要求的食物,我是指客户点的菜单项。到目前为止,我们正在使用价值对象对甜点、饮料等进行建模。现在,我们应该为客户可以选择的选项提供某种形式或标识符,以便我们在订单上下文(如订单)中使用某些唯一标识符。这是我们决定需要另一个聚合根(你称之为产品)的地方。我更愿意称之为食物或类似的东西。
那么什么时候
food = new Food("sushi");
foodRepository.add(food);
food = foodRepository.getBy(foodId);
menu = menuRepository.findByCriteria(mondayNight)
menu.addAt(food, tenDollars);
addAt(food, tenDollars) {
mainEntrees.add(new MenuItem(food.id, food.description, tenDollars)
}
Menu {
List starters;
List entrees;
List desserts;
List drinks;
}