4. Poor software quality costs
more than $150 billion per year
in U.S. and greater than $500
billion per year worldwide
- Capers Jones
5. The city metaphor
Source: http://indiatransportportal.com/wp-content/uploads/2012/04/TrafďŹc-congestion1.jpg
6. The city metaphor
âCities grow, cities evolve, cities
have parts that simply die while other
parts flourish; each city has to be
renewed in order to meet the needs of its
populace⌠Software-intensive systems
are like that. They grow, they evolve,
sometimes they wither away, and
sometimes they flourishâŚâ
Grady Booch in the foreword for âRefactoring for Software Design Smells: Managing Technical Debtâ, Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma, Morgan Kaufmann/Elsevier, 2014.
7.
8. Modularisation in Java 9
Modularize JDK & JRE
Hide platform internal details such as sun.misc
Provide a module system for Java developers
Reference: http://paulbakker.io/java/java-9-modularity/
9. Example of beautiful design
int arr[] = {1, 4, 9, 16, 25}; // some values
// find the first occurrence of 9 in the array
int * arr_pos = find(arr, arr + 4, 9);
std::cout<< âarray pos = â<< arr_pos - arr << endl;
vector<int> int_vec;
for(int i = 1; i <= 5; i++)
int_vec.push_back(i*i);
vector<int>::iterator vec_pos = find (int_vec.begin(), int_vec.end(), 9);
std::cout<< âvector pos = â<< (vec_pos - int_vec.begin());
11. What do we mean by âprinciplesâ?
âDesign principles are key notions considered
fundamental to many different software design
approaches and concepts.â
- SWEBOK v3 (2014)
12. "The critical design tool for software development
is a mind well educated in design principles"
- Craig Larman
15. Michael Feathers
Michael Feathers coined the acronym
SOLID in 2000s to remember ďŹrst ďŹve of the
numerous principles by Robert C. Martin
16. SOLID principles
S
Single Responsibility
Principle
Every object should have a single responsibility and
that should be encapsulated by the class
O Open Closed Principle
Software should be open for extension, but closed for
modification
L
Liskovâs Substitution
Principle
Any subclass should always be usable instead of its
parent class
I
Interface Segregation
Principle
Many client specific interfaces are better than one
general purpose interface
D
Dependency Inversion
Principle
Abstractions should not depend upon details. Details
should depend upon abstractions
19. How to apply principles in practice?
Design principles
Code
How to bridge
the gap?
20. Why care about refactoring?
As an evolving program is
continually changed, its
complexity, reflecting
deteriorating structure,
increases unless work is done
to maintain or reduce it
- Lehman's law of Increasing Complexity
21. What is refactoring?
Refactoring (noun): a change
made to the internal structure of
software to make it easier to
understand and cheaper to
modify without changing its
observable behavior
Refactor (verb): to restructure
software by applying a series
of refactorings without
changing its observable
behavior
24. What are design patterns?
recurrent solutions
to common
design problems
Pattern Name
Problem
Solution
Consequences
25. Why care about patterns?
â Patterns capture expert
knowledge in the form of
proven reusable solutions
â Better to reuse proven
solutions than to âre-inventâ
the wheel
â When used correctly, patterns
positively inďŹuence software
quality
â Creates maintainable,
extensible, and reusable code
26. Design pattern catalog
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
27. Design pattern catalog
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
Creational
Deals with controlled
object creation
Factory method, for
example
Structural
Deals with
composition of classes
or objects
Composite, for example
Behavioral
Deals with interaction
between objects/
classes and
distribution of
responsibility
Strategy, for example
31. Design Practices: Even in C!
Consider the following methods from the C library:
void bcopy(const void *src, void *dst, size_t n);
void *memcpy(void *dst, const void *src, size_t n);
What is the problem in the interfaces of these methods? Does it follow the principles of good API design?
40. Intuitive overloading?
static Colour* createRGBColour(int red, int blue, int green);
static Colour* createHSBColour(float hue, float saturation, float brightness);
41. Intuitive overloading?
void log(double val) {
// prints the natural logarithm value of val
}
void log(String str) {
// logs the string str into the log file
}
42. Intuitive overloading?
void log(double val) {
// prints the natural logarithm value of val
}
void log(String str) {
// logs the string str into the log file
}
void logarithm(double val);
void logger(String str);
// or
void log(double val);
void logger(String str);
43. Preventing inheritance
// C++ Example
class NoInherit {
private:
NoInherit() {
// code for constructor
}
public:
static NoInherit* createInstance() {
return new NoInherit();
}
};
// Creation of the object
NoInherit* nip = NoInherit::createInstance();
44. Beware of versioning problems
class Base { // provided by a third party tool
public:
virtual void vfoo(){ // introduced in version 2.0
cout<< âvfoo in Base â introduced in a new versionâ;
}
// other members
};
class Derived : public Base { // some client code
public:
void vfoo(){ // was available in version 1.0
cout<< âvfoo in Deri â now becomes overriddenâ;
}
// other members
};
45. Follow âsafeâ overriding
class Base {
public:
virtual void call(int val = 10)
{ cout << âThe default value is :â<< endl; }
};
class Derived : public Base {
public:
virtual void call(int val = 20)
{ cout << âThe default value is :â<< endl; }
};
// user code:
Base *b = new Derived;
b->call();
// prints
// The default value is: 10
46. Selectively introduce types
// in mymath.h
namespace math {
class scalar { /* ⌠*/ }
class vector { /* ⌠*/ }
// other members
}
// in use.cpp
// for using std::vector:
#include <vector>
using namespace std;
// for using the scalar class in your math namespace:
#include âmymath.hâ
using namespace math;
int main() {
vector<scalar *> v;
// compiler error: vector is ambiguous
// does vector refer to std::vector or math::vector?
}
47. Selectively expose types to clients
namespace {
int someMem;
void somefunction();
};
// is a better way to limit names to file scope
// than the following:
static int someMem;
static void somefunction();
48. Hiding?
int x, y; // global variables x and y
class Point {
public:
int x, y; // class members x and y
Point(int x, int y); // function arguments x and y
};
// Point constructor for setting values of x and y data members
// C++
Point::Point(int x, int y) {
x = x;
y = y;
}
49. Beware of hiding
void foo { // outer block
int x, y;
{ // inner block
int x = 10, y = 20;
// hides the outer x and y
}
}
65. Open Closed Principle (OCP)
Bertrand Meyer
Software entities should be open for
extension, but closed for modiďŹcation
66. Variation Encapsulation Principle (VEP)
Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides
Encapsulate the concept that varies
67. Fundamental principle: Encapsulation
The principle of encapsulation advocates separation of concerns and
information hiding through techniques such as hiding implementation
details of abstractions and hiding variations
71. LSP violation
class Shape {
public:
// can throw any exceptions
virtual void rotate(int angle) = 0;
// other methods
};
class Circle : public Shape {
public:
virtual void rotate(int angle) throw (CannotRotateException) {
throw CannotRotateException();
}
// other methods
};
// client code
Shape *shapePtr = new Circle();
shapePtr->rotate(10);
// program aborts!
72. Private inheritance and LSP
class Base {};
class Derived : private Base {};
// user code
Base *b = new Derived();
// compiler error: conversion to inaccessible base class âBaseâ
85. Dependency Inversion Principle (DIP)
A. High level modules should not depend upon low level modules.
Both should depend upon abstractions.
B. Abstractions should not depend upon details. Details should depend
upon abstractions.
94. Applying DIP in OO Design
Use references to interfaces/abstract classes as ďŹelds members, as
argument types and return types
Do not derive from concrete classes
Use creational patterns such as factory method and abstract factory
for instantiation
Do not have any references from base classes to its derived classes
95. 3 principles behind patterns
Program to an interface, not to an
implementation
Favor object composition over inheritance
Encapsulate what varies
96. Cover key patterns through examples
It is not about the number of
patterns you know, but how
well you understand âwhy,
when, where, and howâ to
apply them effectively
98. Scenario
enum ColorScheme { RGB, HSB, HLS, CMYK }
class Color {
private ďŹoat red, green, blue; // for supporting RGB scheme
private ďŹoat hue1, saturation1, brightness1; // for supporting HSB scheme
private ďŹoat hue2, lightness2, saturation2; // for supporting HLS scheme
public Color(ďŹoat arg1, ďŹoat arg2, ďŹoat arg3, ColorScheme cs) {
switch (cs) {
// initialize arg1, arg2, and arg3 based on ColorScheme value
}
}
}
⢠Assume that you need to support different Color schemes in your software
⢠RGB (Red, Green, Blue), HSB (Hue, Saturation, Brightness), and HLS (Hue,
Lightness, and Saturation) schemes
⢠Overloading constructors and differentiating them using enums can become
confusing
⢠What could be a better design?
99. A solution using Factory Method pattern
Color
+ GetRGBColor()
+ GetHSBColor()
+ GetHLSColor()
RGBColor
- red : ďŹoat
- green : ďŹoat
- blue : ďŹoat
HSBColor
- hue : ďŹoat
- saturation : ďŹoat
- brightness : ďŹoat
HLSColor
- hue : ďŹoat
- lightness : ďŹoat
- saturation : ďŹoat
100. A solution using Factory Method pattern
Color
+ GetColor(ColorType)
+ âŚ
RGBColor
- red : ďŹoat
- green : ďŹoat
- blue : ďŹoat
HSBColor
- hue : ďŹoat
- saturation : ďŹoat
- brightness : ďŹoat
HLSColor
- hue : ďŹoat
- lightness : ďŹoat
- saturation : ďŹoat
102. Factory method pattern: Discussion
â A class cannot anticipate the
class of objects it must create
â A class wants its subclasses to
specify the objects it creates
DeďŹne an interface for creating an object, but let subclasses decide which class to
instantiate. Factory method lets a class defer instantiation to subclasses.
â Delegate the responsibility
to one of the several helper
subclasses
â Also, localize the
knowledge of which
subclass is the delegate
104. Scenario
public:
MyLocale (std::string language, // e.g. âen" for English
std::string script, // e.g., âArabâ for Arabic
std::string country, // e.g., âusâ for United States
std::string variant, // e.g., âTHâ for Thai
std::string extensions) // e.g., âca-buddhistâ for Thai Buddhist Calendar
⢠Assume that you have a Locale class constructor that takes many âoptional
argumentsâ
⢠Constraint: Only certain variants are allowed - you need to âdisallowâ
inappropriate combinations(e.g., invalid combination of country and variant) by
throwing IllformedLocaleException.
⢠Overloading constructors will result in âtoo many constructorsâ
⢠How will you design a solution for this?
105. Recommended solution
MyLocale aLocale =
new MyLocale.Builder
.setLanguage(âsr")
.setScript(âLatn")
.setRegion("RS")
.build();
⢠Create a Locale Builder that âbuildsâ and returns an object step-by-step
⢠Validation will be performed by the individual set methods
⢠The build() method will return the âbuiltâ object
106. Builder pattern: structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
107. Builder pattern: Discussion
â Creating or assembling a
complex object can be tedious
Separate the construction of a complex object from its representation so that the same
construction process can create different representations.
â Make the algorithm for
creating a complex object
independent of parts that
make up the object and
how they are assembled
â The construction process
allows different
representations for the
object that is constructed
109. Real scenario #1
â How will you refactor such
that:
â A speciďŹc DES, AES, TDES,
⌠can be âpluggedâ at
runtime?
â Reuse these algorithms in
new contexts?
â Easily add support for new
algorithms in Encryption?
Next change:
smelly design
116. Strategy pattern: Discussion
â Useful when there is a set of
related algorithms and a client
object needs to be able to
dynamically pick and choose
an algorithm that suits its
current need
DeďŹnes a family of algorithms, encapsulates each one, and makes
them interchangeable. Strategy lets the algorithm vary
independently from clients that use it
â The implementation of each of the
algorithms is kept in a separate
class referred to as a strategy.
â An object that uses a Strategy
object is referred to as a context
object.
â Changing the behavior of a
Context object is a matter of
changing its Strategy object to the
one that implements the required
algorithm
117. Scenario
â Consider a Route class in an
application like Google Maps
â For ďŹnding shortest path from
source to destination, many
algorithms can be used
â The problem is that these
algorithms get embedded into
Route class and cannot be
reused easily (smell!)
Route
+ SetRoute(Location, Location)
+ FindShortestPathJohnson(): Path
+ FindShortestDijkstra(): Path
+ FindShortestBellmanFord(): Path
How will you refactor such that
a) Support for shortest path
algorithm can be added easily?
b) Separate path ďŹnding logic
from dealing with location
information.
- Source: Location
- Destination: Location
118. Hands-on exercise
â Try-out strategy pattern examples
â Discuss how overriding, functors (âfunction objectsâ),
and lambdas can be used for implementing strategy
119. How about this solution?
ShortestPathAlgos
+ FindPath(): Path
JohnsonsAlgo DijkstrasAlgo
Route
+ SetRoute(Location, Location)
+ ShortestPath(): Path
BellmanFordAlgo
- Source: Location
- Destination: Location
125. More design patterns to explore
Crea%onal)
â˘âŻAbstract)factory))
â˘âŻBuilder))
â˘âŻFactory)method))
â˘âŻPrototype))
â˘âŻSingleton)
Structural)
â˘âŻAdapter))
â˘âŻBridge))
â˘âŻComposite))
â˘âŻDecorator))
â˘âŻFacade))
â˘âŻFlyweight))
â˘âŻProxy)
Behavioral)
â˘âŻChain)of)responsibility))
â˘âŻCommand))
â˘âŻInterpreter))
â˘âŻIterator))
â˘âŻMediator))
â˘âŻMemento))
â˘âŻObserver))
â˘âŻState))
â˘âŻStrategy))
â˘âŻTemplate)method))
â˘âŻVisitor)
deals with object
creation
deals with composition
of classes or objects
deals with interaction
between objects/
classes and
distribution of
responsibility
128. How about this solution?
FileFormat
+ Save()
HTMLFormat RichTextFormat
Report
+ Open()
+ Save(ReportType)
+ âŚ
SummaryReport DetailedReport
129. Youâre right: Its Bridge pattern!
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
130. An example of Bridge pattern
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
131. Bridge pattern: Discussion
â An abstraction can be designed as an
interface with one or more concrete
implementers.
â When subclassing the hierarchy, it
could lead to an exponential number of
subclasses.
â And since both the interface and its
implementation are closely tied
together, they cannot be independently
varied without affecting each other
Decouples an abstraction from its implementation so
that the two can vary independently
â Put both the interfaces and the
implementations into separate class
hierarchies.
â The Abstraction maintains an object
reference of the Implementer type.
â A client application can choose a desired
abstraction type from the Abstraction
class hierarchy.
â The abstraction object can then be
conďŹgured with an instance of an
appropriate implementer from the
Implementer class hierarchy
133. Scenario
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
135. Scenario
â How will you refactor such
that:
â You don't have to âmultiply-
outâ sub-types? (i.e., avoid
âexplosion of classesâ)
â Add or remove
responsibilities (e.g.,
scrolling) at runtime?
Next change:
smelly design
136. How about this solution?
VisualComponent
+ Draw()
TextView
+ Draw()
ScrollDecortor BorderDecorator
+ Draw()
+ ScrollTo()
- ScrollPosition
+ Draw()
+ DrawBorder()
- borderWidth
Decorator
+ Draw() component->Draw()
Decorator::Draw()
DrawBorder()
Decorator::Draw()
ScrollTo()
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
137. At runtime (object diagram)
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
138. Can you identify the pattern?
VisualComponent
+ Draw()
TextView
+ Draw()
ScrollDecortor BorderDecorator
+ Draw()
+ ScrollTo()
- ScrollPosition
+ Draw()
+ DrawBorder()
- borderWidth
Decorator
+ Draw() component->Draw()
Decorator::Draw()
DrawBorder()
Decorator::Draw()
ScrollTo()
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
139. Youâre right: Its Decorator pattern!
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
140. Decorator pattern: Discussion
â Want to add responsibilities to
individual objects (not an
entire class)
â One way is to use inheritance
â InďŹexible; static choice
â Hard to add and remove
responsibilities dynamically
Attach additional responsibilities to an object dynamically. Decorators
provide a ďŹexible alternative to subclassing for extending functionality
â Add responsibilities through
decoration
â in a way transparent to the
clients
â Decorator forwards the requests to
the contained component to
perform additional actions
â Can nest recursively
â Can add an unlimited number
of responsibilities dynamically
144. Composite pattern
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
145. Composite pattern: Discussion
â There are many situations where
a group of components form
larger components
â Simplistic approach: Make
container component contain
primitive ones
â Problem: Code has to treat
container and primitive
components differently
Compose objects into tree structures to represent part-whole hierarchies. Composite
lets client treat individual objects and compositions of objects uniformly.
â Perform recursive
composition of
components
â Clients donât have to
treat container and
primitive components
differently
147. Decorator vs. Composite
Decorator and composite structure looks similar:
Decorator is a degenerate form of Composite!
Decorator Composite
At max. one component Can have many components
Adds responsibilities Aggregates objects
Does not make sense to have
methods such as Add(),
Remove(), GetChid() etc.
Has methods such as Add(),
Remove(), GetChild(), etc.
148. Scenario
How will you design to share the
characters to save space?
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
149. Flyweight as a solution
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
150. Flyweight pattern: structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
151. Flyweight pattern: Discussion
â When an application uses a
large number of small objects,
it can be expensive
â How to share objects at
granular level without
prohibitive cost?
Use sharing to support large numbers of ďŹne-grained objects efďŹciently
â When it is possible to share
objects (i.e., objects don't
depend on identity)
â When objectâs value
remain the same
irrespective of the contexts
- they can be shared
â Share the commonly used
objects in a pool
153. Proxy pattern: example
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
154. Proxy pattern: structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
155. Proxy pattern: Discussion
â How to defect the cost of full
creation and initialization until
we really need it?
Provide a surrogate or placeholder for another object to control access to it.
â When it is possible to share
objects
â When objectâs value
remain the same
irrespective of the
contexts - they can be
shared
â Share the commonly used
objects in a pool
156. Scenario
In an application similar to MS Paint, assume that a class (say
ShapeArchiver) is responsible for archiving information about all
the drawn shapes. Similarly, another class (say Canvas) is
responsible for displaying all drawn shapes. Whenever any
change in shapes takes place, you need to inform these two
classes as to the changed information.
So, how you would like to implement this notiďŹcation?
158. Scenario
How to exploit:
a) common code segments?
b) provide extensibility for
supporting other kinds of
compressed ďŹles (e.g., rar)?
⢠You have code segments and steps for creating different kinds of compressed ďŹles,
such as zip ďŹle and gzip ďŹles. How will you unify the common steps for
compressing ďŹles and support new compression formats easily?
161. Template Method Pattern: Discussion
DeďŹne the skeleton of an algorithm in an operation, deferring some
steps to subclasses. Template Method lets subclasses redeďŹne certain steps
of an algorithm without changing the algorithm's structure.
162. Template Method in CppUnit
https://github.com/hvoigt/cppunit/blob/master/src/cppunit/TestCase.cpp
163. Scenario
How to separate:
a) code generation logic
from node types?
b) how to support different
target types?
class Plus extends Expr {
private Expr left, right;
public Plus(Expr arg1, Expr arg2) {
left = arg1;
right = arg2;
}
public void genCode() {
left.genCode();
right.genCode();
if(t == Target.JVM) {
System.out.println("iadd");
}
else { // DOTNET
System.out.println("add");
}
}
}
165. A solution using Visitor pattern
class Plus extends Expr {
private Expr left, right;
public Plus(Expr arg1, Expr arg2) {
left = arg1;
right = arg2;
}
public Expr getLeft() {
return left;
}
public Expr getRight() {
return right;
}
public void accept(Visitor v) {
v.visit(this);
}
}
class DOTNETVisitor extends Visitor {
public void visit(Constant arg) {
System.out.println("ldarg " + arg.getVal());
}
public void visit(Plus plus) {
genCode(plus.getLeft());
genCode(plus.getRight());
System.out.println("add");
}
public void visit(Sub sub) {
genCode(sub.getLeft());
genCode(sub.getRight());
System.out.println("sub");
}
public void genCode(Expr expr) {
expr.accept(this);
}
}
166. Visitor pattern: structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
167. Visitor pattern: call sequence
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
168. Visitor pattern: Discussion
â Many distinct and unrelated
operations need to be
performed on objects in an
object structure, and you want
to avoid âpollutingâ their
classes with these operations
Represent an operation to be performed on the elements of an object structure.
Visitor lets you deďŹne a new operation without changing the classes of the
elements on which it operations
â Create two class
hierarchies:
â One for the elements
being operated on
â One for the visitors that
deďŹne operations on the
elements
173. Designing a document editor
⢠How to maintain a document structure?
⢠How to support formatting?
⢠How to support embellishments
(highlighting, marking, etc) with ease?
⢠Support multiple look-and-feel
standards
⢠Support multiple windowing systems
(mac, windows, motif, etc)
⢠How to support user operations and
handle user events?
⢠How to support spellchecking and
hyphenation?
⢠âŚ.
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
174. âRecursive compositionâ
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
175. Solution using Composite pattern
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
176. More ârecursive compositionâ
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
177. âRecursive compositionâ - class design
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
178. Supporting bordering, scrolling, âŚ
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
179. Supporting multiple look-and-feel
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
180. Abstract factory: Structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
181. Supporting multiple look-and-feel
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
182. Separating implementation dependencies
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
183. Supporting user operations
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
184. Supporting user operations
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
185. Command pattern: Structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
186. Supporting undo/redo: Command history
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
187. Traversing document (e.g., spell check)
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
188. Iterator pattern: Structure
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
189. Iterator pattern: Another example
Source: âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Addison-Wesley,1994
192. Exercise: Create a suitable design
Note:&Responsibility&of&
rendering&the&line&in&chosen&
style&is&with&underlying&OS&/&
pla;orm&
Source: âRefactoring for Software Design Smells: Managing Technical Debtâ, Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma, Morgan Kaufmann/Elsevier, 2014
193. How about this solution?
Source: âRefactoring for Software Design Smells: Managing Technical Debtâ, Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma, Morgan Kaufmann/Elsevier, 2014
194. Suggested refactoring for this smell
Source: âRefactoring for Software Design Smells: Managing Technical Debtâ, Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma, Morgan Kaufmann/Elsevier, 2014