Lecture 09 Design Patterns

advertisement
CS5103
Software Engineering
Lecture 09
Software Design and
Design Patterns
Last class

Sequence diagrams

Software architecture


2
Why? Higher level design of larger software
projects
Software architectural styles

Pipe and Filter

Layered

Repository
Today’s class


3
Software Design

Process

Factors

Measures
Design Patterns

Composite pattern

Factory pattern

Visitor pattern
Software Design Process

Software design is usually created in two stages

Architecture design

Detail design (component-level design)


4

Design patterns

Design classes
Design review
Other design issues

Refactoring

UI Design
Software Design Factors

Fundamental software design factors

5
Modularity

Abstraction

Information hiding

Component independence

Fault prevention and fault tolerance
Modularity and Abstraction

When we consider modular solutions to any
problems, many levels of abstraction can be posed



At the lower levels of abstraction, a more detailed
description of the solution is provided: class diagrams
Modularity hides details and facilitates evolvement

6
At the highest level of abstraction, a solution is stated in
broad terms of problem domain: architecture
Each component hides a design decision from the others
Component Independent


7
We strive in most designs to make the components
independent of one another, why?
We measure the degree of component
independence using two concepts

Low coupling

High cohesion
Coupling and Cohesion

Coupling




Two components are loosely coupled when they have some
dependence, but the interconnections among them are
weak
Two components are uncoupled when they have no
interconnections at all
Cohesion

8
Two components are highly coupled when there is a great
deal of dependence between them
A component is cohesive if the internal parts of the
component are related to each other and to its overall
purpose
Decoupling

Most difficult part in design: Need tradeoff

Consider the following case:

Online and offline bookstore components

Both need shopping cart checkout



9
Should we have a shopping cart checkout module for both
of them? Or have one, and let the two components to call
the module?
Consider potential changes on overall book discount policy
and specific book discount policy?
Solution for the dilemma: break the checkout module, still
not perfect
Fault defense & tolerance


Defensive design anticipates situations the might
lead to problems

Network Failure

Data corruption

Invalid user inputs
Tolerate runtime errors



10
Exception handling
Redundant components (distributed system or critical
software)
Timely error reporting
Criteria for Good Software Design

11
High-quality designs should have characteristics
that lead to quality products

Correct translation from the requirements specification

Ease of understanding

Ease of implementation

Ease of testing

Ease of modification
Criteria for Good Software Design




12
Architecture

Using suitable architectural styles or patterns

Loose-coupled components

Can be implemented in an evolutionary fashion
Classes at a suitable abstract level
Interfaces are clear and minimize the data
transfer
Design using a effective notation
Software Design Evaluation and
Validation

We check a design in two different ways



13
Validation: the design satisfies all requirements specified
by the customer
Verification: the characteristics (quality) of a good
design are incorporated
We use some techniques for helping us to perform
verification and validation

Measuring design quality

Design reviews
Measuring Software Design Quality

14
We check a design using a set of measures

Coupling

Cohesion

Complexity

Basic metrics: size

Depths of relations

Cyclomatic complexity
Design reviews

15
We check a design

Designers

Customers

Analysts

prospective users

Developers

Moderator leading the discussions

Secretary recording the issues
Design Patterns

Become popular due to a book



16
Design Patterns: Elements of Reusable ObjectOriented Software
Gang of Four: Gamma, Erich; Richard Helm,
Ralph Johnson, and John Vlissides
Provide solutions for common problems
in micro-design
Design Patterns Structure

Name


Problem solved


When to apply the pattern
Solution

17
Important to know for easier communication between
designers
Usually a class diagram segment (sometimes attributes
and operations)
Design Patterns

Structure Patterns


Creation Patterns


Factory
Behavioral Patterns

18
Composite
Visitor
Running Example

19
A Document Editor

Text and graphics can be freely mixed

Graphical user interface

Support different look-and-feel GUI styles

Traversal operations: spell checking
Composite Pattern: Example

A document is represented by structure

Primitive glyphs

20
Characters, circles, pictures

Lines: A sequence of glyphs

Columns: A sequence of Lines

Pages: A sequence of Columns

Documents: A sequence of Pages
Example of Hierarchical Document
21
Possible Designs?
Document

1
*
Page
Classes of Character, Circle, Pictures, lines,
Columns, pages, document

Composition relationship between classes

Not so good, why?

A lot of duplication:
1*
Column
1*
Line
1
*
Glyph

all classes has onClick, draw behavior

Difficult to add or remove levels in hierarchy

Character
22
Picture
Traverse/display operations need to change for
any change of the hierarchy
Alternate Designs

One class of Glyph



23
All elements are subclasses of Glyph
All elements uniformly present the same
interface

How to draw

Computing bounds

Mouse hit detection

…
Make extending the class easier
Logic Object Structure
24
Logic Object Structure
25
Composite Pattern

Applies to any hierarchy structure

Leaves and internal nodes have similar functionality

Pros:


Easy to add, remove new types

Clean interface
Cons:


26
Add corner cases
Enforce certain type of elements only have
certain types of children
Problem: Supporting look-and-feel
settings

Different look-and-feel standards


Appearance of scrollbars, menus, windows,
etc., set by the user
We want to support them all



27
For example: having classes MotifScrollBar
and WindowsScrollBar
Both are subclasses of ScrollBars
How should we create a new scrollbar in a
window?
Possible designs?

Terrible
ScrollBar sc = new WindowScrollBar();

Better, problems?
If (style==MOTIF){
sc = new MotifScrollBar();
}else{
sc = new WindowScrollBar();
}
28

Conditions for other UI elements: menus, etc.

Hard to add new styles
Factory Pattern


29
One method to create a look-and-feel dependent
object
Define a GUIFactory Class

One GUIFactory object for each look and feel

Create itself using conditions set by the user
Factory Pattern
30
Factory Pattern: factory design
abstract class GUIFactory{
abstract ScrollBar CreateScrollBar();
abstract Menu CreateMenu();
...
}
31
class MotifFactory extends GuiFactory{
ScrollBar CreateScrollBar(){
return new MotifScrollBar()
}
Menu createMenu(){
return new MotifMenu();
}
...
}
Factory Pattern: GUI code
GuiFactory factory;
if(style==MOTIF){
factory = new MotifFactory();
}else if(style==WINDOW){
factory = new WindowFactory();
}else{
...
}
ScrollBar bar = factory.createScrollBar();
Menu mn = factory.createMenu();
32
Factory Pattern

Applies to the object creation of a family of
classes

The factory can be changed at runtime

Pros & Cons



33
Lift the conditional creation of objects to the
creation of factories
Flexible for add new type of objects
Sometimes make the code more difficult to
understand
Spell Checking Problem

Considerations

Requires to traverse the document

Need to see every glyph in order

There maybe other analyses that require
traverse the document
 Counting
34
words, Grammar checking
Possible design
class Glyph{…
void spellCheck(char[] curWord):
for(int i = 0; i<this.children.length; i++):
this.children[i].spellCheck(curWord);
if(this isa character):
if(this == space):
Util.SpellCheck(curWord); curWord.clear();
else:
curWord.append(this);
…}
35
Other Actions

36
Document Stats

counting words,

counting pictures,

counting lines, columns, pages)

Find a word

Change line-break rules

…
Now we have

A large number of similar methods


Code duplication always causes problems


37
All need to traverse the document
change the data structure of “children” from
array to list (better insertion and deletion)
Skip full-picture page to enhance
performance for word-related tasks
Solution

Visitor pattern

Decouple traverse process and action

Write traverse code only once

38
Each element in the hierarchy under traverse
has an “action” code
Visitor pattern basic design
class Glyph{…
void scan(Visitor v):
for(int i = 0; i<d.children.length; i++):
d.children[i].scan(v);
…}
We have different visitors: spellcheckVisitor,
documentStatVisitor, etc.
39
Solution
40
Code of SpellCheckVisitor
class SpellCheckVisitor extends Visitor{
char[] curWord = {};
void visitChar(Character c){
if(c==SPACE):
spellCheck(curWord);
curWord.clear();
else:
curWord.add(c);
}
}
41
Still have problems



42
How about counting all glyphs (including
picture, character, circle)?
Need to change visitPicture, visitCharacter,
and visitCircle?
Add visitGlyph
Add VisitGlyph
class Glyph{
…
scan(Visitor){
for each c in children:
v.visitGlyph(c)
c.Scan(v)
}
…
}
43
Code of CountGlyphVisitor
class CountGlyphVisitor extends Visitor{
int count = 0;
void visitGlyph(Glyph g){
if(g.children.length==0):
count++;
}
}
}
44
Summary of design patterns

Major aim: decoupling

pros:


more flexibility

less changes when modification is required
Cons:



45
not intuitive at the beginning, harder to read code, but
get easier when you are familiar with the pattern
Trouble for verifications and analysis (often not scalable
without a design pattern)
So it is rather popular!
Other useful design patterns

Observer

Facade

Factory method

Decorator

Bridge

See them in wiki pages or read the book

46
Design Patterns: Elements of Reusable Object-Oriented
Software
Today’s class


47
Software Design

Design process

Design factors

Design evaluation
Design Patterns

Composite pattern

Factory pattern

Visitor pattern
Next Class

48
Software Implementation: Versioning

Why versioning?

Versioning tools

CVS

SVN

GIT
Thanks!
49
A controversial pattern:
singleton pattern

Problem


50
How to make sure a class only has one object

File system

Windows manager

…
The class itself is made responsible for keeping
track of its instance. It can thus ensure that no
more than one instance is created. This is the
singleton pattern.
Singleton Pattern
Singleton
static uniqueInstance
singletonData
static Instance()
SingletonOp()
GetSingletonData()
return uniqueinstance
Singleton Pattern: code
class Singleton {
// Only one instance can ever be created.
public:
static Singleton Instance();
protected:
// Creation hidden inside Instance().
Singleton();
private:
Static Singleton _instance
}
// Cannot access directly.
Singleton Pattern: code
Singleton _instance;
Singleton Instance(){
if (_instance ==null) {
_instance=new Singleton;
}
Return _instance;
}
// Clients access the singleton
// exclusively via the Instance member
// function.
Singleton Pattern

Pros



54
Controls the number of instances (no need to
refer to another class)
Lazy initialization
Cons

Latent coupling between components and singleton

Singleton may have states: hard to test

Cannot extend singleton class

Terrible in multi-thread if not well implemented
View points



55
We love singletons (getting weaker and weaker in
the past 10 years)
Singletons are evil, actually an anti-pattern (many
people believe this)
Use singletons carefully and only when no other
alternatives, control the number of singleton
classes in your project
Alternative

Dependency injection:

56
Create the object at the beginning and
pass it as a parameter
A story from google
A new developer go to a group and want to try on some methods
testCreditCardCharge() {
CreditCard c = new CreditCard(
"1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
This code:
Only works when you run as part of the suite.
When run in isolation, throws NullPointerException.
When you get your credit card bill, you are out $100 for every time the test runs.
57
A story from google
After a lot of digging, you learn that you need to initialize the
CreditCardProcessor.
testCreditCardCharge() {
CreditCardProcessor.init();
CreditCard c = new CreditCard(
"1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
Still not working
58
A story from google
After a lot of digging, you learn that you need to initialize the
OfflineQueue.
testCreditCardCharge() {
OfflineQueue.init();
CreditCardProcessor.init();
CreditCard c = new CreditCard(
"1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
Still not working
59
A story from google
After a lot of digging, you learn that you need to initialize the
Database.
testCreditCardCharge() {
Database.init();
OfflineQueue.init();
CreditCardProcessor.init();
CreditCard c = new CreditCard(
"1234 5678 9012 3456", 5, 2008);
c.charge(100);
}
But sometimes you have to find out the correct sequence!
60
Solution with dependency injection
testCreditCardCharge() {
Database db = Database();
OfflineQueue q = OfflineQueue(db);
CreditCardProcessor ccp = new CreditCardProcessor(q);
CreditCard c = new CreditCard(
"1234 5678 9012 3456", 5, 2008);
c.charge(ccp, 100);
}
61
Download