Domain driven design 我是否正确地设计和构建我的价值对象?

Domain driven design 我是否正确地设计和构建我的价值对象?,domain-driven-design,cqrs,value-objects,Domain Driven Design,Cqrs,Value Objects,如果这个问题不清楚,请提前道歉。请告诉我如何改变,使之成为一个更好的问题 我目前正在维护一个C WinForm系统,我正在尝试学习和使用DDD和CQRS原理。Vaughn Vernon的实现领域驱动设计是我的主要DDD参考文献。 该系统目前使用传统代码,该代码使用数据感知控件。 在资产库存上下文中,我设计了我的聚合根资产,它由多个ValueObject组成,这些ValueObject是系统中的标准条目: 在此上下文中,我尝试实现一个用例,用户可以手动向系统注册资产 我目前的执行情况如下: 从表示

如果这个问题不清楚,请提前道歉。请告诉我如何改变,使之成为一个更好的问题

我目前正在维护一个C WinForm系统,我正在尝试学习和使用DDD和CQRS原理。Vaughn Vernon的实现领域驱动设计是我的主要DDD参考文献。 该系统目前使用传统代码,该代码使用数据感知控件。 在资产库存上下文中,我设计了我的聚合根资产,它由多个ValueObject组成,这些ValueObject是系统中的标准条目:

在此上下文中,我尝试实现一个用例,用户可以手动向系统注册资产

我目前的执行情况如下:

从表示层: 加载RegisterAssetForm.cs后,它通过数据感知控件加载组、项名称等的现有标准条目列表,所有这些控件都由columnsid:int和name:string的数据行组成。 当用户选择所需的ItemName、Group、PropertyLevel、Department和Category,然后单击save时,将执行一个命令: RegisterAssetForm.cs

从应用层: AssetInventoryApplicationService依赖于域服务。 AssetInventoryApplicationService.cs

从域层: AssetFactory.cs//不是我的最终实现

填充我的值对象的示例表 我知道域模型必须是持久性无关的,这就是为什么我打算在层超类型中使用带有valueobject的代理标识id字段来将持久性问题从域中分离出来

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

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

问题 *创建命令时,我应该传递标准条目的id吗?还是应该传递字符串名称? *如果传递了id,如果需要名称,如何构造标准条目值对象? *如果传递了name,我是否需要从存储库中找出id? *还是我只是错误地设计了我的标准输入值对象?
谢谢您的帮助。

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

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

我在这篇文章中有一个VO的例子,你可能会发现它很有用-

更具体地回答您的“问题”:

如果您正在创建某个实体,那么将id传递给命令可能是有利的。这样,您就已经知道id是什么了。 您不应该能够创建无效的值对象。 你为什么不能把名字和身份证传进来?再次-不确定这是否与值对象相关 我认为你设计得不对。但我不能确定,因为我不知道你的具体领域。
希望这有帮助

实际上,我的主要领域是资产实体。“值对象”组等描述了我的资产实体,并且在构建它时是必需的。是的,值对象有一个id,但这并不意味着它就是它的标识。虽然我的数据模型确实需要这些id,但这就是为什么我想到使用DDD书中描述的层超类型。1.我正在创建一个值对象,而不是一个实体,但我理解你的观点。2 & 4. 这非常有帮助,我可能需要重新设计我的模型。3.在命令中传递/包含的参数方面是否有最佳做法?可能重复
...
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);
    ...
}
...
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);   
    }
...
}
+------------+--------------+
| CategoryID | CategoryName |
+------------+--------------+
|          1 | Category1    |
|          2 | Category2    |
|          3 | Category3    |
|          4 | Category4    |
|          5 | Category5    |
+------------+--------------+