Interface Segregation Principle
On the DDD newsgroup one thread started there recently asked:
Implicit concepts are an important subject in software creation. They allow for breakthroughs in hard to model systems (for example).
Did you ever use _special_ techniques to identify them? Be it via interviews, visualizations, system metaphors, code analysis or code refactoring.
It’s a good question; it’s only by identifying concepts correctly that we can hope to get a rich and useful domain model. My answer went as follows:
One technique I would recommend is to apply Robert Martin’s interface segregation principle.
For example, in our system for administering government benefits [ed: that is, the DSFA project], we started off with two classes:
- Customer (ie a citizen)
- Scheme (ie a claim for a government benefit)
One of the first benefits implemented was for Pensions. So we had a single relationship between PensionScheme and Customer. The Customer paid in their national contributions, and when they retired they got paid a pension. So far so easy, but no implicit concepts identified.
A subsequent benefit implemented was for Child Benefit. Now we needed two relationships between ChildBenefitScheme and Customer. The benefit is *because* of the child but is *paid* to their mother. (That’s how it is in Ireland). This gave us a Source reference (from Scheme to the child Customer) and a Beneficiary reference (from Scheme to the parent Customer). Still no implicit concepts, but it’s getting more complex.
A benefit implemented this year has been the Widow/er’s benefit, whereby a pension money is paid to a bereaved spouse based on the deceased spouse’s contributions. Now this is a little like child benefit in that it separates out two customers: the deceased spouse and the widow/er. However, the rules are much more complex than CB. Untangling them led us to identifying some implicit concepts that had been there from day one:
1. the Customer plays the role of being an IContributionSource with respect to Scheme. The Scheme.Source property should not be of type Customer, it should be of type IContributionSource
2. the Customer also plays the role of being an IBeneficiary with respect to Scheme. The Scheme.Benefits property should not be of type Customer, it should be of type IBeneficiary.
A good (if slightly overgeneralized) summary of this is: always ensure that your properties are named after their type (Benefits:IBeneficiary). The moment there is a mismatch (Benefits:Customer) then that may be a clue to a missing concept.
Robert Martin’s original article on this is at http://www.objectmentor.com/resources/articles/isp.pdf. It’s a little dated, but there are plenty other discussions on this same theme too.