UML Collaboration Diagrams
8. General Principles in Assigning Responsibilities
Patterns are best principles for assigning responsibilities to objects. Patterns are guide to the creation of software methods. They are best principles for assigning responsibilities to objects. They are solutions to common occurring problems. In view of this module the GRASP patterns: General Responsibility Assignment Software Patterns is going to be applied. GRASP pattern takes the following format:
Pattern Name: The name given to the pattern
Solution: Description of the solution of the problem
Problem: Description of the problem that the pattern solves
Most simply, a pattern is a named problem/solution pair that can be applied to new context, with advice on how to apply it in novel situations. GRASP patterns include the following five basic patterns:
1. Expert,
2. Creator,
3. High Cohesion
4. Low Coupling and
5. Controller.
GRASP 1: Expert
This is a very simple pattern and is being used more than any other pattern in assignment of responsibilities. Expert class is that class that has information necessary to fulfill the responsible. Experts do things relating to the information they know. Assign a responsibility to the information expert – the class that has the information necessary to fulfill the responsibility. Example is as shown in Figure 4.10.:
Figure 4.10: Collaboration Diagram for Getting the price of a product
GRASP 2: Creator
The creation of objects is one of the most common activities in an OO system. It asks the question "who should be responsible for creating instances of a particular class?" Assign class B the responsibility to create an instance of class A if one of these is true:
- B contains A
- B records A
- B aggregates A
- B closely uses A
- B has the initializing data for A
For example in POST system, who should be responsible for creating a SalesLineIteM instance? By Creator pattern, we should look for a class that aggregates, contains SalesLineItem instances. Since Sale contains (aggregates) many SalesLine Item objects, the creator pattern suggests that Sale is the right candidate to have the responsibility of creating SalesLine Items instances as in Figure 4.11. This means "makeLineItem" method will be defined in Sale.
GRASP 3: High Cohesion
Cohesion or coherence is the strength of dependencies within a subsystem. Cohesion is a measure of how strongly related and focused the responsibilities of a class. It is the internal "glue" with which a subsystem is constructed. A component is cohesive if all its elements are directed towards a task and the elements are essential for performing the same task. If a subsystem contains unrelated objects, coherence is low. High cohesion is desirable.
A class with high cohesion has highly related functional responsibilities, and does not do tremendous amount of work. Such classes have a small number of methods with simple but highly related functionality. In a good object-oriented design, each class should not do too much work. Assign few methods to a class and delegate parts of the work to fulfill the responsibility to other classes.
The following "liftController" class in Figure 4.12 is not well designed. A class does a lot of work.
LiftController | |
getFloor() moveLift() setTrip() emergencyProcedure() raiseAlarm() udateLed() openDoors() closeDoors() reset() startUP() shutDown() displayLog() |
Figure 4.12: The Lift Controller Class with Low CohesionNote that a class should represent one "thing" from the real would. Key separate abstractions from liftController as shown in Figure 4.13 are:
- An Alarm
- Lift
- Doors and
- Logs
Figure 4.13: The Lift Controller Class Modelled as a Four Separate, More Cohesive Classes
GRASP 4: Low Coupling
Coupling is a measure of how strongly one class is connected to; has knowledge of; or relies on other classes. A class with low (or weak) coupling is not dependent on too many other classes. When we assign a responsibility to a class, we would like to assign responsibilities in a way so that coupling between classes remains low.
From the following example for "makePayment" use case and with the consideration of low coupling, the second design is preferable because it does not need an extra link formed between POST and Payment. This assignment of responsibility is also justifiable as it is reasonable to think that a Sale closely uses a Payment (Figure 4.14).
GRASP 5: Controller
Who handles a system event? Assign the responsibility for handling a system event message to a class representing one of these choices:
- Represents the overall system, device, or a subsystem (facade controller).
- Represents a use case scenario within which the system event occurs (use-case or session controller)
A controller is a non-user interface object responsible in handling a system input events, and the controller defines the method for the system operation corresponding to the system input event. One possible solution is to add/introduce a new class, and make it sit between the actor and the business classes. The name of this controller is usually called Handler. Handler reads the commands from the user and then decides which classes the messages should be directed to. The handler is the only class that will be allowed to read and display. The system receive external input events, typically involving a GUI operated by a person.
Controller pattern takes the following form:
Table 4.3: Controller Pattern
Pattern Name | Controller |
Solution |
Assign the responsibility for handling a system (input) event to a class representing one of the following choices
|
Problem | Who should be responsible for handling a system input event? |