It is Craig Larman’s methodical approach to OO design. In essence, it is a tool to help apply responsibilities to OOD design. These are designed (and meant to be used as) methodical, rational, explainable techniques. They are “patterns of assigning responsibilities”. Note that use of “pattern” here is slightly different from some that intended by the GoF book. 
“Patterns” are invented by Christopher Alexander. The purpose of “pattern language” is to propose solutions for designing spaces used by humans. Classic design patterns for software are invented by the Gang of Four (GoF) which includes Gamma, Johnson, Helm, Vlissides. “Patterns” is now a rather “loose” term. Where as, Larman has a special meaning for his GRASP patterns

What is a GRASP pattern?

A named and well-known problem/solution pair. General enough to be applied to new contexts. Specific enough to give advice on how to apply it. Especially important for novel situations. Also comes with a discussion of:

  • trade-offs
  • implementations
  • variations
GRASP defines nine basic OO principles. These are basic building blocks for OO designs. These are meant to be “pragmatic” and meant to be a “learning aid”. Also intended for combination with:
  • a development process (UP)
  • an organizational metaphor (RDD)
  • a visual modeling notation (UML)

The Nine GRASP Patterns

  1. Creator
  2. Information Expert
  3. Low Coupling
  4. Controller
  5. High Cohesion
  6. Polymorphism
  7. Pure Fabrication
  8. Indirection
  9. Protected Variations

1. GRASP Creator

Object creation is one of the most common OO activities. (However, set aside for now such concerns as “Factory Method” vs. “Abstract Factory”). GRASP “Creator” principle is meant to help us achieve:

  • low coupling
  • increased clarity
  • increased encapsulation
  • increased reusability

Problem statement:

Who should be responsible for creating a new instance of some class?

Solution:

Assign class B the responsibility to create an instance of class A if one of these is true (& the more the better).
  1. B “contains” or compositely aggregates A.
  2. B records A
  3. B closely uses A.
  4. B has initializing data for A (i.e., B is an Expert with respect to creating A).

Consider above example, sale will contain many SalesLineItem objects. Creator GRASP pattern suggests Sale is one object that could fulfill this responsibility.

Consequences:

  • MakeLineItem becomes a method in Sale.
  • We capture this decision in our UML design-model diagrams

Discussion:

Intent is to support low coupling (i.e., creator is found that already needs to be connected to created object). Initializing data is sometimes an indicator of a good Creator. Some object constructors have complex signatures. Which objects have the information needed to supply parameter values for such constructors?

Contraindications

Creation can be complex (recycled instances, creating an instance from a family of similar classes). May wish to use Factory Method or Abstract Factory instead in these cases.

Benefits:

Low coupling has already been mentioned. why is this good? 

Related patterns or principles:

  • Low Coupling
  • Factory Method and Abstract Factory
  • Whole-Part pattern: defines aggregate objects that support encapsulation of components

2. GRASP Information Expert

 

Problem statement

What is a general principle of assigning responsibilities to objects? Design model may end up very large (hundreds of classes and methods). If assignment of responsibilities is well chosen, result is an easy to understand system

Solution:

Assign a responsibility to the information expert. This expert is the class that has the information needed to fulfill the responsibility.

Key Idea: Start assigning responsibilities by clearly stating the responsibility.

NextGEN POS will end up with lots of functionality. One small part of this is class that knows the grand total of a sale. “Clear Statement” rule could transform this into:“Who should be responsible for knowing the grand total of a sale?”. Which class of objects has the information needed to determine the total?

Notice in above picture how the initial assignment of responsibilities drove the design:
Result is the identification of several new methods. Interaction diagram helped us capture the result. Class model entities are also modified. Also notice the degree of delegation “getSubtotal” (vs. “getPrice” and “getQuantity” to supply a multiplication operation.
Benefits:
  • Information encapsulation
  • low coupling
  • behavior is distributed across classes (i.e., high cohesion)
Related Patterns:
  • Low coupling
  • High cohesion

3. GRASP Low Coupling

Problem:

How can our design support. low dependency? low change impact? increased reuse?

Solution:

  • Assign a responsibility so that coupling remains low.
  • Use this principle to evaluate alternative assignment of responsibilities.
Key Idea: Coupling affects global understanding, but decisions about placing responsibility must be made more locally, usually by choosing from amongst alternatives.

Example:

In a POS system, dealing with Payments “what object should be responsible for associating Payments with Sales?”. Three objects appear to be involved
  • Real-world domain: Register records a Payment (Creator?)
  • Also in real-world: A Register also records Sales.
Suppose we apply our two previous GRASP patterns like so:
  • (Creator) Suggests Register as a candidate for creating Payments.
  • (Information Expert) Register knows about Payments, and therefore associates these with Sales


Another approach: (Creator) Suggests Sales creates Payments  

Kinds of Coupling
Often applied to “types” or “classes”
  • Class X  has an attribute referring to Class Y instance
  • Class X objects call on the services of a Class Y object
  • Class X has methods referencing instances of Class Y (i.e., parameters, local variables of Class Y)
  • Class X is a direct or indirect subclass of Class Y
  • Y is an interface, and Class X implements it
Note: All of these are needed at some point. We are not trying to eliminate coupling, but rather make careful choices.

There is a least one set of objects and classes to which we must allow our code to be highly-coupled

  • Java libraries (i.e., javax.swing, java.util) etc.
  • C libraries
  • .NET libraries

Key features permitting this are that these are stable and they are widespread.

4. GRASP Controller

Problem:

What first object beyond the UI layer receives and coordinates (“controls”) a system operation?

Solution:

Assign responsibility to a class based on one of the following:
  • class is “root object” for overall system (or major subsystem)
  • a new class based on use case name

Context:

This usually is applied to the actions recorded in our SSDs
  • System events generated by some GUI
  • We do not write to the GUI just yet, but assume some UI layer
Therefore we do not have “window”, “view” or “document” classes. Be very careful here as we are so tied to GUIs when visualizing applications. GUI is meant to “delegate” tasks to system

Caution:
A balance must be striked between having too many controllers and too few. More common problem is too few (i.e., “bloated controllers”)
Example:
  • Single controller classes for all events (façade)
  • Controller performs many of the events itself rather than delegate work
  • Controller maintain a lot of state about the system (e.g., variables and attributes)

5. GRASP High Cohesion

Problem:

How can we keep objects in our design focused? understandable? manageable?

Solution:

  • Assign a responsibility so that cohesion remains high.
  • As with low coupling, use this evaluate alternatives to placing responsibilities in objects

Classes that do too many unrelated things or which do too much work. Such classes are:

  • hard to comprehend
  • hard to reuse
  • hard to maintain

Delicate in that any change elsewhere in the system requires many changes in this class. In general, the greater the granularity of classes, the lower the cohesion but we do not want to go to the other extreme (i.e., lots and lots of classes, each doing one trivial thing).

Contra-indications:

  • Large class maintained by a single programmer
  • Distributed systems. Any place where the overhead of invoking an operation is a significant proportion of performing the operation

6. GRASP Polymorphism

Problem:

  • How can we handle alternatives based on type?
  • How can we create pluggable software components?
  • “Alternatives based on type”: conditional variation (“if-then-else”, examination of tags, type testing)
  • “Pluggable software components”. Usually applied to “client-server” relationships. How can we replace one server component with another and not need to rewrite the client?

Solution:

  • Use object type to declare alternative behavior.
  • Then use polymorphic operations to define the alternative behavior
  • Insight: We no longer need to test for object type, instead allowing compiler & run-time system to do this work for us.
We have seen one important flavour of this already: “Always program to an interface and not to a concrete instance.”

Example:

Consider a NextGen POS use case specifies multiple external third-party tax calculators:

  • Tax-Master
  • Good-As-Gold Tax Pro
  • Others as yet unknown

Intent is to have system integrate with each of these. Each tax calculator, however, has a different interface. Solution?

Parametric polymorphism:

What we obtain using “generics”?

Example: Creating a list of “integers” vs. a list of instances of class “B”. List operations are not re-written for different types. Impossible to insert an “integer” onto a list for class “B” instances. Range of possible types usable is infinite

Ad-hoc polymorphism:

What we obtain via subclassing. Range of possible types usable is finite (Also: this is what we get with overloading)

Contraindicators:
May not need to “future proof” the code (or at least not as much as we think). 

7. GRASP Pure Fabrication

Problem:

What object should have the responsibility, when you do not want to violate High Cohesion and Low Coupling, or other goals.

Solution:

Create an artificial or convenience class and assign a highly cohesive set of responsibilities to it. This class is literally a “fabrication” (i.e., “made out of whole cloth”). As we have total freedom in creating such a class, we get much of what we want by way of cohesion and coupling.

Example:

Sales: we need to save them in a relational database. Where do we place this functionality?
Beware:
  • Such a task may require use of a lot of database operations – which, of course, have nothing to do with “sales”.
  • Sale class would be coupled with a database API.
  • Saving data is actually a very general task; are we willing to duplicate this functionality across our design?
Solution: PersistentStorage class
This solves several design problems. Sale remains well designed, with high cohesion and low coupling. PersistentStorage class is itself relatively cohesive (i.e., sole purpose is storing or inserting objects in some persistent storage medium). PersistentStorage is generic and may be used by other classes
Note: emphasis is on where responsibility should be placed.

Contraindications:
Pure Fabrication tends to be preferred by novice designers. Also preferred by those new to object-oriented programming. Example: all functions simply become “objects”. Overuse of Pure Fabrication could lead to too many “behavioral” objects.

8. GRASP Indirection

Problem:

Where do we assign a responsibility such that we avoid direct coupling between two or more things?

Recall:

  • Coupling is necessary in systems
  • But too much coupling results in brittleness
  • When we are aware of possible brittleness, how do we deal with it?

Solution:

Assign responsibility to an intermediate object. This object “mediates” between other components or services. Therefore object and services are not directly coupled. Classic example is to use of Adapter GoF pattern
Another example is to use PersistentStorage from previous GRASP pattern. Practically every one of the GoF patterns involves indirection. “Most problems in computer science can be solved with an additional level of indirection.”

9. GRASP Protected Variations

Problem:

How can we design objects? subsystems? and systems? such that the variations in these do not have an undesirable impact on other elements in the system?

Solution:

  • Identify points of predicted variation or instability
  • Assign responsibilities to create a stable interface around them.
  • This principle is simply the source of most software engineering wisdom.
Law of Demeter

Also called “Don’t Talk to Strangers” by Larman. “Law” states that, within a method, message should only be sent to the following objects

  • The “this” object
  • A parameter of the method.
  • An attribute of “this”
  • An element of a collection which is an attribute of “this”
  • An object created within the method
Motivation behind “Law of Demeter” is that traversing path of object connections à talking to a distant stranger
Design impact:
code is now coupled to a specific structure of object connections. The farther along the path a program traverses, the more fragile the code is. In some situations, long traversals are not necessarily bad i.e., standard libraries (Java, STL).
Tagged with: Design PatternJAVAObject Oriented
 

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 

Looking for something?

Use the form below to search the site:


Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Related News Feeds

Set your Twitter account name in your settings to use the TwitterBar Section.