View
232
Download
0
Tags:
Embed Size (px)
Citation preview
Chapter 8, Object Design: Reuse and Patterns
Qutaibah MalluhiSoftware EngineeringQatar University
Based on slides by Bernd Bruegge & Allen H. Dutoit
Object Design Analysis
Determines what the implementation must do (What) Analysis object model: Skeleton of the final system
System design Formulates the plan of attack (How), But on a very high level (subsystems, layers and partitions).
Object design Carries out the plan of attack! Process of adding details to the previous models and making
implementation decisions Iterates on and refines the previous models Full definitions of classes and associations used in the
implementation, as well as the interfaces and the algorithms of the methods used to implement operations.
Basis of implementation
Overview of Object Design Activities
Reuse: Identification of existing solutions Proper use of inheritance Off-the-shelf components Design patterns Frameworks
Interface specification Describes precisely each class interface
Object model restructuring Transforms the object design model to improve
its understandability and extensibility
Object model optimization Transforms the object design model to address
performance criteria such as response time or memory utilization.
Chapter 8
Chapter 9
Chapter 10
Agenda
Reuse ConceptsSolution domain objects, Inheritance, and
design patterns Implementation versus Interface
Inheritance Delegation Components and Design Patterns (Student
Presentations)
Moving to the Solution Domain
New objects are often needed during object design: The use of design patterns introduces new classes The implementation of algorithms may necessitate objects to hold
values New low-level operations may be needed during the decomposition
of high-level operations
Example: The EraseArea() operation in a drawing program. Conceptually very simple Implementation
Area represented by pixels Repair () cleans up objects partially covered by the erased area Redraw() draws objects uncovered by the erasure Draw() erases pixels in background color not covered by other objects
The Use of Inheritance
Description of Taxonomies Used during requirements analysis.
Activity: identify application domain objects that are hierarchically related
Goal: make the analysis model more understandable
Specialization or generalization
Enhance Reuse Used during object design Reduce redundancy: factor out common behavior
May lead to implementation inheritance– see later
Extensibility: specify abstract classes and interfaces Typically leads to interface inheritance– see later
Metamodel for Inheritance
Inheritance is used during analysis and object design
Inheritance
InterfaceInheritance
ImplementationInheritance
Inheritancefor ReuseTaxonomy
Inheritance detectedby generalization
Inheritance detectedby specialization
Analysisactivity
Object Design
Implementation Inheritance vs. Interface Inheritance Implementation inheritance
Reuse the implementation Typically corresponds to “extends” in Java Goal: Extend an applications’ functionality by reusing
functionality that exist in parent class
Interface inheritance Reuse the interface Typically corresponds to “implements” in java
Not necessarily. “extends” if an abstract class is used instead of interface
Inherit from an abstract class with all operations specified, but not yet implemented
Taxonomy Example
Mammal
Tiger Wolf Wale
Employee+printInfo()
Faculty+printInfo()
Staff+printInfo()
Secretary+printInfo
Engineer+printInfo()
Specialization
Interface Inheritance Examples
Example 1: Dealing with multiple image formats Abstract Image class defining all operations images
should support Series of specialized image classes for different
formats: GIFImage, JPEGImage, etc. The application deals with the Image superclass Application can support new image formats by simply
adding another specialized subclass (E.g. TiffImage) Example 2: Dealing with multiple drawing objects
Abstract DrawingObject class Many specializations Rectangle, Circle, etc.
Problem with implementation inheritance:• Some of the inherited operations might exhibit unwanted
behavior.• What happens if the Stack user calls Remove() instead of
Pop()?
Example: I have a List class, I need a Stack class. How about subclassing the Stack class from the List class and providing three methods, Push() and Pop(), Top()?
Add ()
Remove()
List
Push ()Pop()
Stack
Top()
“Already implemented”
Implementation Inheritance
A very similar class is already implemented that does almost the same as the desired class implementation.
Problem with implementation inheritance
Some of the inherited operations might exhibit unwanted behavior. What happens if the Stack user calls Remove() instead of Pop()? This will lead to inability to change stack implementation after
clients start using it because some clients may be using remove() Solve by overriding all superclass (List) methods.
Unwanted methods can through exception More complex class that is difficult to understand and reuse
Inheritance decouple the classes using the superclass from the specialized subclass but introduces strong coupling between the subclass and its superclass. This strong coupling is sometimes unwanted (as in the above example)
Client Receiver DelegateDelegates to calls
Delegation as alternative to Implementation Inheritance A class A is said to delegate to class B if it implements an
operation by resending a message to B In delegation two objects are involved in handling a
request A receiving object delegates operations to its delegate. The developer can make sure that the receiving object does not
allow the client to misuse the delegate object
Delegation instead of Implementation Inheritance Inheritance: Extending a Base class by a new operation or
overwriting an operation. Delegation: Catching an operation and sending it to another object.
Use aggregation relationship (List object is included in Stack)
Which of the following models is better for implementing a stack?
+Add()+Remove()
List
Stack
+Push()+Pop()+Top()
+Push()+Pop()+Top()
Stack
Add()Remove()
List
Delegation vs. Implementation Inheritance
DelegationPro: Flexibility: Any object can be
replaced at run time by another one E.g. change implementation of
stack to use an array without affecting clients
Con: Inefficiency: Objects are
encapsulated. E.g. instance of list must be
held inside the stack
Implementation InheritancePro: Straightforward to use
Con: Inheritance exposes a subclass
to the details of its parent class Any change in the parent class
implementation forces the subclass to change (which requires recompilation of both)
When should we use inheritance?When should we use inheritance?
Liskov Substitution Principle (LSP) “If an object of type S can be substituted in all the places
where an object of type T is expected, then S is a subtype of T”
“All derived classes must be substituteable for their base class”
LSP Gives a good check of when to use inheritance by providing a formal definition of interface inheritance.
Demand no more, promise no less Demand no more: the subclass would accept any arguments that
the superclass would accept. Promise no less: Any assumption that is valid when the
superclass is used must be valid when the subclass is used. Interface inheritance – The principle applies
e.g. substitute Image by GIFImage Implementation inheritance – Does not always apply. If it
does not, use delegation instead.
The Liskov substitution principle
Implementation inheritance When you use List to implement Stack (in Java), use
delegation (composition), not inheritance. The intention is that you use only List’s implementation
Implementation inheritance but not interface inheritance
List+add()+remove()+find()
Stack+push()+pop()+isEmpty()
<foundation>
List+add()+remove()+find()
Stack+push()+pop()+isEmpty()
List+add()+remove()+find()
Stack+push()+pop()+isEmpty()
MyList
The Liskov substitution principle
Rectangle-int width;-int height+getWidth()+setWidth()+getHeight()+setHeight()+area();
class Square extends Rectangle { public void setWidth(int width) { super.setWidth(width); super.setHeight(width); } public void setHeight(int height) { super.setHeight(height); super.setWidth(height); }}void clientOfRectangle(Rectangle r) { r.setWidth(10); r.setHeight(20); print(r.area());}Rectangle r = new Square(…);clientOfRectangle(r); // what would be printed?
Square+getWidth()+setWidth()+getHeight()+setHeight()
IS-A
Substituting a rectangle byA square produced differentresults
Rectangle and Square
Clients (users) of Rectangle expect that setting height leaves width unchanged (and vice versa)
Square does not fulfil this expectation Client algorithms can get confused
Hack: attempt to identify subclasses and use if/switch Evil that you want to prevent
Many design patterns use a combination of inheritance
and delegation
Many design patterns use a combination of inheritance
and delegation
Will see a few examples of Design Patterns
Design Patterns
Template solutions that developers have refined over time to solve a range of recurring problems.
Design pattern elementsNameProblem DescriptionSolutionConsequences
Popular Reference on Design Patterns
The concept of Design Patterns gained popularity after this popular excellent book
“Design Patterns: Elements of Reusable Object-Oriented Software” by GoF (Gang of Four:
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides)
published in 1994
Check course website for otherreferences
Pattern Example: Adapter Pattern “Convert the interface of a class into another
interface that clients expect.” Also known as a wrapper Used to provide a new interface to existing legacy
components. Motivation:
Adapter is often used when we create an application using library classes, but where we want to retain the flexibility to select alternative library classes.
Use it when you want to use the functionality provided by an existing application modify our application as little as possible be able to easily switch to alternative implementations
Adapter Pattern
Name Adapter Design Pattern
Problem Description: Convert the interface of a legacy class into a different interface
expected by the client, so that the client and the legacy class can work together without change
Solution: See next slide
Consequences Client and LegacyClass work together without modification Adapter works with LegacyClass and all its subclasses A new Adapter needs to be written for each specialization (e.g.,
subclass) of ClientInterface
Delegation is used tobind an Adapter and an Adaptee
Interface inheritance is used to specify the interface of the Adapter class.
Target and Adaptee (usually called legacy system) pre-exist the Adapter.
Target may be realized as an interface or abstract class in Java.
Adapter Pattern Solution
ClientClientInterface
Request()
LegacyClass
ExistingRequest()
Adapter
Request()
adaptee
target Adaptee
Adapter Solution with Sequence Diagram
:Adapteradaptee
:RequiredClass
:AbstractClass:Client
SequenceDiagram for
Adapter
clientNameForRequiredMethod()
requiredMethod()
adaptee
AbstractClass or InterfaceclientNameForRequiredMethod()
AdapterclientNameForRequiredMethod()
RequiredClassrequiredMethod()
Client
{ adaptee.requiredMethod (); }
Adapter Design Pattern: Example I
Implement a stack using List where both List object and stack interfaces exist.
ClientStack
Push(element)
List
Add(element)
myStack
Push(element)
myStack
Push(element)
adaptee
Adapter Design Pattern: Example II
Existing Financial System: Legacy application that computes the principal money obtained from investing
FinancialAdapteramount()
PrincipalcomputeValue()
Financialamount()
Client
{ adaptee.requiredMethod (); }
Application Legacy systemAdaptation
Legacy application …..: computeValue (float years, float interest, float amount)New application …….: amount (float originalAmount, float numYears, float intRate)
Legacy Adaptee
ImplementationClass FinancialAdapter extends Financial{ principal legacyAdaptee = null; // Constructors go here . . . /** This method uses the legacy computeValue() method */ float amount ( float originalAmount, float unmYears, float intRate) { return legacyAdaptee.computeValue ( originalAmount, numYears, intRate); }}
The client could be written with a to use an instance of FinancialAdapter through a Financial (abstract) variable.
All calls to the amount () method of Financial are passed to the legacy method computeValue().
Abstract Factory Pattern
Consider a user interface toolkit to support multiple look-and-feel standards.
For portability an application must not hard-code its widgets for one look and feel.
How to design the application so that incorporating new look and feel requirements will be easy?
Different Look-and-Feel
Abstract Factory Solution
Define an abstract WidgetFactory class. This class declares an interface to create different
kinds of widgets.
There is one abstract class for each kind of widget and concrete subclasses implement widgets for different standards.
WidgetFactory offers an operation to return a new widget object for each abstract widget class. Clients call these operations to obtain instances of
widgets without being aware of the concrete classes they use.
Widget Factory
CreateScrollBar()
CreateWindow()
WinWidgetFactory
CreateScrollBar()
CreateWindow()
MacWidgetFactory
CreateScrollBar()
CreateWindow()
Client
Windows
MacWindow WinWindow
ScrollBar
MacScrollBar WinScrollBar
Abstract Factory Solution
ABSTRACT FACTORY Pattern
Problem: Provide an interface for creating families of related or dependent
objects (platforms) without specifying their concrete classes Shield client from the implementation of the different families of
products (platforms) Solution:
Abstract ProductFactory class. Contains methods for creating each basic kind of widget
Concrete factory for each platform (family of products) Abstract class for each kind of product, Concrete classes implement specific platform widgets
Client deals with abstract ProductFactory and abstract product objects (i.e., independent of concrete implementation)
Abstract Factory
CreateProductA()
CreateProductB()
ConcreteFactory1 ConcreteFactory2
Client
AbstractProductA
ProductA2 ProductA1
ProductB2 ProductB1
CreateProductA()
CreateProductB()
CreateProductA()
CreateProductB()AbstractProductB
Abstract Factory Structure
ABSTRACT FACTORY Participants
AbtractFactory Declares interface for operations that create abstract product
objects ConcreteFactory
Implements operations to create concrete product objects AbstractProduct
Declares an interface for a type of product object ConcreteProduct
Defines a product object to be created by concrete factory Implements the abstract product interface
Client Uses only interfaces declared by AbstractFactory and
AbstractProduct classes
Abstract Factory Applicability
Independence from initialization or representation: The client system should be independent of how its products are
created, composed or represented. Manufacturer Independence:
A system must be configured with one of multiple families of products.
You want to provide a class library for a customer (E.g., “dynamic look-and-feel”), but you don’t want to reveal what particular product you are using.
Constraints on related products: A family of related products is designed to be used together
and you need to enforce this constraint. Cope with upcoming change:
You use one particular product family, but you expect that the underlying technology is changing very soon, and new products will appear on the market.
Abstract Factory Examples of Use
User interface toolkit supports multiple look-and-feel standards(Motif, Presentation Manager)
Different appearances and behaviors for UI widgets Applications should not hard-code its widgets
An intelligent house system dealing with multiple families of products coming from different manufacturers. Example of a family of products: (light bulb, blinds, electrical
switch, etc.) One product from one family (e.g. light-bulb) is incompatible with
another product from a different family (e.g. switch)
Component Selection
Select existing off-the-shelf class libraries frameworks or components
Adjust the class libraries, framework or components Change the API if you have the source code. Use the adapter or bridge pattern if you don’t have
access
Architecture Driven Design
Reuse...
Look for existing classes in class libraries JSAPI, JTAPI, ....
Select data structures appropriate to the algorithms Container classes Arrays, lists, queues, stacks, sets, trees, ...
It might be necessary to define new internal classes and operations Complex operations defined in terms of lower-level
operations might need new classes and operations
Frameworks
A framework is a reusable partial application that can be specialized to produce custom applications.
Frameworks are targeted to particular technologies, such as data processing or cellular communications, or to application domains, such as user interfaces or real-time avionics.
The key benefits of frameworks are reusability and extensibility. Reusability leverages of the application domain knowledge and prior
effort of experienced developers Extensibility is provided by hook methods, which are overwritten by the
application to extend the framework. Hook methods systematically decouple the interfaces and behaviors of an
application domain from the variations required by an application in a particular context.
Classification of Frameworks
Frameworks can be classified by their position in the software development process.
Frameworks can also be classified by the techniques used to extend them. Whitebox frameworksBlackbox frameworks
Frameworks in the Development Process Infrastructure frameworks aim to simplify the software
development process System infrastructure frameworks are used internally within a
software project and are usually not delivered to a client.
Middleware frameworks are used to integrate existing distributed applications and components. Examples: MFC, DCOM, Java RMI, WebObjects, WebSphere,
WebLogic Enterprise Application [BEA].
Enterprise application frameworks are application specific and focus on domains Example domains: telecommunications, avionics, environmental
modeling, manufacturing, financial engineering, enterprise business activities.
White-box & Black-Box Frameworks
Whitebox frameworks: Extensibility achieved through inheritance and dynamic binding. Existing functionality is extended by subclassing framework base
classes and overriding predefined hook methods Often design patterns such as the template method pattern are
used to override the hook methods.
Blackbox frameworks Extensibility achieved by defining interfaces for components that
can be plugged into the framework. Existing functionality is reused by defining components that
conform to a particular interface These components are integrated with the framework via
delegation.
Class libraries and Frameworks
Class Libraries: Less domain specific Provide a smaller scope of reuse. Class libraries are passive; no constraint on control flow.
Framework: Classes cooperate for a family of related applications. Frameworks are active; affect the flow of control.
In practice, developers often use both: Frameworks often use class libraries internally to simplify the
development of the framework. Framework event handlers use class libraries to perform basic
tasks (e.g. string processing, file management, numerical analysis…. )
Components and Frameworks Components
Self-contained instances of classes Plugged together to form complete applications. Blackbox that defines a cohesive set of operations, Can be used based on the syntax and semantics of the
interface. Components can even be reused on the binary code level.
The advantage is that applications do not always have to be recompiled when components change.
Frameworks: Often used to develop components Components are often plugged into blackbox frameworks.
Summary Object design closes the gap between the requirements and the
machine. Object design is the process of adding details to the requirements
analysis and making implementation decisions Object design activities include:
Identification of Reuse Identification of Inheritance and Delegation opportunities Design pattern selection Frameworks selection Component selection
Interface specification (next chapter) Object model restructuring Object model optimization
Object design is documented in the Object Design Document, which can be automatically generated from a specification using tools such as JavaDoc.
Lecture on Mapping Models to Code
Planning Ahead
Object Design: Specifying interfaces Mapping Models to Code Testing
Coping with Change
Agile methodologies and Extreme Programming Will not use the textbook. See Website
resources
Presentations+ wrap-up session
1-2 Lectures