Warning: this is a very long post

I would like to start a discussion about the business tier, including the business domain models and validation rules (business rules). This discussion is not really specific to rich client applications, however, because a rich client application is by definition a remote application that requires domain information to be serialized and sent to/from a remote service, many of the tricky problems associated with the business tier are more apparent.

As a starting point for the discussion (I hope others will find it interesting and jump in), I’ll highlight how we think this should work, and the problems we are encountering in real life situations. Of course, please jump in if you see statements or ideas that you disagree with, or have alternative solutions or suggestions.

First though, a few definitions:

Business Tier:
The business tier represents the inherent business problem that a system is solving. Note that it is not tied to a specific presentation technology. It should be possible for both technical people and business people to review models of the business tier and ‘see’ the business entities, relationships, core operations, and business rules.

Presentation Tier:
The presentation tier represents ‘what the application looks like’. It should be possible to have multiple different presentation tiers that use the exact same set of objects from the business tier. For example, you should be able to easily replace or run in parallel:
- a web interface based on Struts
- a web interface based on Spring MVC
- a rich client interface based on raw Swing (like we used to write our rich client apps)
- a rich client interface based on Spring Rich
- a mobile interface for a pocket PC


Domain Object:

The domain object classes represent business entities, the business attributes and business relationships to other entities. This is often a set of relatively simple POJOs. The pet clinic classes (Owner, Pet, Visit, Vet, PetType and Specialty in package org.springframework.samples.petclinic) represent the domain objects in the rich client sample application. Rules that are inherent to an entity can be implemented directly by the domain object class. This includes simple get/set of attributes such as setName(…), as well as relationships such as owner.addPet( aPet ).

Note that the term ‘domain model’ is sometimes used to mean the Domain Objects themselves. I tend to think of the ‘domain model’ as a synonym for the business tier, which is the collection of all domain objects, services and business rules that are independent of the presentation tier.

Domain Services
The domain services represent business operations that involve the domain objects but may be external to the object itself. A simple but common example is ownerService.getOwnerById( ownerId ), or ownerService.save( anOwner ). A more complex business operation could be ownerService.checkAccountIsInGoodStanding( anOwner ).

Again, note that these service operations are completely independent of the presentation tier (a rich client, or web client application) as the exact same call should be made by either presentation technology.

Validation / Business Rules:
The business rules are constraints that the domain objects must satisfy. Many business rules are very simple rules that can be defined for an attribute on a domain object. For example, the owner’s lastName is required, must be <= 255 characters, and be alphabetic. Other business rules require input from two or more attributes (e.g. a date attribute is mandatory only if another condition is true). The rule may be more complex yet and involve multiple domain objects and attributes. (this is the type of business rule that is currently giving us the most trouble).

Value Objects:
A value object is a simple ‘bit bucket’ for holding or transporting data. For example, an object to carry search parameters may be a simple value object as it doesn’t really represent a meaningful business entity. Putting all of the query attributes together into a value object to pass to the server is really just a programming convenience.

It can be somewhat unclear the distinction between a domain model and a value object, and in practice the distinction may not matter that much. For me I tend to think of an object that is just carrying data as a value object, and one that is capturing meaningful business data and relationships as a domain object. In either case, a value object or domain model could be passed to services, and serialized to be passed to/from the server from a remote client.

Client/Server:
I would like to define ‘client server’ in the way that traditional client-server tools such as PowerBuilder or VisualBasic work. In fact, many of the Java automatic DB binding tools and GUI builders provided by IDEs are in this category too. This definition may not be completely correct, but I can’t think of a better name or way of describing it. Client-Server applications work by processing data result sets and rows. They typically have an easy way to connect to a database and bring back rows, display them, and insert, update, and delete them.

With this definition, I would say that a client-server application does not have a true domain model. The system may create Java classes (value objects) to carry around a row, and it may put these objects in a collection, but it is inherently still just result set processing. There has been no attempt to capture the business meaning and relationships other than what the database schema itself represents.

For many systems or portions of a system, simple result set processing is sufficient and in fact is the appropriate way of developing the application. It starts to break down however when the business domain is complex. A client-server based application often ends up putting a lot of logic that is really domain knowledge in the presentation tier, since a true domain model with domain objects and domain services doesn’t exist.

Domain Driven Design
I believe that the potential of Spring Rich Client is that it can directly work with systems that are built around a true domain model. All complex systems need this.

A system that is driven by a domain model is fundamentally different than a client-server application. The domain model is designed to capture the business entities, the business relationships, core operations and rules. The fact that some entities may be persisted into a relational database is secondary, and it is very common for the structure of the domain model to be significantly different than the relational database schema.

A very good book that describes this is ‘Domain Driven Design by Eric Evans’.

The Spring PetClinic example(s):
Now that I have defined what I mean by some of the basic concepts, I’d like to take a look at the domain model provided with the Spring Pet Clinic sample applications. The Pet Clinic sample provided by spring does provide domain objects, that I believe are true domain objects. These classes, summarized below, are used by both the web and rich client samples, which supports the idea that they are part of the business tier and independent of the presentation tier.

Code:
package org.springframework.samples.petclinic;

public class Person extends Entity 
&#123;
    private String firstName;
    private String lastName;
    private String address;
    private String city;
    private String telephone;

    ... getters / setters omitted ...
&#125;

public class Owner extends Person 
&#123;
    private Set pets;

 ... getters/setters omitted ...
 
    public List getPets&#40;&#41; &#123; ... &#125; // returns an unmodifiable list
    public void addPet&#40;Pet pet&#41; &#123; ... &#125;
    public Pet  getPet&#40;String name&#41; &#123; ... &#125;
    public Pet  getPet&#40;String name, boolean ignoreNew&#41; &#123; ... &#125;
&#125;

public class Pet extends NamedEntity 
&#123;
    private Date    birthDate;
    private PetType type;
    private Owner   owner;
    private Set     visits;

    ... getter/setters omitted ...

    public List getVisits&#40;&#41; &#123; ... &#125; // returns an unmodifiable list
    public void addVisit&#40;Visit visit&#41; &#123; ... &#125;
&#125;

public class Visit extends Entity 
&#123;
    private Date    date;
    private String  description;
    private Pet     pet;
 
    ... getters/setters omitted ...
&#125;
What does this domain model tell us about the business:
- An owner is a ‘person’ that has basic information (name, address and phone)
- An owner can have many pets, and these are identified by the pet’s name
- There will be trouble if the owner has more than one pet with the same name, but this may be OK with the business (my wife’s sister has had two different dogs with the same name though, so this is likely a problem that the business users missed)
- A pet has a name, date of birth and a ‘PetType’, which in this simple example can be any string. In a more realistic example it would likely be a code value.
- A Pet know who it’s owner is (as a direct link – more on this later)
- Pets can know what visits they have had (list of visits)
- A visit is on a specific date, for a specific Pet (direct link back to the Pet)

This is a simple example, and of course it isn’t really meant to be realistic, but based on this domain model, I would want clarify if the business really intends a visit to only be able to handle a single pet. The way this is modeled, an owner with 2 dogs can not take them both to the same visit. (maybe this is really an ‘appointment’ that is tied to an owner who pays the bill, and many ‘treatments’ that is tied to the Pet(s) that were at the appointment) This is just an example of the value of using a domain model – it gives the technical and business users a common understanding of the business problem, and forces the business relationships to be specified in a very precise way.

Unfortunately, the above domain objects is where the PetClinic sample application stops in terms of a common business tier. The rest of what I believe should be part of the business tier seem to be intermixed with the presentation tier code in the various examples. I don’t think this is necessary, but it is very easy to accidentally do when the application is focusing (for now) on a single presentation technology.

Validation
There are validation rules that should also be part of the domain model. In the rich client pet clinic example, these rules are defined in the following class:

Code:
package org.springframework.richclient.samples.petclinic.domain;

... imports deleted ...

public class PetClinicValidationRulesSource extends DefaultRulesSource &#123;

    public PetClinicValidationRulesSource&#40;&#41; &#123;
        super&#40;&#41;;
        addRules&#40;createOwnerRules&#40;&#41;&#41;;
    &#125;

    private Rules createOwnerRules&#40;&#41; &#123;
        return new Rules&#40;Owner.class&#41; &#123;
            protected void initRules&#40;&#41; &#123;
                add&#40;"firstName", getNameValueConstraint&#40;&#41;&#41;;
                add&#40;"lastName",  getNameValueConstraint&#40;&#41;&#41;;
                add&#40;not&#40;eqProperty&#40;"firstName", "lastName"&#41;&#41;&#41;;
                add&#40;"address", required&#40;&#41;&#41;;
            &#125;

            private Constraint getNameValueConstraint&#40;&#41; &#123;
                return all&#40;new Constraint&#91;&#93; &#123; required&#40;&#41;, 
                                              maxLength&#40;25&#41;, 
                                              regexp&#40;"&#91;a-zA-Z&#93;*", 
                                              "alphabetic"&#41; &#125;&#41;;
            &#125;
        &#125;;
    &#125;
&#125;
Please humour me as I outline the way this is used in the rich client application – it is somewhat round-about, and took quite a bit of time to track down how this was working at all…

The PetClinicValidationRulesSource has buried inside it the ‘createOwnerRules’ method that fairly nicely encapsulates business rules for the Owner domain object. However, these rules are inherent to the Owner, and should not be tied directly to the presentation technology. The PetClinicValidationRulesSource is defined as a ‘rulesSource’ bean in the rich-client-application-context.xml file. The ‘rulesSource’ bean in turn is used by the ApplicationServices object, which uses this name by default and loads it from the application context. (it isn’t specified in a configuration file – this is a magic name). Note that the ApplicationServices object contains other things like the imageSource, lookAndFeelConfigurer, componentFactory, and other things that are a necessary part of the rich client tier. Unfortunately though, this means that a core operation like applying validation logic is not handled by the business tier – you need to have the rich client specific class available before the validation rules can be used. (the web sample application has a similar, but different technique of applying similar but probably different business rules – I was too lazy to track the web usage of a business rule down)

Note that the ApplicationServices object in turn is held by the ‘Application’ object (based on a default name – not in a configuration file). The Application object represents the rich client application itself, and is a singleton to hold resources needed throughout the application (like the applicationContext and ApplicationServices).

Note that the rich client sample application is not using the SpringFramework Validator and Errors interfaces. I would like to investigate why there are different techniques in play for this.

Validation Questions:

How should the business tier handle the business rules? We need to make it available directly from the business tier, without any ties to the presentation tier.
- Should the domain object itself hold its ‘Validator’?
- Should there be a service object corresponding to each domain object that holds the validator?
- Should we have a DomainObjectFactory that uses Spring to serve up the domain objects? This could be useful, as Spring could be configured to wrapper the domain objects with the capability of holding the business rules (Validator), Errors object, and other useful things such as automatic dirty checking.

Should the domain object be able to report any validation errors that exist at the time? Again, this is a question that should be independent of a presentation tier. If the owner.lastName is mandatory but not filled in, a field level error exists for lastName. How a given presentation tier displays this error is not important at the domain model level.

What object holds the errors object? Note that a Validator for a domain object can be stateless and could therefore be held by a service object. However, an Errors object would need to hold context information about the specific domain object that has errors, so I believe it needs to be held by the domain object itself.

If the domain object is holding an Errors object, should it also hold a reference to the Validator used to generate the errors? Should the Errors object hold the reference to the Validator that was used?

Should the business rules for an object (such as Owner) be in their own class? For example, we could break the above example out into:

Code:
public class OwnerRules extends BusinessRules
&#123;
    public OwnerRules&#40;&#41; &#123;
        super&#40;&#41;;
        
        initRules&#40;&#41;;
    &#125;

	protected boolean supports&#40;Class  clazz&#41; &#123; ... &#125;
	public    void    validate&#40;Object obj, Errors errors&#41; &#123; ... &#125;

   protected void initRules&#40;&#41; &#123;
       add&#40;"firstName", getNameValueConstraint&#40;&#41;&#41;;
       add&#40;"lastName",  getNameValueConstraint&#40;&#41;&#41;;
       add&#40;not&#40;eqProperty&#40;"firstName", "lastName"&#41;&#41;&#41;;
       add&#40;"address", required&#40;&#41;&#41;;
    &#125;

    private Constraint getNameValueConstraint&#40;&#41; &#123;
        return all&#40;new Constraint&#91;&#93; &#123; required&#40;&#41;, maxLength&#40;25&#41;, regexp&#40;"&#91;a-zA-Z&#93;*", "alphabetic"&#41; &#125;&#41;;
    &#125;
&#125;
More complex validations
Now that we have discussed the simple cases, lets take a look at a more complex business rule. This type of rule is very common in real business systems.

Lets add the rule that the Visit date must be greater than or equal to the Pet’s date of birth. (you can not have a vet clinic visit for a pet that has not been born yet – you may have a visit for the mother, but not for the unborn puppy) Simple enough, and a very reasonable data integrity check for the business data.

How do we specify this? I think we should be able to do something like this (I have never written this code for real, so I suspect it won’t even compile):

Code:
public class VisitRules extends BusinessRules
&#123;
    public VisitRules&#40;&#41; &#123;
        super&#40;&#41;;
        
        initRules&#40;&#41;;
    &#125;

    protected boolean supports&#40;Class  clazz&#41; &#123; ... &#125;
    public    void    validate&#40;Object obj, Errors errors&#41; &#123; ... &#125;

   protected void initRules&#40;&#41; &#123;
       add&#40;"date", geProperty&#40; "date", "pet.birthDate" &#41;;
    &#125;
&#125;
What I am trying to specify is the following:
- there is a business rule tied to the Visit domain object’s ‘date’ field
- the ‘date’ value must be greater than or equal to the pet’s birthdate (‘pet.birthDate’ will be converted to myVisit.getPet().getBirthDate() using the underlying bean utilities mechanism)

I think the above should work, however, I am a bit concerned that this has now coupled the ‘Visit’ object with details of the Pet object. Is this OK, or does it violate the encapsulation of the Visit object? Since ‘Visit’ was designed with a back pointer to ‘Pet’ I believe this linkage in the business rule is fine. (more on this later though)

Using the above technique we should be able to specify fairly complex business rules as long as it is possible to use traversal notation to get to the input data needed by the rule. We want to avoid traversal that is more than one level deep though, as this creates linkages to structures such that modifying the internals of an object could break code in a seemingly unrelated business rules. (Don’t specify something like “pet.owner.lastName� to get the last name of the pet. If we change owner.lastName to owner.familyName, then this rule will break, and the compiler won’t find it.)

A more realistic domain model
I would like to try to make the pet clinic example more closely mimic a real life domain model. Let’s consider the following situation:

We have an owner – let’s call her “Granny Smith�
Granny Smith is 93 years old and has been at the clinic for the last 50 years.
During that time, Granny has owned 15 cats, 14 dogs, and one bird (who quickly was eaten by a cat, so she didn’t get any more birds)
Each of these pets visits the clinic three times per year (each independently because that is how our domain model works)

What do we have?
- 1 owner object (Granny Smith)
- That holds a collection of 30 pets
- That in turn hold about 30 visits each (average 10 year lifespan with 3 visits per year), for a total of approximately 900 visits
- (what a good client Granny has been)

Now, we really don’t want to bring all of this into memory just because Granny shows up with her a new cat for the first visit.

To solve this, we probably want to decouple the domain models somewhat, and move some functionality from the domain object into a corresponding domain service object. For example, ‘Owner’ could be modified to hold a ‘PetSummary’ record, that is just the basic information about a pet (name and a unique business level pet identifier), instead of the full information. When we call ‘OwnerService.getOwner()’, it would return just the owner record with enough pet information to display the list of pets, but not have all information in memory. When an application selects a specific pet summary record (from a list or tree – from the web application link – whatever, the domain model doesn’t care) it would result in the following call at the domain level ‘PetService.getPetDeails( petIdentifier )’. We may, or may not, attach this pet details record directly to the corresponding pet summary record.

Similarly, to handle the Visits for a Pet, there could be a service object (PetService, and VisitService) that handle the details of pulling back just the right amount of information, such that we don’t have to bring everything into memory at once, just the portion we need.

Some Nasty Details
The back pointers can cause real grief for several reasons:
- Having a back pointer, such as pet.getOwner() or visit.getPet(), means that the pet or visit objects are directly tied to their parent. We may not want to bring in this object, or we may want to use this object in a different context.
- Often the lifecycle of the objects are different. In my modified example above, we want to save or update an Owner record without saving the Pet record. We certainly want to update a Pet record without updating the Owner record.
- In a rich client (remote) application, this is critical, as when we pass a Pet domain object to the server to be saved, we do not want to also pass the ‘Owner’ and in turn all other Pet records and their 900 visits. This is simply too much data!
- In a web application this is also important, although often overlooked. A web application lives on the server, so a large interconnected object model doesn’t need to be serialized over a slow network just to send it to the data tier to be saved. However, it is very easy to end up pulling too much information into memory, using unnecessary memory and time resources. This of course can kill a web server that needs to handle many simultaneous users.

Lets assume that we rework our domain model such that the domain objects only hold direct references to other objects that share the same lifecycle (aggregate objects – see the Domain Driven Design book for details on what I mean here). We will not have back pointers, but there will be appropriate methods in domain service objects such that the information an application may need is easily available.

Back to Validation
There is a business rule that the pet’s date of birth must be earlier than the date of the visit. We implemented this using a rule on the Visit object that traversed using the back pointer (from above)…

add("date", geProperty( "date", "pet.birthDate" );

However, we may no longer have a ‘pet’ back pointer in the Visit object. I need another way to implement this rule, or a better understanding of how to properly decouple a complex domain model such that we don’t end up pulling too much information into memory at once.

I think this is more than enough to start. I definitely have more thoughts and details on this subject, but would appreciate comments from people that have also tried to fully decouple the domain model from the presentation tier. In our example this is not just a theoretical exercise, as we have both a rich client and web front end to the exact same business problem (in some cases duplicating the screens almost exactly). The business domain, including validation rules and core operations, must be fully independent from the presentation technologies.

Jim Leask