Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1

I have been wanting to pull some thoughts together related to my experience of a project I’ll be releasing in a few months that has pulled from all of these hats. The decision to gradually wade into these waters was driven largely by the increased complexity of the behaviors required by this mission-critical system. There were some remarks made either in useful blogs, forums or other venues along the way that would make a particular quandary seemingly less monumental – my hope is that perhaps there are some of those remarks made here to contribute to others possibly investigating an architecture that might benefit from these paradigms.

First, system infrastructure:

  • Monorail MVC web framework
  • Rhino Service Bus for messaging
  • Windows Services hosting the domain and reporting
  • Sql Server 2005 Domain Event storage (the ‘command’ side)
  • NHibernate OR/M helping the Reporting Model that supports the web UI and domain services
  • Driven by TDD/BDD specs using homegrown BDD artifacts

Do Not Skip The Ubiquitous Language

It was somewhat ironic that I felt like the part about “Ubiquitous Language” in Eric Evans’ book was boring. This is mostly due to the fact that I work alone with A subject matter expert that gives requirements out of a gerbil feeding tube for this project. Still my failure to get what he is driving at really bit me and made my system far too complex to understand because a system without a behavioral emphasis is necessarily procedural. Even with neato patterns and good OOP the system still felt like it was programmer-centric. It wasn’t until I watched Udi Dahan talk about Making Roles Explicit that I realized what was lacking to help us succeed. This in conjunction with Greg Young’s assertion that a domain consists of behavior, not shape, really made me see that my state-based, data-driven domain needed refinement to scale and adapt.

Specifically, I started thinking how the lab or field construction worker thinks. For example, when they pour concrete into a designated area they Complete The Placement. Yet in the system I had the operation that was the entry point for a Placement into the system called “AddPlacement”. If you were to ask the construction guy “Have you added that Placement yet?”, he’d just say “huh?”. This sounds trivial but the simple movement away from collection-based or procedural naming conventions revolutionized how my specs were driven. This wasn’t just syntactic sugar stroking a geek for cheap goose pimples, this was improved structure and behavioral concerns.

When moving to an Event Driven Architecture I believe the majority of growing pains come from this shift in reasoning about what is actually being done in the system from the user’s perspective versus how it is being implemented by code. A code smell to me now includes the presence of collections-type semantics when defining my events. “AddThis”, “DeleteThat”, “ReplaceThis” – these are the kinds of language that make me wonder if I am thinking too much like a developer working with data. When I fall into this, I pull back and try to reconsider what is really being done for the business. Many answers or suggestions that come from people I have learned to respect are usually reframing the problem into a more semantically correct question, leading to a more meaningful answer. A good example of this was the recent debate about “soft deletes” bandied about in the blogosphere – Udi Dahan weighed in with advice that I felt remembers the original problem; namely, how would a user of the application define the operation?

Relying on domain events for building up state in the domain is a lot like installing bright lights in an apartment that you need to clean thoroughly to get your deposit back– suddenly you see the parts you have been overlooking. Changing state in a system that is using event sourcing seems to reveal these little shortcuts of thinking that open up doors of opportunity for both the end user and you. Making transitions in the system explicit with meaningful names derived from the business vernacular, not the technological, suddenly makes intent clearer and the paths through the system clearer – something Event Driven architectures need.

Today I found myself slipping back into events like “ElutriationCalculatedEvent”, “WeightPassChangedEvent” and so on. When I started using the vernacular of the docs my business people are using,though, I used names like “ElutriationDeterminedEvent”. This seems trivial, but no one in a lab “Calculates” the material left over from washing – they “determine” it and that informs other observations. When I think along these terms, my code inevitably becomes richer and my conversations more natural with the business people. As an aside, I felt a recent post by Russell Ball really hit the nail on the head with the programmer’s responsibility for concise language in this regard.

 

References

Posted 05-06-2010 12:50 AM by Michael Nichols

[Advertisement]

Comments

Paco wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-06-2010 5:21 AM

What are you going to do with NHibernate on the query side?

Michael Nichols wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-06-2010 12:55 PM

@Paco

I am only using it in my denormalizers and it helps me read in my Web.Reporting repositories. I could go raw ado.net too.

Josh wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-06-2010 10:14 PM

I'd be interested to know specific details about how and when you translate your commands into a denormalized relational representation in sql server for the query side.

Mike wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-06-2010 11:24 PM

@Josh

My commands are handled by a Windows Service that act on the domain. Currently, all bounded contexts sit in the same process but they don't have to.

When the Unit of Work is committed, domain events are emitted. There are two options here:

1. Publish the events via some asynch bus and have a separate windows service handle the denorm there.

2. Publish the events synchronously, probably using a bus but in the same scope.

I am currently porting from #2 to #1. Does that answer your question?

Paco wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-07-2010 6:39 AM

I wonder why you use multiple reporting repositories with NHibernate. Isn't it more code with NHibernate than without? With using multiple repositories, I think you mean that the reporting queries are not just GetReport<TReport>(object reportId), but other things else well. Like what?

Arnis L. wrote re: Notes From A Project Applying Domain-Driven Design, Event Sourcing and CQRS : Part 1
on 05-09-2010 1:35 PM

I'm not sure if it's just me but I think that CQRS and event sourcing are quite simple stuff. Real hard nut is domain driven design. Recently finished reading 'Das Book' second time and I'm sure that I will go through it ~next year once more.

Looking forward to follow these posts, Mike.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)