我正确地设计和构建我的值对象吗?

时间:2018-03-07 13:39:40

标签: domain-driven-design cqrs value-objects

如果此问题不明确,请提前抱歉。请告诉我要改变什么以使其成为更好的问题。

我目前正在维护一个C#WinForm系统,我正在尝试学习和使用DDD和CQRS原则。 Vaughn Vernon的实施领域驱动设计是我的主要DDD参考文献。

系统当前使用遗留代码,该代码使用数据感知控件。 在资产清单上下文中,我设计了我的聚合根Asset,它由多个valueObjects组成,这些valueObjects是系统中的标准条目:

Asset Entity

在此上下文中,我正在尝试实现用户可以手动向系统注册Asset的用例。

我目前的实施如下:

来自表示层:

加载RegisterAssetForm.cs后,它会通过Data Aware控件加载GroupItemName等现有的标准条目列表,所有控件都包含列{{1}的数据行}和id: int

当用户选择所需的name: stringItemNameGroupPropertyLevelDepartment,然后点击保存,执行命令:

RegisterAssetForm.cs

Category

从应用层:

... AssetInventoryApplicationService _assetInventoryServ; ... void btnSave_Click(object sender, EventArgs e) { int itemNameId = srcItemName.Value // srcItemName is a custom control whose Value = datarow["id"] int groupId = srcGroup.Value; string categoryId = srcCategory.Value; string departmentId = srcDepartment.Value; string propLvlId = srcPropLevel.Value; ... RegisterAssetCommand cmd = new RegisterAssetCommand(itemNameId, groupId, categoryId, departmentId, propLvlId); _assetInventoryServ.RegisterAsset(cmd); ... } 取决于域名服务。

AssetInventoryApplicationService.cs

AssetInventoryApplicationService

来自域层:

AssetFactory.cs //不是我的最终实施

...
IAssetRepository _assetRepo;
...
public void RegisterAsset(RegisterAssetCommand cmd)
{
    ...
    AssetFactory factory = new AssetFactory();
    AssetID newId = _assetRepo.NextId();
    Asset asset =  factory.CreateAsset(newId, cmd.ItemNameId, cmd.PropertyLevelId,
        cmd.GroupId, cmd.CategoryId, cmd.DepartmentId);

   _assetRepo.Save(asset);
    ...
}

填充我的值对象的示例表

...
public class AssetFactory
{
...
    public Asset CreateAsset(AssetID id, int itemNameId, int propLvlId, int groupId, int categoryId, int departmentId)
    {
        ItemName itemName = new ItemName(itemNameId);
        PropertyLevel propLvl = new PropertyLevel(propLvlNameId);
        Group group = new Group(groupNameId);
        Category category = new Category(categoryNameId);
        Department department = new Department(departmentNameId);

        return new Asset(id, itemName, propLvl, group, category, deparment);   
    }
...
}

我知道域模型必须是持久性 - 无知的,这就是为什么我打算在 Layer Supertype 中使用代理身份(id字段)和我的valueobject将持久性问题与域名。

区分我的值对象的主要属性是名称

从表示层,我通过命令将标准条目值作为与主键对应的整数id发送到使用域服务的应用层。

问题

    *我在创建命令时传递标准条目的id是正确的,还是应该传递字符串名称?
    *如果传递了id,如果需要名称,如何构造标准条目值对象?
    *如果传递了名称,我是否需要从存储库中找出id?
    *或者我只是错误地设计我的标准入口值对象?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在我看来,您可能会混淆价值对象和实体。

本质区别在于实体需要Id,但VO是一种东西(而不是特定的东西)。 CRM中的电话号码可能是VO。但如果你是一家电话公司,它可能会成为一个实体。

我在这篇文章中有一个VO示例,您可能会发现它很有用 - you can get it here

回答您的问题'更具体地说:

  1. 如果您正在创建某个实体,那么将id传递给命令会更有利。这样你就已经知道了id是什么。
  2. 您不应该能够创建无效的值对象。
  3. 为什么不能传递姓名和身份证明?再次 - 不确定这是否与值对象相关
  4. 认为你错误地设计了它们。但我无法确定,因为我不了解您的特定域名。
  5. 希望这有帮助!