Tweeted twitter.com/StackSoftEng/status/927068564418375680
2 added domain event thought
source | link

Getting things right

Of course, I am not going to get things right first time. But this is me rewriting an existing system as I truly believe in DDD for complex systems. The previous one was a .NET Entity Framework solution, that essentially was driven using Entity Framework, with business logic scattered throughout the application. I horrible BBoM and some spaghetti code - and hard to unit test. I decided on applying the DDD learning to the domain I am somewhat familiar with. Its getting the Strategy right, then trying to apply the Tactical patterns that I need to get experience with.

I have already gone through countless iterations of classes. I have a nice set of value types. But its the time to glue the use cases/processes together.

So the key thing here is how to "model" the process of the Inspection of the Product.

  • Does the aggregate approach I have demonstrated fit the scenario?
  • Would a Domain Service be a better fit?
  • Maybe Domain Events would be a better fit as I am saying something has happened?
  • Thinking performance - should aggregates load all of their children for a scenario?
  • If Product created one Bounded Context, with a lot more properties that I have put in the example, from what I understand, in the Bounded Context where it is also consumed, it is another view from that Bounded Context, although represented differently, it would be fine just to define the data that was required.

So the key thing here is how to "model" the process of the Inspection of the Product.

  • Does the aggregate approach I have demonstrated fit the scenario?
  • Would a Domain Service be a better fit?
  • Thinking performance - should aggregates load all of their children for a scenario?
  • If Product created one Bounded Context, with a lot more properties that I have put in the example, from what I understand, in the Bounded Context where it is also consumed, it is another view from that Bounded Context, although represented differently, it would be fine just to define the data that was required.

Getting things right

Of course, I am not going to get things right first time. But this is me rewriting an existing system as I truly believe in DDD for complex systems. The previous one was a .NET Entity Framework solution, that essentially was driven using Entity Framework, with business logic scattered throughout the application. I horrible BBoM and some spaghetti code - and hard to unit test. I decided on applying the DDD learning to the domain I am somewhat familiar with. Its getting the Strategy right, then trying to apply the Tactical patterns that I need to get experience with.

I have already gone through countless iterations of classes. I have a nice set of value types. But its the time to glue the use cases/processes together.

So the key thing here is how to "model" the process of the Inspection of the Product.

  • Does the aggregate approach I have demonstrated fit the scenario?
  • Would a Domain Service be a better fit?
  • Maybe Domain Events would be a better fit as I am saying something has happened?
  • Thinking performance - should aggregates load all of their children for a scenario?
  • If Product created one Bounded Context, with a lot more properties that I have put in the example, from what I understand, in the Bounded Context where it is also consumed, it is another view from that Bounded Context, although represented differently, it would be fine just to define the data that was required.
1
source | link

DDD - Domain Modelling association between aggregates

I have a bit of a mental block when trying to model my scenario whilst practicing DDD.

The problem appears to be around 2 entities you would consider to be aggregate roots. I feel these aggregate roots would be an aggregate root in their own respective bounded context.

Essentially, I have complex rules to apply in this scenario. I've tried to simplify this with the following scenario:

Scenario

The scenario would be to take a Product. This produce would be put together in a Design context with its various dimensions by the design team.

It would then be assembled on a production line in. The product would exist in a Batch.

Then once Product was assembled, it would be Quality Controlled inspected by an Inspector.

The Inspector would select a number of Products in the batch at random, and would determine if it passes the Quality Control (QC) checks. Something along the lines of is the product width between a minimum and maximum range. He would also perform a visual check of the product.

The Inspector has to be qualified to perform the various checks. Therefore he needs to have a valid Visual QC certificate which is valid to a certain date - before he would need to requalify. He would need a valid Dimension QC certificate to perform dimension checks.

You might have one Inspector doing a Visual check and another Inspector doing the dimension check. For a Product to pass QC, then Visual and Dimension checks will need to be passed. The result of the check is either pass or fail.

Applying DDD Tactical Patterns

So now we come to writing code for the Domain Model. Assuming that the DDD Strategy has been applied successfully, then I currently have:

Design Bounded Context

  • Product Batch Aggregate Root
  • Product Entity

Qualification Bounded Context

  • Inspector Aggregate Root
  • Inspection Certificate Entity

Quality Control Bounded Context

This seemingly needs to bring the concept of the Product/Product Batch and the Inspector together.

I keep running through the Vaughn Vernon's red book and countless online articles, including Udi Dahan's Many to Many.

Do we have a specific Aggregate root at play? I've tried applying Udi's theory to the scenario, so it would feel like the Inspector is the Aggregate root.

But if we need to treat the Aggregate as a whole, would that mean we need to load ALL of the child data? That would be quite an overhead - if it was all Inspections since day one and all qualifications since day one.

So to quickly mock up the model to try and add some clarity - with the primitively obsessed, not really expressive and slightly anaemic approach to quickly show some context:

public class InspectorAggregateRoot
{
    public Guid Id { get; private set; }

    public List<Qualification> Qualifications { get; private set; }

    public List<Inspection> Inspections { get; private set; }

    public void PerformInspection(Product product, InspectionType type, bool hasPassed)
    {
        if (!IsInspectorQualified())
        {
            throw new InvalidOperationException("Inspector is not qualified");
        }

        Inspections.Add(new Inspection
        {
            InspectionDate = DateTime.Now,
            InspectionType = type,
            Pass = hasPassed,
            ProductId = product.Id
        });
    }

    private bool IsInspectorQualified()
    {
        // check inspectors qualifications
        return true;
    }
}

public class Inspection
{
    public Guid ProductId { get; set; }

    public InspectionType InspectionType { get; set; }

    public DateTime InspectionDate { get; set; }

    public bool Pass { get; set; }
}

public enum InspectionType
{
    Visual,
    Dimension
}

public class Product
{
    public Guid Id { get; set; }
    public int Height { get; set; }
    public int Width { get; set; }
    public int Length { get; set; }
}

public class Qualification
{
    public InspectionType InspectionType { get; private set; }

    public DateTime ValidTo { get; set; }
}

NOTE: Yes I deliberately have omitted newing up the lists, not bothered about the anaemic part as this is quick and dirty to highlight the modelling scenario - this isn't about Value objects - yet.

So the key thing here is how to "model" the process of the Inspection of the Product.

Too many questions, but I just want to discuss approaching this and finding a best way to do things.

The questions that spring to mind are:

  • Does the aggregate approach I have demonstrated fit the scenario?
  • Would a Domain Service be a better fit?
  • Thinking performance - should aggregates load all of their children for a scenario?
  • If Product created one Bounded Context, with a lot more properties that I have put in the example, from what I understand, in the Bounded Context where it is also consumed, it is another view from that Bounded Context, although represented differently, it would be fine just to define the data that was required.

Other thoughts are:

  • An Inspector might have 100's of qualifications (ie different Inspection Types not in example)
  • There might be 1000's of products in a Batch
  • There will be lots of Batches over the lifetime of the system.