290 likes | 414 Views
Chapter 25. More GRASP Patterns. Polymorphism. Problems: Handle alternatives based on type – if a program uses if-then-else or case statement conditional logic and a new variation arises, the case logic has to be modified (in many places).
E N D
Chapter 25 More GRASP Patterns
Polymorphism • Problems: • Handle alternatives based on type – if a program uses if-then-else or case statement conditional logic and a new variation arises, the case logic has to be modified (in many places). • Create pluggable software components – How can you replace one server component with another without affecting the client?
Polymorphism • Solution: When related alternatives or behaviors vary by type (class), assign responsibility for the behavior, using polymorphic operations, to the types for which the behavior varies. • Do not test for the type of an object and use conditional logic to perform varying alternatives based on type. • E.g., in POS application, support third-party tax calculators with adapter objects.
Pure Fabrication • Problem: To which object should a responsibility be assigned when assigning it to a domain layer software class would lead to problems? • E.g., low cohesion, high coupling, low reuse potential. • Solution: Assign a highly cohesive set of responsibilities to an artificial or convenience class that does not represent a problem domain concept.
Pure Fabrication in the POS Case Study • What class should be responsible for saving Sale instances in a relational DB? • Information Expert: Have Sale do it. But: • Requires numerous supporting database-oriented operations unrelated to “sale-ness,” so incohesive • Sale has to be coupled to DB interface. • Many classes need support for saving objects in DB, so code will be duplicated across classes. • Create new class PersistentStorage. • Not a domain concept, but convenient for software developer, and highly cohesive.
Pure Fabrication in the Monopoly Case Study • Dice rolling: Player rolls all dice and sums total. • Summing service is not generalized for use in other games. • Can’t ask for current dice total without rolling again. • Add a Pure Fabrication called Cup to hold dice, roll them, and know their total. • Not a domain concept from Monopoly, but the name of the class is relevant to other games.
Types of Decomposition • Design of objects: Chosen by • Representational decomposition – software class related to/representing a domain object. • Supports low representational gap. • E.g., TableOfContents in the domain of books. • Behavioral decomposition – group by behaviors or by algorithms. • No concern for relating to real-world domain concept. • E.g., TableOfContentsGenerator is an “algorithm” object. • All GoF design patterns are Pure Fabrications.
Indirection • Problem: How do we assign responsibility to avoid direct coupling between two or more classes? • Solution: Assign responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled. • Intermediary creates indirection between other components. • “Most problems in computer science can be solved by another layer of indirection.”
Protected Variations • Problem: How do we design objects, subsystems, and systems so that the variations or instability in these elements does not have an undesirable impact on other elements? • Solution: Identify points of predicted variation or instability; assign responsibility to create a stable interface around them. • E.g., use of polymorphism to implement an adapter for external tax calculators.
Mechanisms Motivated by Protected Variations • Core Protected Variations Mechanisms • Data encapsulation, interfaces, indirection, polymorphism, standards, virtual machines … • Data-Driven Designs • Reading parameters from an external source to change behavior of a system at run time, style sheets, metadata for object-relational mapping, property files, reading in window layouts, . . . • Protects by externalizing the variant.
Mechanisms Motivated by Protected Variations, cont. • Service Lookup • Using naming services or traders to obtain a service (e.g., Java’s JNDI for Jini, or UDDI for web services). • Protected from variations in location of services. • A special case of data-driven design. • Interpreter-Driven Designs • Interpreters that execute rules/scripts read from an external source, neural network or constraint logic networks, . . . • Externalizes the logic, reads, and interprets it.
Mechanisms Motivated by Protected Variations, cont. • Reflective or Meta-Level Designs • Reflective algorithms that use introspection and meta-language services. • Another special case of data-driven design. • Standard Languages • Official language standards protect against a proliferation of varying languages. • E.g., SQL
Mechanisms Motivated by Protected Variations, cont. • Uniform Access • Some languages (Ada, Eiffel, C#) support a syntactic construct (auto getters and setters) so that both a method and field access are expressed the same way. • E.g., aCircle.radius could invoke a radius() method or directly access a public field radius. • Can change from public fields to access methods without changing client code.
Liskov Substitution Principle (LSP) • Software that refers to a type T should work as expected with any substituted implementation or subclass of T. “If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T.” • Formalizes the principle of protection against variations in different implementations of an interface, or subclass extensions of a superclass.
“Don’t Talk to Strangers” (Law of Demeter) • Within a method, messages should only be sent to the following objects: • The this (or self) object. • A parameter of the method. • An attribute of this. • An element of a collection that is an attribute of this. • An object created within the method. • Avoids coupling a client to knowledge of indirect objects.
Don’t Talk to Strangers – An Example • Avoid creating designs that traverse long object structure paths. • Mild violation of the principle: Money amount = sale.getPayment().getTenderedAmount(); • Traversing farther along a structural path: AccountHolder holder = sale.getPayment() .getAccount().getAccountHolder(); • More generally: E someE = foo.getA().getB().getC().getD().getE(); • Preferred: AccountHolder holder = sale.getAccountHolderOfPayment();
Points of Change • Variation point: A point of change in the existing, current system or requirements. • E.g., multiple tax calculator interfaces must be supported. • Evolution point: A speculative point of variation that may arise in the future, but is not present in the existing requirements. • Can be documented with UP Change Cases. • Caution: the cost of engineering protection at evolution points can be higher than reworking a simple design.
Information Hiding • David Parnas, On the Criteria to be Used in Decomposing Systems into Modules: Hide information about the design from other modules, at the points of difficulty or likely change. • The same principle as Protected Variations. • Not simply data encapsulation – that is only one technique to hide information about the design.
Open-Closed Principle (OCP) • Bertrand Meyer: Modules should be both • open (for extension; adaptable) and • closed (to modification that affects clients). • The phrase “closed with respect to X ” means that clients are not affected if Xchanges. • E.g., “the class is closed with respect to instance field definitions” through the mechanism of data encapsulation with private fields and public accessing methods.