fredag 18. februar 2011

A layer of abstraction or a layer of complexity

To me abstraction rarely has to do with technical issues alone. When writing a layer of abstraction the domain plays a huge role. I find this specific issue is often handled badly with ORM's. A relational database especially is rarely modeled in a way that reflects domain behaviors. I therefore cringe when I see ORM's used to generate a object mirror of the database schema. Unless it's a pure CRUD app what do we really gain by doing this? Other than database intellisense.

Greg Young threw me a bit of when for some time ago I mentioned using Unit of Work and he replied “why do you need that?”. I frankly didn't even understand the question. Why would I not need a Unit of Work? I now know the answer and it makes me sad. I never knew what an aggregate was about and frankly I never really paid attention to the problem I was trying to solve. I never included the domain into the actual solution.

When doing something like generating an object version of a relational database we state that “I have no idea what this thing is supposed to do so I'll support everything”.Instead of first getting an understanding of the domain behaviors and create a persistence model supporting those scenarios.

Back to what Greg said. Why don't we need a Unit of Work? Because we have modeled true behaviors. Unit of Work is solving transactional issues. Actually Unit of Work is there to handle transactions between aggregates. The reason we tend to use a Unit of Work is because we have paid no attention to what an aggregate should contain. If we have an object model that is generated from a database schema our aggregates are defined by our database relations. Because of that our aggregates are completely separated from our domain behaviors. Resulting in most domain behaviors touching more than one aggregate. And through that we are forced to use a Unit of Work. However if we take the time to model our aggregates based on actual behavior there would be no need for cross aggregate transactions. Actually what we are doing when not paying attention to domain behaviors is creating and impedance mismatch between the problem we are trying to solve and our technical implementation.

If you want to learn more about these type of concepts visit http://cqrsinfo.com/. And if you get the time today. Greg is doing an online session today (http://cqrsweekday.eventbrite.com/). There is still time! If you can attend you should! You will not regret it.

2 kommentarer:

  1. For me, the need for unit of work wasn't comming from crossing aggregate boundaries. It was rather because some of my aggregates spanned multiple tables. I needed transactions for atomicity reason.
    So, assuming RDBMS, can you avoid transactions (when NOT using event sourcing)? One option is serializing the aggregate and storing that JSON/XML... But is it worth?

    SvarSlett
  2. Using a transaction within an aggregate when persisting it is perfectly fine. The scope of that transaction would be fixed to the content of the aggregate. The Unit of Work on the other hand is dynamic. You can register any entity with it and have it persist them within the same transaction.
    Theoretically with a Unit of Work you can generate payroll information and book a purchase within the same transaction. Even though they are not related. The Unit of Work is more of a generic transaction handler.

    SvarSlett