0

Sorry in advance if this question is unclear. Please tell me what to change to make it a better question.

I am currently maintaining a C# WinForm system where I'm trying to learn and use DDD and CQRS principles. Vaughn Vernon's Implementing Domain Driven Design is my main DDD reference literature.

The system currently uses legacy code which makes use of Data Aware Controls. In the Asset Inventory Context, i have designed my aggregate root Asset which composes of multiple valueObjects which are standard entries in the system:

Asset Entity

In this Context, i'm trying to implement a use case where the user can manually register an Asset to the system.

My current implementation is the following:

From Presentation Layer:

Upon loading the RegisterAssetForm.cs it loads the existing standard entry lists of Group, ItemName, etc. through the Data Aware controls, all consisting of data rows with columnsid: int and name: string.

When the user selects the desired ItemName, Group, PropertyLevel, Department, and Category, then clicks save, a command is performed:

RegisterAssetForm.cs

...
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);
    ...
}

From Application Layer:

The AssetInventoryApplicationService depends on domain services.

AssetInventoryApplicationService.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);
    ...
}

From Domain Layer:

AssetFactory.cs //not my final implementation

...
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);   
    }
...
}

Sample table of what fills my value objects

+------------+--------------+
| CategoryID | CategoryName |
+------------+--------------+
|          1 | Category1    |
|          2 | Category2    |
|          3 | Category3    |
|          4 | Category4    |
|          5 | Category5    |
+------------+--------------+

I know domain models must be persistence-ignorant that's why i intend to use surrogate identites (id field) in Layer Supertype with my valueobject to separate the persistence concern from the domain.

The main property to distinguish my value objects is their Name

From the presentation layer, i send the standard entry value as integer id corresponding to primary keys through a command to the application layer which uses domain services.

Problem

    * Is it right for me to pass the standard entry's id when creating the command, or should I pass the string name?
    * If id is passed, how do i construct the standard entry value object if name is needed?
    * If name is passed, do i need to figure out the id from a repository?
    * Or am I simply designing my standard entry value objects incorrectly?

Thanks for your help.

  • Possible duplicate of [Loading a Value object in List or DropdownList, DDD](https://stackoverflow.com/questions/5478253/loading-a-value-object-in-list-or-dropdownlist-ddd) – guillaume31 Mar 08 '18 at 09:07

1 Answers1

1

It looks to me that you may be confusing a Value Object and an Entity.

The essential difference is that an Entity needs an Id but a VO is a thing (rather than a specific thing). A telephone number in a CRM would likely be a VO. But it would likely be an Entity in if you are a telephone company.

I have an example of VO in this post which you may find helpful - you can get it here

To answer your 'Problems' more specifically:

  1. If you are creating some entity then it can be advantageous to pass in the id to a command. That way you already know what the id will be.
  2. You shouldn't be able to create an invalid value object.
  3. Why can't you pass in the name and the ID? Again - not sure this is relevant to a Value Object
  4. I think you have designed them incorrectly. But I can't be sure because I don't know your specific domain.

Hope this helps!

Codescribler
  • 2,235
  • 18
  • 22
  • Actually my main domain is the Asset entity. the value objects (group, etc.) describes my Asset entity and is required when building it. Yes the value objects have an id but it doesn't mean it is its identity. although i do need those id for my data model, that's why i thought of using a Layer supertype as described in the DDD book. 1. I'm creating a value object not an entity but i understand your point here. 2 & 4. This was very helpful and i'm probably gonna need to redesign my models. 3. Are there best practices in terms of the parameters passed/included in a command? – Mikhail Peralta Mar 08 '18 at 04:35