SOA: Contracts, Events, and Ownership
I recently listened to Udi Dahan's excellent "Avoiding a Failed SOA" presentation from QCON London (it is about an hour long, but it is worth your time).
I agree with most of what Udi says except two points. One is that pub/sub is not the only way to go (and you should minimize duplex message). Events and choreography are definitely my preferred way to go since they make it easier to do the right thing -- i.e. model the solution correctly, but I believe orchestration based solution can also work. Maybe I'll expand this in another post -- but the point of this one is on the other point I disagree with.
Udi presents services (which I usually call "business services") which hold within them autonomous components (I usually call these "services"). The solution offered is based on pub/sub (Inversion of communications pattern) so the contract for each component is actually the events/messages it sends. This is inverted to what you'd commonly do with a RPC-induced SOA e.g. usually with a WCF web service the contract includes all the messages the web-service provide. The example in the presentation is that of the Sales service which doesn't own both "Customer status" events and pricing update events even though it processes both but does own Order accepted event which it sends away.
I don't have a problem with the first part, i.e. with services don't owning the events they handle -- but I don't think that it is always wisest to have the services own the events that they send out. I think a better approach is to move the events out to catalogs where each catalog is owned by the business process/entity. what happens with the services owns the messages they get/send is that the business process get fragmented; in this instance, that would be the Order.
The order starts at sales but then get billed someplace else and fulfilled in some other place -- and shipped elsewhere. Consider, for example, the order business entity lifecycle that Jean Jacques Dubray published about a month ago. The transitions defined there don't exactly match those Udi mentions since it is not the same example, but they roughly follow the same process. A catalog would hold all the events related to the entity.
Managing the events out side of the services brings the following benefits:
- Increased visibility both to the business and dev teams. It is easier to explain, manage and even document event flows where the events are not scattered about
- Repeat usage. Several related services can use the same events. For instance a cancel order event can be used both in B2B and B2C scenarios event though the business flows are different. In fact, coupled with context based routing (this is not a typo -- I mean context and not content) you can use the same events within different flows where the context is set by the saga initiator and/or any participating service. Udi gives an example of a large customer that needs a different process from a regular customer, or a perishable goods vs. other goods (needed to be handled differently). If each involved service decorates the events with the context the bus can route it to different participants (or participants can disregard/filter them)
- Easier to make subscription explicit -- not just parsing XML (or JSON etc.) -- if the events are external services that raise the events and services that consume them can bind to the definition without adding too much coupling. There are still places where you want to just parse messages but you have the option not to
- Through a repository into the mix and you can also use this principle for better design and runtime governance. It is harder to do that when tthe events (and messages) are owned by individual services (whether RPCed, or Pub/Subed
For instance most the most important business service in xsights was "Identification" or matching service (take an image and find out what it is). Within it we had quite a few services that make that happen for instance we had several gateways services (get an image by email, from a mobile client or from MMS, from 3G video call). All the gateway services, once they managed to extract the image from the source raised the same event -- a "Frame Arrived" event, which held the image and meta data describing the image. There were also several services that listened for the event some of them like the matching engine were part of the same business service and some, like the statistics collection, part of other business services (you can read a little more about it here)
To sum this up: There are always several ways to skin a cat so, what I am saying here is not an absolute truth or anything. I do however think there's a lot of benefit in decoupling the events ownership from the services that use them and making them explicitly part of the business processes and entities. At mentioned above this helps both the flexibility of the solution and the long term manageability (esp. as the number of events and services grow)
* illustration by shho