Geeks With Blogs
Chris Falter .NET Design and Best Practices

When you are coding in a hurry, it is very tempting to write business logic in the first place that comes to mind, such as a button click handler.  However, for all but the simplest systems, such a practice leads very quickly to a chaotic system whose business logic is scattered like the ash from an erupting volcano.  So let's take a step back and see how you can develop an application more intelligently.

"Divide and Conquer"

“Divide and Conquer” is a useful metaphor for organizing the effort of developing a complex system.  A software architect can assign major system responsibilities to various components or layers (which I will refer to as a “part”).  As long as the responsibilities of a part are understood, a developer can develop the part in such a way as to satisfy those responsibilities.  And as long as the parts integrate well, a useful system can emerge.

“Divide and Conquer” has many advantages: 

  • A team can work in a coordinated fashion on several parts of the system simultaneously, without stepping on each other’s toes.
  • Assigning a limited set of related responsibilities to a system part simplifies its design.
  • Modifying a system is easier when the part that is responsible for the functionality that must be changed can be identified.
  • Ultimately, the complexity of the system decreases as its various responsibilities, and the strategies for handling them, become clear.  Unnecessary complexity is what can make “the last 10%” of a project go into deep cost and time overruns, as quality issues and poor design make their effects known.

“Divide and Conquer” is the driving force behind creating logical layers of a user interface, an application layer, a data layer, and a domain model in an enterprise software application. 

While the advantages of separating UI, application, and data logic into their own layers are well understood and frequently practiced, the point behind creating a domain model is not as widely grasped.  A domain model defines the business entities represented by a system, the activities associated with them, the relationships between them, and the rules and constraints that govern them. These are clearly very important aspects of the system, even though (from the end user’s perspective) they are not as visible as the user interface, application flow, or database.  I will illustrate the importance of a domain model by examining how insurance endorsements work in the homeowners point-of-sale system that my team has developed.

Example of a Complex Business Domain

Let’s start by examining the data model for endorsements: 

  • An endorsement can be associated with either an application (future policy) or with a risk (such as a dwelling or a vehicle).  Therefore the Endorsement table has 2 foreign keys: one that relates an endorsement to an application (via the Quotenumber) and the other that relates it to a risk (via the RiskId).
  • Endorsements come in a bewildering variety.  Some endorsements have no related data; some have one or more limits; some have one or more attributes, few of which are common between endorsements.  Clearly it is unwise to attempt to create a single table with identified columns for each of the possible limits or attributes that an endorsement may possess.  In addition, any attempt to create a unique table for each endorsement’s associated attributes is going to result in a very large number of tables—along with the responsibility of defining a new table each time a new endorsement type is created.  Therefore, the design we chose was to create 2 dependent tables for Endorsement: an EndorsementLimit table and an EndorsementDescription table.  Each table has 3 fields: an EndorsementId (foreign key back to the associated endorsement), a “type” field that allows the system to distinguish between all the related descriptions (or limits) of an endorsement, and the associated data field (a numerical limit or a varchar description).  Note that segmentation and history are irrelevant to a point-of-sale system, so the schema is not designed with that capability.
  • Some endorsements are concerned with parties to an insurance application other than the applicant, such as an additional interest or an additional insured.  Since these additional entities reside in a different table (the OtherParty table), we use a join table (EndorsementParty) to manage the association between Endorsement and OtherParty.

This portion of the database schema is represented graphically below:

Entity-Relationship Diagram for Endorsements

So if we have a data model, why do we need a domain model?  Why can’t some UI code simply write its data directly to the tables?  Clearly this one way of designing a system—you can, after all, do anything with software (provided you have sufficient time and resources).

Let us consider, though, the knowledge about the business domain that the point-of-sale application must manage with regard to endorsements:

  1. The relationship of endorsement attributes to an endorsement.  A homeowners “HO 05 28” (golf cart) endorsement has several related attributes: a limit (cart value), a make, a model, a serial number, and an indicator of whether collision coverage is included.  Each one of these attributes is stored in its own record in the EndorsementLimit or EndorsementDesc table.  The DescType field distinguishes the four EndorsementDesc records from one another; however, the system must somehow keep track of which DescType is used for which attribute.
  2. Differences between the format of stored data and how it is used.  In a database system that does not have a built-in boolean type (such as the DB2 flavor used at my shop), there are probably as many different ways to store boolean data as there are programmers.  True vs. false could be represented as “0” vs. “1”, or as “1” vs. “2”, or as “T” vs. “F”, or as “t” vs. “f”, or as “true” vs. “false”, or as “Y” vs. “N”, etc.  (In one of my consulting engagements, I actually saw all of these plus a couple more in a single application.) To handle a golf cart endorsement’s indicator of collision coverage, the system must be able to reliably map between the stored data and a run-time choice of true/false.
  3. The relationships between endorsements and other entities.  Some endorsements are related to the risk being insured (such as the earthquake endorsement), and some are related to the (potential) policy itself (such as an “Additional Insured” endorsement).
  4. The relationships between endorsement attributes.  The “HO 04 65” endorsement (scheduled property) contains a set of schedules; each schedule is designated by a letter such as “A” or “J” and has a description (the personal property being insured) and a limit.  Since descriptions and limits are stored in separate tables, the system must have some way of identifying and associating the schedules’ descriptions and limits.
  5. Rules and constraints on various endorsements.  The 6 schedules on a “HO 04 65” endorsement have base (default) limits, for example, such that the total limit of a schedule can be described as the base limit plus an additional limit.  Mathematically speaking, we use the formula Total Limit = Base (fixed by rule) + Additional (stored in EndorsementLimit table).  So the system must be able both to provide base, additional, and total limits (given the stored additional limit) and to update the stored additional limit (based on user entry).

Complexity Resolved: A Domain Model

The beauty of our team's domain model is that it completely hides all of this complexity from the user interface.

  • An endorsement class is defined for each type of endorsement, and it provides an interface that is radically simple for the UI developer to use.  To give just one example, the golf cart endorsement provides a boolean CollisionIncluded property that can be mapped to a checkbox. 
  • All of the other issues (which EndorsementDesc record the indicator is stored in, how the boolean is mapped to a varchar, etc.) are managed inside an endorsement class—frequently by using capabilities inherited from the EndorsementBase class or borrowed from utility classes in the domain layer.
  • Responsibilities are clearly grouped and assigned in this way of designing a system.  Tasks and attributes that are common to all endorsements are the responsibility of the EndorsementBase class.  The tasks and attributes that are unique to a particular endorsement are the responsibility of the corresponding subclass of EndorsementBase (which already has the common endorsement capabilities via its inheritance relationship with EndorsementBase).  Neither of these classes needs to know anything about the application or user interface which will use them, which in turn need to know nothing at all about the internal implementation details of an endorsement class. The diagram below depicts the assignment of some endorsement responsibilities to classes in our domain layer.

    Endorsement Class Diagram
  • The association of an endorsement with a policy or with a risk is managed via its membership in an EndorsementCollection that is accessed via the HomeApplication object or the HomeApplication.Home object (of type HomeRisk), respectively. The relationship between these various entities is depicted below.

    Relationship of Endorsements to HomeApplication and HomeRisk

Conclusion

There are some things that should never leak.  Space shuttle O-rings.  Tires.  Diapers.  And now that you've read this article, add your business domain model to the list.  Always isolate your business domain logic in a cohesive model; do not let the logic leak into a "smart UI" or into the data layer!  If you follow this rule, you will save yourself and your team much time and effort when you need to modify the business logic in your application.

Also, keep the importance of your domain model in mind when it is time to choose a development tool.  A rapid application development (RAD) tool that can only design screens and logic flows might be a very good choice for building a very simple system that needs little complexity in its business logic.  However, it is very difficult to envision how a RAD tool would be able to represent the relationships and constraints inherent to a complex business domain, such as homeowners insurance endorsements.  Given the inherent limitations of a RAD tool, the complexity that my team's domain model currently manages quite capably would have to spill out into the flows and screens themselves. 

While the result may initially seem counterintuitive, a RAD tool that at first glance makes everything look simple might very well in the end produce a system far more complex than a system produced with a set of tools that offer a robust and complete set of programming capabilities.  And this unanticipated complexity can make the systems you develop far more difficult to implement on time and to extend with new customer-requested capabilities.

Posted on Tuesday, March 25, 2008 9:01 AM Coding Practices and Design Patterns , Software Architecture | Back to top


Comments on this post: Want to Write Great Business Software? Create a Great Domain Model!

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
is the "or" about endorsements an English xor? if so, i'm suspicious of having the 2 possible types of endorsements shoved into one row.

in other words: specs, and communicating them, are hard!

:)
Left by Raoul Duke on Mar 26, 2008 6:32 AM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
"you can, after all, do anything with software (provided you have sufficient time and resources)."

solve the halting problem, then, please ;-)
Left by Raoul Duke on Mar 26, 2008 6:34 AM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
IMHO, what should be done first is not the domain model, but the UI screens. Creating the UI screens is a great way to clarify a lot of things between what the client wants and what is written in the specs.

You may able to create a great domain model based on the specifications, but if the specifications did not capture what the client really wants ( which is usually the case ), then you may have to edit your domain model again.
Left by Franz See on Mar 29, 2008 3:14 PM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
@Raoul #360399 - It is an exclusive or. An endorsement can be related either to the application (policy) or to the risk, but not to both. And yes, communicating specs can be hard.

You raise an interesting point about 2 different kinds of endorsements being in the same table. Since the only difference between the 2 was in their relationship to some other entity, it seemed reasonable to treat the relationship as just another attribute of an endorsement.

@Raoul #360400 - I am working on a system that will calculate the amount of force necessary to move an immovable object. Are you available for consulting? ;-)

@Franz - I agree that getting functional requirements is an important challenge in and of itself. In addition, getting the user to interact with screens is extremely useful, and helps the user to define what s/he really wants.

The domain model will not necessarily change, however, when a requirement changes. If the new requirement is the result of trying to deal with an aspect of the business that the system had not previously dealt with, then you would expect to have to modify or extend the domain model to implement the new requirement. If the requirement is to change application behavior with regard to the same business entities, the domain model may not have to change at all.

That's one of the big reasons for a domain model, after all. You can change a workflow or some controls on a UI without having to change your model of how business entities relate to one another.
Left by Chris Falter on Apr 01, 2008 7:52 AM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
the only thing complex here is the authors way of explaining simple concepts
Left by average developer on Apr 30, 2009 2:03 AM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
Hmm...if I had picked a very simple "Hello world" domain to analyze, the value of a domain model would not have been evident. I do understand how someone could get lost in the details of insurance endorsements--plenty of developers have, including myself when I first started doing insurance software.

As long as the reader comes away with the impression that real-world software for complex businesses really should have a domain model, rather than relying on forms-over-data architecture, this blog post has value. I think :)
Left by Chris Falter on Apr 30, 2009 3:47 AM

# re: Want to Write Great Business Software? Create a Great Domain Model!
Requesting Gravatar...
The domain model will not necessarily change, however, when a requirement changes. If the new requirement is the result of trying to deal with an aspect of the business that the system had not previously dealt with, then you would expect to have to modify or extend the domain model to implement the new requirement. If the requirement is to change application behavior with regard to the same business entities, the domain model may not have to change at all.
Left by steve on Jul 10, 2010 1:51 AM

Your comment:
 (will show your gravatar)


Copyright © Chris Falter | Powered by: GeeksWithBlogs.net