2.2 Tracking Policy Updates
The user interface is connected to the model using a simple model-view- controller design. There is a simple PolicyListener interface that clients can implement, and after registering themselves with a policy, they will receive a policyUpdated() notification whenever the policy is updated. Figure 2.7 shows the PolicyListener interface in the editor. Figures 2.8 and 2.9 show excerpts from the PolicyImpl class. Notice in Figure 2.8 the calls to notifyListeners after updating the state of the Policy on lines 86 and 101.
Figure 2.7 PolicyListener.
Figure 2.8 Change notifications.
Figure 2.9 shows the code that keeps track of registered listeners and performs the actual notification.
Figure 2.9 Managing the listeners.
The various types of insurance policy all inherit the basic capability of managing a set of listeners from their parent PolicyImpl class, but each subclass has to be sure to call the notifyListeners method whenever it updates any of its own state. For example, the AutoPolicyImpl class keeps track of a no-claims bonus. If we look into the update method for the no-claims bonus, we will see the code shown in Listing 2.1, with a call to notifyListeners() duly made after updating the state.
Listing 2.1 Excerpt from AutoPolicyImpl Class
public void setNoClaims(boolean noClaims) { this.noClaims = noClaims; notifyListeners(); }
So far this strategy has been working okay, but now the business has asked us to consider adding support for pet insurance policies, too. Rather than keep adding more and more calls to notifyListeners() spread throughout the hierarchy, is there something better we can do? What we're looking at is a 1-to-n implementation: We have one simple requirement, to notify all registered listeners whenever a policy is updated, but an implementation that is scattered in n places throughout the policy hierarchy. To quote from the eXtreme programming discipline: "Refactor mercilessly to keep the design simple as you go and to avoid needless clutter and complexity. Keep your code clean and concise so it is easier to understand, modify, and extend. Make sure everything is expressed once and only once. In the end it takes less time to produce a system that is well groomed."1 We said in the introduction that aspect-oriented programming offered us a new kind of a module, known as an aspect, that could help solve problems such as this and turn it back into a one-to-one mapping. In other words, we should be able to modularize the change notification policy inside an aspect. Instead of adding yet more scattered calls to notifyListeners in the new PetPolicyImpl class, perhaps we should consider refactoring.