GRASP 2 CSC 440: Software Engineering Slide #1
GRASP Patterns General Responsibility Assignment Software Patterns Describe fundamental principles of object design and responsibility assignment. Five GRASP Patterns we previously covered: 1. Information Expert 2. Creator 3. Low Coupling 4. High Cohesion 5. Controller CSC 440: Software Engineering Slide #2
Four More GRASP Patterns 1. Polymorphism 2. Indirection 3. Pure Fabrication 4. Protected Variants CSC 440: Software Engineering Slide #3
Polymorphism Pattern Name: Polymorphism Problem: How to handle alternatives based on type? Long if/elsif and switch statements make code hard to maintain. New types require editing each one. How to created pluggable software components? Pluggable components require swapping one component for another without changing design. Solution: Give the same interface (names and parameters) to services in different objects, so code can call same method, no matter which class object belongs to. Also called Subtyping. CSC 440: Software Engineering Slide #4
Polymorphism Example «interface» ITaxCalculatorAdapter gettaxes( Sale ) : List<TaxLineItems> TaxMasterAdapter gettaxes( Sale ) : List<TaxLineItems> GoodAsGoldTaxPro Adapter gettaxes( Sale ) : List<TaxLineItems>...... <???>Adapter By Polymorphism, multiple tax calculator adapters have their own similar, but varying behavior for adapting to different external tax calculators. CSC 440: Software Engineering Slide #5
Monopoly Class Diagram CSC 440: Software Engineering Slide #6
Polymorphic Interactions CSC 440: Software Engineering Slide #7
GoSquare Sequence CSC 440: Software Engineering Slide #8
RegularSquare Sequence CSC 440: Software Engineering Slide #9
TaxSquare Sequence CSC 440: Software Engineering Slide #10
JailSquare Sequence CSC 440: Software Engineering Slide #11
Implementing Polymorphism Inheritance Make each polymorphic class a subclass of an abstract superclass that defined the interface. Interfaces Create interface defining methods and parameters. Each polymorphic class will implement the interface. Required in single inheritance languages in some situations. Encapsulation Define methods with same names and parameters. Pass object with such methods as parameter to instantiation of object of primary type, which stores object as an attribute. Primary class implements method by calling encapsulated object. Dynamic typing Define methods with same names and parameters in each of a group of classes. CSC 440: Software Engineering Slide #12
Polymorphism via Inheritance class Animal def noise raise NotImplementedError end end class Dog < Animal def noise puts Bark end end class Cat < Animal def noise puts Meow end end CSC 440: Software Engineering Slide #13
Polymorphism via Interface interface Noise { void noise(); } class Dog implements Noise { public void noise() { System.out.println( Bark ); } } class Cat implements Noise { public void noise() { System.out.println( Meow ); } } CSC 440: Software Engineering Slide #14
Polymorphism via Encapsulation class Noise def initialize(noise_string) @noisestring = noise_string end def noise puts @noisestring end end class Cat def initialize(noise_object) @noise_object = noise_object end def noise @noise_object.noise() end end CSC 440: Software Engineering Slide #15
Polymorphism via Dynamic class Dog def noise puts Bark end end class Cat def noise puts Meow end end CSC 440: Software Engineering Slide #16
Pure Fabrication Pattern Name: Pure Fabrication Problem: What object should have responsibility when you don t want to violate High Cohesion and Low Coupling but solutions offered by Information Expert are inappropriate? Solution: Assign a highly cohesive set of responsibilities to a class that does not represent a problem domain concept. Such a class is a fabrication of the imagination. CSC 440: Software Engineering Slide #17
Example Problem What class should have responsibility for saving Sale objects to relational database? Expert suggests Sale. Problem: Low Cohesion Sale domain has nothing to do with databases. Problem: High Coupling Sale class has to be coupled to your specific relational database interface, limiting reuse to situations where the same database and interface are used. Objects of other classes also need to be saved to database, leading to much code duplication. CSC 440: Software Engineering Slide #18
Example Solution Create a new class that s solely responsible for saving objects in a persistent storage medium, such as a relational database. This class is not a member of the problem domain, so it s a Pure Fabrication. By Pure Fabrication PersistentStorage insert( Object ) update( Object )... CSC 440: Software Engineering Slide #19
Object-Relational Mapping To implement Persistent Storage class, we must have a way of mapping objects to relational tables in the database. The simplest mapping is: Each class is represented by a table. Each instance of class represented by a row in the table. CSC 440: Software Engineering Slide #20
Comparing SQL and ORM String sql = "SELECT... FROM persons WHERE id = 10"; DbCommand cmd = new DbCommand(connection, sql); Result res = cmd.execute(); String name = res[0]["first_name"]; Person p = repository.getperson(10); String name = p.firstname; Person p = Person.Get(10); Person p = Person.Get(Person.Id == 10); CSC 440: Software Engineering Slide #21
Object-Relational Mapping How do we represent the relationship between Sales and SalesLineItem in the relational database? We create tables for Sales and SalesLineItem. Each Sale object is a row in Sales table. Each SalesLineItem object is a row in SalesLineItem table. Each SalesLineItem row has a foreign key attribute storing the primary key of the Sale to which it belongs. To get every SalesLineItem corresponding to a Sale, we would use a query like: SELECT * FROM SalesLineItem WHERE sale= MySaleKey CSC 440: Software Engineering Slide #22
Object-Relational Mapping Object-relational mapping is a complex topic What about many-to-many relationships? What about recursive relationships? Hierarchical organizational charts, where management relations are between two objects of the Person class. Future design patterns will offer help in dealing with more complex O-R mapping in later iterations. CSC 440: Software Engineering Slide #23
Popular ORMs CSC 440: Software Engineering Slide #24
Discussion The design of objects can be broadly divided into two groups: Objects chosen by representational decomposition. ex: Sale represents a concept in problem domain. ex: TableOfContents represents a concept in problem domain. Objects chosen by behavioral decomposition (fabrications). ex: ProcessSaleHandler represents a behavior of the system. ex: TOCGenerator represents a behavior of the system. Many GoF design patterns, such as Adapter, Command, Strategy, etc. are Pure Fabrications. CSC 440: Software Engineering Slide #25
Benefits High Cohesion is supported because responsibilities are factored into a fine-grained class that only focuses on a specific set of related tasks. Reuse potential may increase because of the presence of fine-grained Pure Fabrication classes, like Persistent Storage, which have applicability in other applications. CSC 440: Software Engineering Slide #26
Indirection Pattern Name: Indirection Problem: Where to assign a responsibility while avoiding direct coupling between two components? How to decouple objects so that low coupling is supported and reuse potential remains higher? Solution: Assign the responsibility to an intermediate object to mediate between other components so that they aren t directly coupled. CSC 440: Software Engineering Slide #27
Example TaxCalculatorAdaptor Act as intermediator to external tax calculator. Allows Polymorphism to be used to handle calculator variations. : Sale :TaxMasterAdapter t = gettotal... taxes = gettaxes( s ) TCP socket communication xxx... «actor» :TaxMasterSystem the adapter acts as a level of indirection to external systems CSC 440: Software Engineering Slide #28
Example 2 PersistentStorage Pure Fabrication example is also an example of the Indirection pattern of assigning responsibilities. Class acts as an intermediary between Sale class and database service. CSC 440: Software Engineering Slide #29
Discussion All problems in computer science can be solved by another layer of indirection. David Wheeler Many GoF design patterns are specializations of Indirection: Adapter Façade Observer Reduces coupling between components. CSC 440: Software Engineering Slide #30
Protected Variations Pattern Name: Protected Variations Problem: How to design objects, subsystems, and systems so that the variations or instability in these elements not have an undesirable impact on other elements? Solution: Identify points of predicted variation or instability; assign responsibilities to create a stable interface around them. CSC 440: Software Engineering Slide #31
Example The external tax calculator problem Point of instability: different APIs of different tax calculators. POS system needs to integrate with current and future different tax APIs. Solution: Add layer of indirection, the tax calculator adaptor classes, between system and varying tax APIs. Use polymorphism to treat different tax calculator adapter classes in the same way. CSC 440: Software Engineering Slide #32
Examples Data-driven designs. Style sheets, ORM metadata, property files. Service Lookup Using an intermediary service to look up services by name, like Sun RPC portmapper. Interpreters Make application scriptable to enable varying behavior. Virtual Machines CSC 440: Software Engineering Slide #33
Points of Change Variation Point Variations on the existing, current system or requirements. Evolution Point Points of variation that aren t present but may arise in the future. CSC 440: Software Engineering Slide #34
Structure-Hiding Designs Avoid creating designs that traverse long object structure paths, or send messages to distant, indirect objects. Why? Decrease coupling. Long paths to an object have multiple potential points of change. CSC 440: Software Engineering Slide #35
Structure-Hiding Designs Within a method, send messages only to self Objects that are parameters of the method. Attributes of self. An element of a collection that is an attribute of self. An object created within the method. CSC 440: Software Engineering Slide #36
Level of Developers Novices Tend toward simple, brittle designs that are difficult to modify. Intermediate Developers Tend toward overly fancy and flexible, generalized designs, where effort is wasted in future proofing points that never change. Expert Designers Use Protected Variations when necessary and avoid using it where unnecessary. CSC 440: Software Engineering Slide #37