Friday, July 6, 2012

Domain Events and Domain Events

My friend Alessandro is building something really really interesting around DDD concepts, go and take a look (it’s in Italian).

Following up to his series of posts I’d like to analyze some concepts behind domain events, if you recall when we spoke about WS-Federation on top of NServiceBus we started using the following picture to summarize to flow:

image3

Keep your eyes on the domain portion of the above picture, we basically have some logic (domain logic) running that when finished raises a domain event that carries with itself all the relevant information so that the event itself is consistent and an eventual listener does not need any other resource to understand what has happened.

note: everything is in the past, “ed”, a domain event represents something that has happened, something that immutable and that have absolutely no behavior, the past cannot be altered in any way; all what you can do is to try to compensate something you do not really like that is happened.

Given that an event is something immutable is quite natural to represent an event using a class with only read-only properties such as the following:

class CustomerNameChanged
{
    public CustomerNameChanged( String customerId, String oldCustomerName, String newCustomerName )
    {
        //set properties using .ctor values
    }
    public String CustomerId{ get; private set; }
    public String OldCustomerName{ get; private set; }
    public String NewCustomerName{ get; private set; }
}

now imagine that we need to publish the “same” event to the outside world…we need to face a couple of problem(s):

the class is serializable but not deserializable; private setters prevent the serialization engines to set the properties;

this is a problem that can be circumvented, obviously, for example introducing some custom serialization steps. With NServiceBus (since we are sending the event to the outside world) injecting logic in the serialization process is a bit tricky, to say, because they use a completely custom serialization engine that does not honor the serialization attributes nor the serialization interfaces…but…

Is this a real problem? or is a smell…?

let’s move to the second problem, leaving the first one aside for a while, the question is: if we send something to the outside world is it the same something? In order to answer the question imagine something a bit more complex (or a bit more real world) such as the following event:

class InvoicePaid
{
    public DateTimeOffset PaidOn{ get; private set; }
    public String InvoiceNumber{ get; private set; }
    public String IssuerId{ get; private set; }
    public String PaidUsingBankAccountNumber{ get; private set; }
    public String AuthorizedBy{ get; private set; }
    public TimeSpan PaymentDelay { get; private set; }
}

Nothing really complex, now imagine that we need to publish the “same” event to the outside world, is it the same event? or it something much more similar to

class InvoicePaid
{
    public DateTimeOffset PaidOn{ get; private set; }
    public String InvoiceNumber{ get; private set; }
    public String IssuerId{ get; private set; }
}

where we remove internal/confidential information useless, or worse dangerous, for the outside world?

I suppose that we all agree that those are two different events, that communicate a similar concept.

Now…

This neat separation gives us a huge power: evolution. The application can evolve changing the structure of its own domain events without affecting in any way the external “listeners” that have a completely different event to listen to. But we still have a couple of problems to solve:

  • one is still related to coupling;
  • the other one is the deserialization of the private properties;

stay tuned, something is going to happen…

.m

1 comment:

  1. I completely agree,

    Probably the field IssuerId is interesting in that Bounded context, but when it is time to communicate to external world it could be also a little bit denormalized, like IssuerId and IssureName, etc etc.

    Decoupling internal Domain Event from that one that goes to the outside world is really an interesting concept.

    ReplyDelete