Don't make your domain objects serializable
A while ago I blogged about the dangers of serialization and I mentioned there that serializing your domain objects is bad. I wanted to follow that up with some details on why it's so dangerous, and briefly mention a different approach.
Technologies like web services make it real easy to start serializing objects and then send them to and fro - so serializing an Order object on the server and then sending it to the client application. Simple - I can just write my client app to operate on the domain objects directly, and then send them back to the server. What could go wrong - I can almost pretend it's not a distributed system.
People talk a lot about decoupling but an area often neglected is coherence, in the case of many systems this means putting the business logic that operates on domain objects in the same place. It also often implies ownership - a particular server or tier in the application owns the domain objects and is responsible for mediating access and acting upon them. So why is coherence important?
Suppose I've allowed my Orders, say, to be serialized and sent to others parts of the system. This may not seem important to start with - but as soon as you get multiple components able to change domain objects then synchronisation becomes a big issue. If a component updates it's copy of an Order at the same time as someone else (who also has a serialized copy) then we are going to need some kind of conflict resolution on the server side to work out what the final state of the order should be based on two (now different) copies of the same order. Systems like this have no clear concept of ownership nor, quite often, a clean model of an object's state at any one instance of time. All too often projects using this approach burn a lot of time trying to create fancy conflict resolution algorithms.
Requirement change also becomes a problem, when you serializable domain objects it's very difficult to avoid distributing the business logic. That is manageable to start with, but as you add more functionality or change existing code you need to keep track of all the different components where that change may have impact. The business logic becomes 'smeared' across the system - coherence has been destroyed. A tweak to UI changes the Order object, necessarily because the serialized Order object is being use directly in the UI. A seemingly small change on the server side breaks all the client apps.
We may have used some nice messaging technology and thought we'd ticked the 'decoupled' box, but we've coupled our components together as tightly as if we'd just done RPC. If you don't keep an eye on both coupling and coherence you'll end up with a messy system thats hard to maintain and change.
So what can we do instead - I still need my components to do things with Orders. One way to model this is with a document centric approach, the objects sent between components are documents describing the changes we'd like made to a domain object. The documents are received, the business logic applied and some sort of a response document is returned. If some other component's request is processed before mine I'll get a response back saying the domain object was in the wrong state - requests are processed one at a time, there is no complicated conflict resolution.
I can change both the domain objects and the business logic on the server as long as I respect the clear document based interface I have with other components. We have drawn a clear boundary around a service, the service manages the domain objects and I can request services by sending documents and receiving responses.
Thinking about requests modelled as documents which are then sent to the appropriate service is, to my mind anyway, a much clearer model for a distributed system. It's certainly one I've found makes delivering complex distributed systems slightly easier to model, understand and deliver.
Technologies like web services make it real easy to start serializing objects and then send them to and fro - so serializing an Order object on the server and then sending it to the client application. Simple - I can just write my client app to operate on the domain objects directly, and then send them back to the server. What could go wrong - I can almost pretend it's not a distributed system.
People talk a lot about decoupling but an area often neglected is coherence, in the case of many systems this means putting the business logic that operates on domain objects in the same place. It also often implies ownership - a particular server or tier in the application owns the domain objects and is responsible for mediating access and acting upon them. So why is coherence important?
Suppose I've allowed my Orders, say, to be serialized and sent to others parts of the system. This may not seem important to start with - but as soon as you get multiple components able to change domain objects then synchronisation becomes a big issue. If a component updates it's copy of an Order at the same time as someone else (who also has a serialized copy) then we are going to need some kind of conflict resolution on the server side to work out what the final state of the order should be based on two (now different) copies of the same order. Systems like this have no clear concept of ownership nor, quite often, a clean model of an object's state at any one instance of time. All too often projects using this approach burn a lot of time trying to create fancy conflict resolution algorithms.
Requirement change also becomes a problem, when you serializable domain objects it's very difficult to avoid distributing the business logic. That is manageable to start with, but as you add more functionality or change existing code you need to keep track of all the different components where that change may have impact. The business logic becomes 'smeared' across the system - coherence has been destroyed. A tweak to UI changes the Order object, necessarily because the serialized Order object is being use directly in the UI. A seemingly small change on the server side breaks all the client apps.
We may have used some nice messaging technology and thought we'd ticked the 'decoupled' box, but we've coupled our components together as tightly as if we'd just done RPC. If you don't keep an eye on both coupling and coherence you'll end up with a messy system thats hard to maintain and change.
So what can we do instead - I still need my components to do things with Orders. One way to model this is with a document centric approach, the objects sent between components are documents describing the changes we'd like made to a domain object. The documents are received, the business logic applied and some sort of a response document is returned. If some other component's request is processed before mine I'll get a response back saying the domain object was in the wrong state - requests are processed one at a time, there is no complicated conflict resolution.
I can change both the domain objects and the business logic on the server as long as I respect the clear document based interface I have with other components. We have drawn a clear boundary around a service, the service manages the domain objects and I can request services by sending documents and receiving responses.
Thinking about requests modelled as documents which are then sent to the appropriate service is, to my mind anyway, a much clearer model for a distributed system. It's certainly one I've found makes delivering complex distributed systems slightly easier to model, understand and deliver.


