1

I am looking for some advice on DDD modelling and specifically nested levels of ValueObjects.

Take the below code, this is a dumbed down sample of how my domain is starting to take shape. This is all within my Contracts bounded context and have identified the Contract as the aggregate root. This does make sense based off discussion sessions with the domain expert but I wonder if I am going about this the wrong way.

The issue I have with this nesting is that:

1 - I have now lost the ability to create concise domain events such as TreatyDetailsCreated but instead need to fire events a level above so ContractCreated as an example.

2 - My commands are starting to follow this similar nesting format again causing them to lose clarity

3 - I am now forced to load the Contract each time I am required to update something deep in the graph and that these higher value objects are not required to enforce invariants.

My question is would I be better looking into potentially having my first level nested objects defined as aggreagtes? This would solve my nesting issue and allow me to gain back descriptive domain events. My invariants will only be enforced at the Contract level at the point of submission and will likely be handled within a Domain Service due to the complexities so Contract feels like a logical container more than anything.

public class CreateContractCommand
{
    public CreateTreatyDetails CreateTreatyDetails { get; set; }

}

public class CreateTreatyDetails
{
    public string Umr { get; set; }
}

public class Contract : Aggregate
{
    internal TreatyDetails TreatyDetails { get; private set; }

    private Contract() { }

    public static Contract Create(CreateContractCommand command)
    {
        var contract = new Contract {TreatyDetails = new TreatyDetails(command.CreateTreatyDetails)};

        //Raise domain events

        return contract;
    }
}

public class TreatyDetails : ValueObject
{
    //Additional properties removed for simplicity
    public Umr Umr { get; private set; }

    public TreatyDetails(CreateTreatyDetails createTreatyDetails)
    {
        Umr = new Umr(createTreatyDetails.Umr);
    }
}

public class Umr : ValueObject
{
    public string Value { get; private set; }

    public Umr(string value)
    {
        //Validate value

        Value = value;
    }
}
jonytek
  • 111
  • 2
  • 7

1 Answers1

2

So after spending some time here looking through search results from a 'DDD' query I stumbled across an essay by Vaughn Vernon which has given me pointers to help me continue on my journey.

Based on the content of the essay it have confirmed my suspensions that I should have multiple aggregates. So for my example I will have TreatyDetails and Contract where Contract will have a reference (TreatyDeatilsId) back.

http://dddcommunity.org/library/vernon_2011/

jonytek
  • 111
  • 2
  • 7
  • If treatly details is a value object, then it cannot be an aggregate on his own. An aggregate must have at least one entity (the aggregate root). I don't see any problem in having domain events fired when a vakue object is created. A domain event is just something of interest that happened in the domain. – choquero70 Feb 06 '19 at 21:22