Saturday, June 21, 2008

The myth of Serializable free distributed computing

For some, Domain modeling is not a science its an art. Hardcore domain modelers will tell you rules and list of good practices that will make you believe that you haven't learned anything yet. I loosely touched this subject in one of my blogs as well. A good domain object is one that does not know anything about the infrastructure it will be run inside. A domain object is not just a placeholder of getters and setters but can also have other behaviors as long as it only operates on the attributes it owns. Following is a good example of a domain object:


public class TwoInt {
private int a;
private int b;
public int getA () {..}
public void setA (int a) {..}
public int getB () {..}
public void setB (int b) {..}

// --
public int add (int a, int b) {
return a+b;
}
}

Distributed computing somewhat challenges the established notions of domain modeling. The JVM contract says if an Object is to be moved from one JVM to another it has to be Serializable. Period. This contract can not be breached. Designing a distributed application with a Single System Image has this challenge to overcome. For the example Object TwoInt to be used in a distributed environment it has to implement java.io.Serializable that the domain perfectionists will see red on. What if the application is only deployed on one single JVM? Then why Serializable? Being Serializable is a concern of an infrastructure not a requirement of the domain model.
Whats wrong with the following?

public class TwoInt implements Serializable {....}

public class App {
public static void main (String [] args) {
TwoInt key = new TwoInt ();
TwoInt value = new TwoInt ();
java.util.Map m = <??????>;
m.put (key, value);
}
}

Map is an Interface. If its implementation is to be replaced by a HashMap by far the most popular implementation of java.util.Map, then TwoInt objects are not required to implement Serializable. If this application is to be run in a Distributed Environment and Map's implementation is a NamedCache (Another implementation of a Map interface but now in a distributed environment) then TwoInt has to implement Serializable. So any change in the Map's implementation has a direct consequence on its domain model.
Aspect Oriented Programming can be a bridge between what is required in distributed computing and domain perfectionists. Good part is, a domain modeler sees a Java source and Distributed computing sees the byte codes. Hence Serializable is a cross cutting concern and with AOP if implemented at compile time both camps will be happy. Following is a sample how to do it using AspectJ, an AOP implementation:

public aspect TwoIntAspect {
declare parents: TwoInt implements Serializable;
}

Then compile the domain object with its Aspect using ajc (AspectJ Java compiler) as:
$ ajc TwoInt.java TwoIntAspect.java
The TwoInt.class will be changed to have Serializable interface implemented.

No comments: