Reflection: Finding the Underlying Abstractions


So far, we have learned that a simple use case analysis can provide a wealth of information and insights into the design of a system. Figures 26-6 through 26-10 resulted from thinking about the use cases, that is, thinking about behavior.

To use the OCP effectively, we must hunt for abstractions and find those that underlie the application. Often, these abstractions are not stated or even alluded to by the requirements of the application or even the use cases. Requirements and use cases may be too steeped in details to express the generalities of the underlying abstractions.

Employee Payment

Let's look again at the requirements. We see statements like this: "Some employees work by the hour" and "Some employees are paid a flat salary" and "Some . . . employees are paid a commission." This hints at the following generalization: All employees are paid, but they are paid by different schemes. The abstraction here is that all employees are paid. Our model of the PaymentClassification in Figures 26-7 through 26-10 expresses this abstraction nicely. Thus, this abstraction has already been found among our user stories by doing a very simple use case analysis.

Payment Schedule

Looking for other abstractions, we find "They are paid every Friday," "They are paid on the last working day of the month," and "They are paid every other Friday." This leads us to another generality: All employees are paid according to a schedule. The abstraction here is the notion of the schedule. It should be possible to ask an Employee object whether a certain date is its payday. The use cases barely mention this. The requirements associate an employee's schedule and payment classification. Specifically, hourly employees are paid weekly, salaried employees are paid monthly, and employees receiving commissions are paid biweekly; however, is this association essential? Might not the policy change one day, so that employees could select a particular schedule or employees belonging to different departments or different divisions could have different schedules? Might not schedule policy change independent of payment policy? Certainly, this seems likely.

If, as the requirements imply, we delegated the issue of schedule to the Payment-Classification class, our class could not be closed against issues of change in schedule. When we changed payment policy, we would also have to test schedule; when we changed schedules, we would also have to test payment policy. Both OCP and SRP would be violated.

An association between schedule and payment policy could lead to bugs in which a change to a particular payment policy caused incorrect scheduling of certain employees. Bugs like this may make sense to programmers, but they strike fear in the hearts of managers and users. They fear, and rightly so, that if schedules can be broken by a change to payment policy, any change made anywhere might cause problems in any other unrelated part of the system. They fear that they cannot predict the effects of a change. When effects cannot be predicted, confidence is lost, and the program assumes the status of "dangerous and unstable" in the minds of its managers and users.

Despite the essential nature of the schedule abstraction, our use case analysis failed to give us any direct clues about its existence. To spot it required careful consideration of the requirements and an insight into the wiles of the user community. Overreliance on tools and procedures and underreliance on intelligence and experience are recipes for disaster.

Figures 26-11 and 26-12 show the static and dynamic models for the schedule abstraction. As you can see, we've used the STRATEGY pattern yet again. The Employee class contains the abstract PaymentSchedule class. The three varieties of PaymentSchedule correspond to the three known schedules by which employees are paid.

Figure 26-11. Static model of a Schedule abstraction


Figure 26-12. Dynamic model of a Schedule abstraction


Payment Methods

Another generalization we can make from the requirements is that all employees receive their pay by some method. The abstraction is the PaymentMethod class. Interestingly enough, this abstraction is already expressed in Figure 26-6.

Affiliations

The requirements imply that employees may have affiliations with a union; however, the union may not be the only organization that has a claim to some of an employee's pay. Employees might want to make automatic contributions to certain charities or have their dues to professional associations paid automatically. The generalization therefore becomes that the employee may be affiliated with many organizations that should be automatically paid from the employee's paycheck.

The corresponding abstraction is the Affiliation class that is shown in Figure 26-6. That figure, however, does not show the Employee containing more than one Affiliation, and it shows the presence of a NoAffiliation class. This design does not quite fit the abstraction we now think we need. Figures 26-13 and 26-14 show the static and dynamic models that represent the Affiliation abstraction.

Figure 26-13. Static structure of Affiliation abstraction


Figure 26-14. Dynamic structure of Affiliation abstraction


The list of Affiliation objects has obviated the need to use the NULL OBJECT pattern for unaffiliated employees. Now, the list of affiliations for an employee who has no affiliation will simply be empty.




Agile Principles, Patterns, and Practices in C#
Agile Principles, Patterns, and Practices in C#
ISBN: 0131857258
EAN: 2147483647
Year: 2006
Pages: 272

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net