I. GRASP: Designing Objects with Responsibilities (Larman, Ch 16) A. responsibilities and methods (16.1) ------------------------------------------ RESPONSIBILITIES (16.1) Def: A responsibility is "a contract or obligation". Two basic types of responsibilities an object may have: A. doing - something by itself: creating objects, calculating - telling others to do something initiating action coordinating activities B. knowing - some private data - about related objects - about things it can calculate ------------------------------------------ Is a responsibility the same thing as a method? B. Patterns (16.3) ------------------------------------------ DESIGN PATTERNS (16.3) Def: a design pattern is a named problem/solution pair that can be applied in new contexts, with advice on how to apply it, and discussion of its trade-offs. ------------------------------------------ C. GRASP Patterns (16.4) 1. Information Expert (16.6) ------------------------------------------ INFORMATION EXPERT (16.6) Solution: Assign a responsibility to the information expert -- the class that has the information necessary to fulfill the responsibility. Problem: How should one assign responsibilities to objects? Example: In the POS system, Who should be responsible for knowing the total of a sale? By Information Expert we should look for a class of objects that has the information needed. ------------------------------------------ Where do we look for classes that have information? What information is needed to determine the grand total? what information is needed to determine the line item subtotal? What information is needed to determine the product price? What responsibilities did we assign? ------------------------------------------ INFORMATION EXPERT (CONTINUED) Discussion: Information Expert is a frequently used guiding principle. Many partial experts that collaborate. All objects are "alive" or "smart" Should avoid having a single "god class" with many "dumb" objects doing its will. Contraindications: avoid if causes problems with coupling and cohesion. For example, who should the responsible for saving a Sale in a database? Instead design faor separation of major concerns (information hiding). Benefits: - Information hiding, hence low coupling. - Behavior spread out, encouraging more cohesive lightweight classes. Related: - Low Coupling - High Cohesion A.K.A: "Place responsibilities with data", "Do it Myself", ... ------------------------------------------ what examples are there in your designs? 2. Creator (16.7) ------------------------------------------ CREATOR (16.7) Solution: Assign class B responsibility for creating an instance of class A if: - B aggregates objects of class A - B contains A objects - B records instances of A objects - B closely uses A objects - B has the initializing data needed to create A objects If more than one applies, prefer a class that aggregates or contains A objects. Problem: who should be responsible for creating new instances of some class? Example: In the POS system, who should be responsible for creating a SalesLineItem instance? ------------------------------------------ What class is like that in the domain model? ------------------------------------------ Discussion: The basic idea is to find a creator that needs to be connected to the created object anyway. This supports low coupling. Contraindications: if the creation is complex, then use the Factory pattern. Benefits: - low coupling Related Patterns: - Low Coupling - Factory - Whole-Part ------------------------------------------ what examples are there in your designs? 3. Low Coupling (16.8) ------------------------------------------ LOW COUPLING (16.8) Solution: Assign a responsibility so that classes aren't strongly connected. Problem: How to support low dependency, low change impact, and increased reuse? "Coupling" is a measure how strongly one element is connected to, has knowledge of, or relies on other elements. High coupling causes: - changes to affect other classes - difficulty in understanding classes (in isolation) - difficulty in reuse, because more classes are needed Example: Who should create a Payment instance and associate it with a Sale? ------------------------------------------ Which design has lower coupling? ------------------------------------------ Discussion: Low Coupling is an evaluative principle that applies when considering all design decisions. Common forms of coupling X to Y include - X has an attribute of Y - X calls methods of Y objects - X has a method that uses Y e.g., as a parameter, local variable, return type - X is a subclass of Y - X implements the interface Y Low coupling reduces impact of changes. A subclass is strongly coupled to its superclass(es). There will usually be some coupling, just need to gauge it, and understand it. But don't couple strongly with unstable elements. Reusable classes should have low coupling. Contraindications: high coupling to stable elements (the programming language, libraries) is okay. Don't spend extra time "future proofing". Focus on realistic points of high instability or evolution. Benefits: - not affected by other's changes - simple to understand in isolation - convenient to reuse Related Patterns: - Protected Variation ------------------------------------------ what examples are there in your designs? 4. High Cohesion (16.9) ------------------------------------------ HIGH COHESION (16.9) Solution: Assign a responsibility so that cohesion remains high. Problem: How to keep complexity manageable? Functional cohesion is a measure of how strongly related and focused the responsibilities of an element are. A class with low cohesion does many unrelated things, or too much work. This causes classes to be - hard to comprehend - hard to reuse - hard to maintain - delicate; often affected by change Example: Who should create a Payment instance and associate it with a Sale? ------------------------------------------ ------------------------------------------ Discussion: This also applies to methods, subsystems, etc., not just classes. It is an evaluative principle, and should be considered all the time. A rule of thumb is that a class with high cohesion has relatively few methods, with highly related functionality. ------------------------------------------ ------------------------------------------ Contraindications: - simplify maintenance for non OO folk - performance in distributed settings Benefits: - clarity and ease of comprehension - maintenance and enhancement easier - low coupling is often supported - easier to reuse ------------------------------------------ what examples are there in your designs? 5. Controller (16.10) ------------------------------------------ CONTROLLER (16.10) Solution: Assign the responsibility for receiving or handling a system event to a class that: - represents the overall system, device, or subsystem (facade controller), or - represents a use case scenario (use-case or session controller). ------------------------------------------ ------------------------------------------ Problem: Who should be responsible for handling an input system event? An input system event is generated by an external actor. The UI turns these into system operations in the application layer. A controller is a non-UI object responsible for handling a system event. Example: In the POS system, who should handle system events such as enterItem? ------------------------------------------ ------------------------------------------ Discussion: A Controller is a facade that hides details of the domain layer (from the UI layer). Use a use-case controller if - state info must be kept between system events, - to identify out-of-sequence events, - if there are not "too many" kinds of system events A controller should delegate instead of doing the work itself. ------------------------------------------ Why is it bad for the user interface to have responsibility for handling system events? ------------------------------------------ Benefits: - separates application logic from UI leading to higher reuse - allows reasoning about state of interaction in a use-case Related Patterns: - Command, for message handling systems each message is a command object - Facade, a controller is a Facade - Layers - Pure Fabrication, controllers aren't part of domain model ------------------------------------------ what examples are there in your designs? D. Object Design and CRC cards (16.11) ------------------------------------------ CRC CARDS (16.11) An index card for each design class: |------------------------------------| | Sale Collaborators | |------------------------------------| | Knows total SalesLineItem| | Aggregates SalesLineItems | | ... | |------------------------------------| Can use them to play out scenarios - pick up cards when active ------------------------------------------