NServiceBus: Distributing Event Schema/Contract
In SOA, events facilitate loose coupling. One of the primary tenets of SOA is that services define schema and contract not class or type. For this reason it is good to keep the event definitions separate from your code. In fact, Udi recommend keeping this separation to the utmost—by having totally separate source control repositories for the event definitions and another for the service implementation.
One issue that we’ve experienced in strongly typed, compile-time friendly .NET land is that of dependency versioning. For example, if you reference version 1.0 of an assembly and I reference version 1.5 of an assembly and both our bits of code are running together in the same process, we’re in for a heap ‘o trouble—some of which usually isn’t found until runtime.
To a very large extent SOA is able to mitigate most of these issues because things are separated cleanly. But there is one remaining NServiceBus-specific issue that we encounter related to binary assembly versioning.
All of our events are required to depend upon NServiceBus’ IMessage contract. I can accept that, even if I wish I didn’t have to. But that’s okay, a lot of NServiceBus magic comes when I implement that marker interface.
The issue is that, when I compile my events down to an assembly, they are compiled against a specific version of NServiceBus—in our case 2.0. The purpose of compiling the events down to an assembly is so that other business services can reference the assembly and respond to those events. Herein lies the problem. What happens if my business service uses NSB 2.0 while the other business service relies upon NSB 2.5? In this situation, my dependency upon an “older” version of NSB has caused problems for the other business service.
One possible solution is to always use the latest version of NServiceBus. The only problem with that is, I would like to be able to upgrade things independently. In other words, I would like to be able to have different services be truly independent of one another.
So here’s the solution. Don’t provide your events in binary form. In this way others can reference your schema without having to take a dependency upon whatever version of NSB you compiled against.
There are a number of ways to distribute your schema. One very good way is to publish the generated XSD files from your events. One other potential way is to publish the actual source code for your events. The way we’ve started doing this is having Business Service A have a reference to the repository for the events for Business Service B. Then each component that subscribes to an event just references the necessary event definition (in C# form). The name and schema of the event are the same and the component in Business Service A already has a reference to NSB—even if it’s a completely different version.
The bottom line in all of this is that we avoid any kind of dependency upon a specific version of NServiceBus.
How does everyone else publish their event schema for other business services to use?