0% found this document useful (0 votes)
13 views

11-Design

Uploaded by

nvm2phvgpy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

11-Design

Uploaded by

nvm2phvgpy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 56

Design

Design Overview
Software design is an iterative process through which
requirements are translated into a “blueprint” for
constructing the software.
▪ Initially, the blueprint depicts a holistic view of software.
That is, the design is represented at a high level of
abstraction
▪ Directly traced to the specific system objective and
more detailed data, functional, and behavioral
requirements
▪ During the design process refinements lead to much
lower levels of abstraction
Design Overview
Requirement/User Story
As a student, I want to search for courses through a search
page.
▪ What are the components/objects?
▪ Search Page
▪ Courses
▪ Do we need the student as an object?
▪ What questions could we ask to further refine?
Design Refinement
Requirement/User Story
As a student, I want to search for courses
through a search page.
▪ New Components: Button, Input Field,
Results Page
▪ Connections: to the new components
▪ Does the University already have a course
database to connect to?
▪ Components/Modules – turns into
collections of functions, classes, or other
components. These pieces represent
simple problems that the developers
individually implement.
Module/Design
Sequence Diagram
Design: Object Interactions
System Sequence Diagram

Controller : Checker : KeyStorage : LockCtrl

User
«initiating actor»
ystem
: System
Timer
«offstage actor»
checkKey()
sk := getNext()
select function(“unlock")

prompt for the key


alt val != null setOpen(true)
enter key
verify key

signal: valid key, lock open


open the lock,
[else] val == null : setLit(true)
turn on the light

start ("duration“)

• System Sequence Diagrams represent interactions of actors


• Module Sequence Diagrams represent interactions of modules inside the system
System Sequence Diagrams
Use case: Unlock
System Sequence Diagrams
represent interactions between the : System
User LockDevice LightSwitch Timer
actors and the system. «initiating actor» «supporting actor» «supporting actor» «offstage actor»
select function(“unlock")

Similar to UML sequence diagrams, prompt for the key

but for actor interactions instead of enter key


verify key
software object interactions
signal: valid key, lock open
Typically used to visualize a use open the lock
case. turn on the light

start ("duration“)
System Sequence Diagrams
▪ Actors and System
Components – at top Use case: Unlock
▪ Lifelines – under actors and
system
▪ Activation – rectangles
▪ Actions – extend from
lifelines; usually with a
message describing the
action
▪ Solid Line – message symbol
▪ Dashed Line – return symbol
System Sequence Diagrams – More Complex
▪ Alt – if/then like behavior
▪ Loop – for/while loop behavior
System Sequence Diagram Example:
SafeHome Use Case Unlock
Alternate scenario (burglary attempt)
Main success scenario

: System
User LockDevice LightSwitch Timer
: System
«initiating actor» «supporting actor» «supporting actor» «offstage actor» User AlarmBell Police
select function(“unlock") «initiating actor» «supporting actor» «offstage actor»
select function(“unlock")
prompt for the key
loop prompt for the key
enter key
verify key
enter key
verify key

signal: valid key, lock open


signal: invalid key
open the lock prompt to try again
sound alarm
turn on the light
notify intrusion
start ("duration“)
Types of Object Responsibilities
▪ Knowing responsibility: Memorizing data values, collections,
or references to other objects, represented as attributes
▪ Doing responsibility: Performing computations, data
processing, control of physical devices, etc., represented as
methods
▪ Delegation responsibility: Delegating subtasks to object’s
dependencies, represented as sending messages (method
invocation)
Example: Safe Home
Delegation responsibilities identified for the system
function “enter security key”:
Responsibility Description
Send message to Key Checker to validate the key entered by the user.
Send message to a Device Controller to disarm the lock device.
Send message to a Device Controller to switch the light bulb on.
Send message to Photo Observer to report whether daylight is sensed.
Send message to a Device Controller to sound the alarm bell.
Assignment Responsibilities:
(Design or Module) Sequence Diagramming
First purpose of design diagrams:
Communication tool, during the creative process ➔
use hand drawings and take an image by phone
camera (don’t waste time on polishing something until you’re feel confident
that you reached a good design)

Second purposes of design diagrams: : Controller : Checker : DeviceCtrl

Specification tool for documentation ➔ use UML checkKey()

design tools to produce presentable and


professional-looking diagrams
activate( "lock" )
?

UML Sequence Diagram Conventions


Gluing the Modules (Connecting the Dots)
Starting Point: Domain Model from UC-1 (concept modules):

Symbolizes Symbolizes
“worker”-type “thing”-type
concept. concept.
«entity» «entity»
KeyChecker KeyStorage

«boundary» «entity»
KeycodeEntry Key

Use Case UC-1:Unlock (plan of action):


1. User enters the key code «boundary»
StatusDisplay
«control»
Controller LockDevice
2. System verifies that the key is valid «boundary»
HouseholdDeviceOperator

3. System signals the key validity


4. System controls: User LightSwitch

(a) LockDevice to disarm the lock


(b) LightSwitch to turn the light on
Gluing the Modules by Plan Walkthrough
Starting Points: Domain Model from UC-1 (concept modules):
Symbolizes Symbolizes
“worker”-type “thing”-type
Use Case UC-1: Unlock (plan of action): concept.
«entity»
concept.
«entity»
KeyStorage
1. User enters the key code
KeyChecker

2. System verifies that the key is valid «boundary»


KeycodeEntry
«entity»
Key
3. System signals the key validity
4. System controls: «boundary» «control»
(a) LockDevice to disarm the lock StatusDisplay Controller LockDevice
«boundary»
(b) LightSwitch to turn the light on HouseholdDeviceOperator

Scenario Walkthrough: User LightSwitch

for mapping a Use Case plan-of-action to the Domain Model


Q: who handles this data?

Interface objects and Controller


return value
Q: who performs the verification? Based on what data?

Key Checker, based on entered key-code and stored valid keys

Module Sequence Diagram


Starting Points: Domain Model from UC-1 (concept modules):
Symbolizes Symbolizes
“worker”-type “thing”-type
Use Case UC-1: Unlock (plan of action): concept.
«entity»
concept.
«entity»
KeyStorage
1. User enters the key code
KeyChecker

2. System verifies that the key is valid «boundary»


KeycodeEntry
«entity»
Key
3. System signals the key validity
4. System controls: «boundary» «control»
(a) LockDevice to disarm the lock StatusDisplay Controller LockDevice
«boundary»
(b) LightSwitch to turn the light on HouseholdDeviceOperator

Scenario Walkthrough: User LightSwitch

for mapping a Use Case plan-of-action to the Domain Model


Q: who handles this data?

Interface objects and Controller message: checkKey(k)

Mapping Q: who performs the verification? Based on what data? return value

Actions to Key Checker, based on entered key-code and stored valid keys message: ???

Modules Q: who signals? Based on what data?


Controller and Interface objects, based on key verification; because they are «boundary»
Q: who signals? Based on what data?
Controller or Key checker ???, based on key verification
(Design or
Module)
Sequence
Diagram in
Progress
Q: who performs the verification? Based on what data? return value

Key Checker, based on entered key-code and stored valid keys message: ???

Q: who signals? Based on what data?


Controller and Interface objects, based on key verification; because they are «boundary»
Q: who signals? Based on what data?
Controller or Key checker ???, based on key verification
Alternative Designs

versus

❑ Which is better?
❑ How do we evaluate the “goodness” of design?
How Data Travels:
Safe Home Example
Option A:
“expert” (Key Checker) passes the information (key validity) to another object (Controller)
which uses it to perform some work (activate the lock device)

key-code key-code is-valid activation-params

Controller Checker Controller LockCtrl

Which is better?
“expert” on key validity

Option B:
Advantage: “expert” (Key Checker) directly uses the information (key validity)
Shorter communication chain to perform some work (activate the lock device)

Drawback: key-code key-code activation-params

Extra responsibility for Checker Controller Checker LockCtrl

“expert” on key validity


Characteristics of Good Designs
❑Short communication chains between the objects

❑Balanced workload across the objects


▪ divide-and-conquer during analysis method_1() method_1()
method_2()
should divide the system into manageable modules …
method_N()

❑Low degree of connectivity (associations) among the


objects
▪ A system with “hub” modules
is more prone to failures
Coupling vs. Cohesion
Cohesion: measures the degree to which
elements work together to achieve a single
purpose
low is bad, high is good

Coupling: measures complexity between module


loose/low is good, tight/high is bad
Example: Coupling and Cohesion
public class Sensor {
// stuff
public void get (int controlFlag) {
switch (controlFlag) {
case 0:
return this.humidity;
case 1:
return this.temperature;
default:
throw new UnknownControlFlagException();
}
}

What can we say about the coupling and cohesion


regarding this class? How would we redesign this class?
Design Principles (some…more are coming)
Expert Doer Principle: module that knows should communicate information to
those that need it
❑ How to recognize a violation: If a method call passes many arguments

High Cohesion Principle: module should not take on


too many computation responsibilities
❑ How to recognize a violation: If a class has many
loosely or not-related attributes and methods
❑ Related: Single Responsibility Principle (coming up)

Low Coupling Principle: module should not delegate responsibilities in many


tiny parts
❑ How to recognize a violation: many outgoing links
❑ Better solution: Hierarchical delegation by limiting the number of dependencies for
each delegate and letting the delegates further split the complex responsibilities
Compromise is Necessary
❑Any nontrivial design is a compromise
between the desired and the possible
❑Design principles may contradict each other:
▪ Shortening the communication chain (expert
doer) tends to concentrate responsibilities to
fewer objects (low cohesion)
▪ Minimizing the number of responsibilities per object (high cohesion)
tends to increase the number of dependencies (strong coupling)
❑It is critical for others to know how the designer resolved each
compromise/tradeoff, so others can evaluate the reasoning
▪ document the reasons for choosing tradeoffs and compromises
▪ code alone cannot provide this information
▪ code shows the product but not the process of reasoning
Separation of Concerns
❑Principle in Software Design:
▪ Concern – general notion, anything that matters
regarding problem solution
▪ Concerns lead to other concerns
▪ Examples:
• What information to represent?
• What manipulates the information?
❑Key concept in OOP…leads to the idea of classes
❑Goal: create flexible, maintainable, and reusable
code
Example: Separation of Concerns
public class SmartPhone {
// stuff
public SmartPhone() { … };

public void takePhoto { … };


public void savePhoto {…};
public void cameraFlash {…};

public void makePhoneCall() {…};


public void encryptOutingSound() {…};
public void decipherIncomingSound() {…};
}

How would we redesign this class?


Responsibility Driven Design
1. Identify the responsibilities
▪ start with a use case plan-of-action
▪ some may be missed at first and identified during implementation of
the design
2. For each responsibility, identify candidate modules or objects to
assign to
3. Consider the merits and tradeoffs of each alternative by applying
the design principles
▪ select what you consider the “optimal” choice
4. Document the reasoning process by which you arrived at each
responsibility assignment
▪ design involves tradeoffs—let others know how you resolved them
▪ preserve not only the final chosen design but also all the alternatives you
considered and their perceived merits (process, instead of product only!)
Example: Assigning Responsibilities

Option A: Option B:
“expert” (Key Checker) passes the information (key validity) to “expert” (Key Checker) directly uses the information (key validity)
another object (Controller) which uses it to perform some work to perform some work (activate the lock device)
(activate the lock device)

key-code key-code activation-params key-code key-code is-valid activation-params

Controller Checker LockCtrl Controller Checker Controller LockCtrl


: Controller k : Key : Checker : KeyStorage : DeviceCtrl : PhotoObsrv : Logger

Unlock Use Case: enterKey()


«create»

Safe Home Example val := checkKey( k )


loop [for all stored keys]
sk := getNext()

(Module or Design) compare(k, sk)

Sequence Diagram logTransaction( k, val )


«destroy»

alt val == true activate( "lock" )

dl := isDaylight()

Advantages/Disadvantages? opt dl == false activate( "bulb" )

[else] numOfAttempts++

alt numOfAttempts == maxNumOfAttempts


denyMoreAttempts()

activate( "alarm" )

[else]

prompt: "try again"


Unlock Use Case: Variation 1 : Controller k : Key : Checker : KeyStorage : DeviceCtrl : PhotoObsrv : Logger

enterKey()
«create»
: Controller k : Key : Checker : KeyStorage : LockCtrl
loop [for all stored keys]
val := checkKey( k )
k := create() sk := getNext()

compare(k, sk)
checkKey(k) loop
sk := getNext()
logTransaction( k, val )
«destroy»
setValid(ok)
alt val == true activate( "lock" )
controlLock(k)
ok := isValid() dl := isDaylight()

opt ok == true
opt dl == false activate( "bulb" )
setOpen(true)

❑ Sets a Boolean attribute of the Key object: ok = true/false; [else] numOfAttempts++

❑ Business logic (IF-THEN rule) relocated from Controller to


alt numOfAttempts == maxNumOfAttempts
LockCtrl denyMoreAttempts()

❑ May be useful if Controller and LockCtrl are in different activate( "alarm" )

memory spaces and their communication could be


[else]
intercepted, so the Key should be encrypted
prompt: "try again"
: Controller k : Key : Checker : KeyStorage : DeviceCtrl : PhotoObsrv : Logger

Unlock Use Case: enterKey()


«create»

loop [for all stored keys]


Variation 2 : LightCtrl : PhotoSObs
val := checkKey( k )
sk := getNext()

compare(k, sk)

logTransaction( k, val )
controlLight() «destroy»
dl := isDaylight()
alt val == true activate( "lock" )

opt dl == false dl := isDaylight()

setLit(true) opt dl == false activate( "bulb" )

❑ Controller only sends the message to one of a group of [else] numOfAttempts++


objects associated with a device
❑ Checking whether it is dark and the light is needed should alt numOfAttempts == maxNumOfAttempts
denyMoreAttempts()
be a responsibility of LightCtrl
activate( "alarm" )
❑ Similarly, if other devices require multi-step control, the
Controller should not be involved [else]

▪ AlarmCtrl will determine the list of who needs to be prompt: "try again"

notified and send text messages


: LightCtrl : PhotoSObs
Unlock Use Case: : LightCtrl : PhotoSObs

Variation 3 checkIfDaylightAndIfNotThenSetLit()
controlLight() dl := isDaylight()
dl := isDaylight()
opt dl == false

opt dl == false
setLit(true)

setLit(true)
This solution need
separate methods to:
- Turn light ON
- Turn light OFF
❑ It may seem helpful that checkIfDaylightAndIfNotThenSetLit() is named informatively (reveals the intention) …
❑ but the low-level knowledge of operating a particular device (lighting) is encoded in the name of the method …
❑ which, in turn, means that low-level knowledge (“mechanism”) is imparted onto the caller (Controller) which
should be concerned with high-level business policies
❑ Mixing low-level knowledge with high-level knowledge results in rigid and non-reusable designs
Are we done with UC-1: Unlock?
❑Didn’t check that the user is at the right door
▪ Missing: Managing access rights
❑Didn’t distinguish critical and non-critical functions
▪ For example, what if logTransaction() call to Logger does not return, e.g., no access
to database (network outage) or disk-space full ?
▪ Missing: Independent execution of non-critical functions
❑Adding new household devices causes major design changes
❑Controller has several unrelated reasons for future changes:
▪ Business policies are entangled with authentication mechanisms
▪ Device management
❑Etc.
policy:

IF key  ValidKeys THEN disarm lock and turn lights on


ELSE
mechanism:
increment failed-attempts-counter
IF failed-attempts-counter equals maximum number allowed
THEN block further attempts and raise alarm

Example: Should be moved into a separate object:


Business ❑ Make them explicit part of the model
❑ Separate business policies from impl. Mechanism
Policy ❑ See Dependency Inversion Principle (upcoming)
Class Diagram (Based on Original)
PhotoSObsrv Key KeyStorage
1..* 1
– code_ : string
+ isDaylight() : boolean – timestamp_ : long + getNext() : Key
– doorLocation_ : string
1 sensor validKeys 1

Controller
# numOfAttemps_ : long
# maxNumOfAttempts_ : long
+ enterKey(k : Key)
– denyMoreAttempts() KeyChecker
1

checker + checkKey(k : Key) : boolean


1 devCtrl – compare(k : Key, sk : Key) : boolean

DeviceCtrl
1 logger
# devStatuses_ : Vector
Logger + activate(dev : string) : boolean
+ deactivate(dev :string) : boolean
+ logTransaction(k : Key) + getStatus(dev : string) : Object
Principles and Patterns
❑Principles are used to diagnose problems with
designs
❑Patterns are used to address the problems
Some Software Design Goals
Modular
▪ Software is logically partitioned into elements or subsystems
Independence
▪ Design should lead to components that exhibit independent functional
characteristics
Complexity Reduction
▪ Interfaces between components and the external environment should be as
simple as possible
Motivated by Requirements
▪ Design should be driven by information obtained during requirement analysis
Easy to Understand
▪ Design should be effectively communicated
SOLID Design Principles for OO
Software inevitably changes/evolves over time (maintenance, upgrade)
❑ Single responsibility principle (SRP)
▪ Every class should have only one reason to be changed
▪ If class "A" has two responsibilities, create new classes "B" and "C" to handle each responsibility
in isolation, and then compose "A" out of "B" and "C"
❑ Open/closed principle (OCP)
▪ Every class should be open for extension, but closed for modification
▪ Put the system parts that are likely to change into implementations (i.e. concrete classes) and define parts that are unlikely to change (e.g.
abstract base classes)
▪ A class should be extendable with modifying the class itself.
❑ Liskov substitution principle (LSP)
▪ objects of a superclass should be replaceable with objects of its subclasses without breaking the application (requirements determined by its
clients!)
▪ When you create derived classes, be sure they conform to pre- and postconditions
❑ Interface segregation principle (ISP)
▪ Keep interfaces (between classes) as small as possible, to avoid unnecessary dependencies
▪ Ideally, it should be possible to understand any part of the code in isolation, without needing to look up the rest of the system code
❑ Dependency inversion principle (DIP)
▪ Loosely coupling software modules in a way that high level modules should not depend on low level modules
▪ Instead of having concrete implementations communicate directly (and depend on each other), decouple them by formalizing their
communication as an abstract interface based on the needs of the higher-level class
SRP Example
Library System – Book Class
Book
Thoughts?
# author : Person
# datePublished: Date
- title : String We can easily think of two different actors here:
….
▪ Book Management (like the librarian)
+ getTitle : String
+ getAuthor: Person ▪ Data Presentation Mechanism (graphical UI, text-only
+ turnPage
+ printCurrentPage UI, maybe printing).
….

Solution: Give printing responsibility to another class (or


multiple classes)
▪ PlainTextPrinter
▪ HTMLPrinter
Open/Closed Principle Bad: DrawShapes

Example ▪ Not open to accept more shapes


▪ Requires modification to work for triangles

Thoughts? public class Circle { }

public class Square { }


public interface IShape { void Draw(); }
public static class Drawer {
public class Circle : IShape { public void Draw() { /*Draw circle*/ }}
public static void DrawShapes(IEnumerable<object> shapes) {
foreach (object shape in shapes) {
public class Square : IShape { public void Draw() { /*Draw Square*/ } }
if (shape is Circle) {
DrawCircle(shape as Circle);
public static class Drawer {
} else if (shape is Square) {
public static void DrawShapes(IEnumerable<IShape> shapes) {
DrawSquare(shape as Square);
foreach (IShape shape in shapes) {
}
shape.Draw();
}
}
}
}
private static void DrawCircle(Circle circle) { /*Draw circle*/ }
}
private static void DrawSquare(Square square) { /*Draw Square*/ }
Good: DrawShapes }
▪ open to accept shapes like triangles
▪ No need to modify the code (method is
closed)
Open/Closed Principle
This principle is used to keep stable parts of your system separate from the varying
parts.

You should consider a class as being closed to editing once it has been
• tested to be functioning properly
• all the attributes and behaviors are encapsulated
• proved to be stable within your system

The open principle is how to add more features,


• extend by inheritance
• extend using abstract classes
Liskov substitution principle (LSP)
objects of a superclass should be replaceable with objects of its subclasses
without breaking the application (requirements determined by its clients!)

Which is correct?
Subtype requirement
Let object x be of type T1 and object y be of type T2. Further,
let T2 be a subtype of T1.
Any provable property about objects of type T1 (supertype)
should be true for objects of type T2 (subtype).

Rectangle
+ width : double
+ height : double
Is the subtype requirement
+ getArea : double fulfilled?
….
LSP Example (continued) Rectangle
+ width : double
+ height : double
Subtype requirement + getArea : double
Let object x be of type T1 and object y be of type T2. Further, ….

let T2 be a subtype of T1.


Any provable property about objects of type T1 (supertype)
should be true for objects of type T2 (subtype).

Rectangle r = new Rectangle(2,2);


Rectangle r = new Square(2);
int A = r.getArea();
int w = r.getWidth();
r.setWidth(w * 2);
assertEquals(A * 2, r.getArea());
Liskov substitution principle (LSP)
objects of a superclass should be replaceable with objects of its subclasses
without breaking the application (requirements determined by its clients!)

Enforces Proper Inheritance


1) The condition used to determine if a base class should or should not invoke a method cannot
be "strengthened" by a subclass. That is, a subclass cannot add more conditions to determine
if a method should be called.
2) The condition of the program after the execution of a method cannot be "weakened" by a
subclass. This means that the subclass should cause the state of the program to be in the same
state as the base class after a method call. Subclasses are allowed to "strengthen" the
postcondition of a program. For example, if the base class sets an alarm for a specific date, the
subclass must do the same, but the result can be more precise by setting the specific hour as
well.
3) Invariant conditions that exist in the base class, must also remain invariant in the subclass.
4) Immutable characteristics of a base class must not be changed by the subclass.
Exercise: Liskov
public class Animal {
private int numberOfLegs;
private boolean hasTail;

public Animal(int legs, boolean tail) {


this.numberOfLegs = legs;
this.hasTail = tail;
};

public void walk() { … };


public void run() {…};
public void eat {…};

Give an example of a subclass that breaks LSP?


Interface Segregation Principle
A class should not be
forced to depend on
methods that it does not
use
▪ No “Dummy”
implementations of an
interface
▪ To overcome, split large
interfaces into smaller
(usually more specific)
generalizations.
Interface Segregation Principle
(ISP) Example
ISP – The interfaces need to have a specific Why is this bad?
purpose.
▪ Many client-specific interfaces are better public interface Vehicle {
than one general purpose interface void setPrice(double price);
void setColor(String color);
public interface Vehicle { void start();
void setPrice(double price); void stop();
void setColor(String color); void fly();
} }

public interface Movable { public interface Flyable {


void start(); void fly();
void stop(); }
}
Design Trade-Off
Constant Balancing Act
❑Performance
❑Convenience
❑Security
Dependency Inversion Principle
High level modules should depend on high level
generalizations and not on low level details
Dependency Inversion Principle (DIP) Goal
❑ Low-level modules are more likely to User Authenticator
change
❑ High-level modules are more likely to
remain stable: they implement the
Key Descriptor Key Validator Valid Keys Storage
business policies, which is the purpose of
the system and is unlikely to change
❑ Related to coupling – lower dependency
means you have a lower degree of coupling Key Reader File or Database

❑ measures how easy it is to change your


system
DIP
Dependency Inversion Principle (DIP)
Instead of high-level module (policy)
depending on low-level module User Authenticator

(mechanism/service/utility):
▪ High-level module defines its desired
interface for the low-level service (i.e., high-
level depends on itself-defined interface) Key Descriptor Key Validator Valid Keys Storage

▪ Lower-level module depends on (implements)


the interface defined by the high-level module
▪ Dependency inversion (from low to high,
Key Reader File or Database
instead the opposite)
Safe Home Access Policy Level
❑ Detailed statement of the problem:
▪ Read the numeric code typed-in by the
user
User Authenticator
▪ Validate the code, and
▪ Set the voltage high to disarm the lock,
turn on the light
❑ Abstract statement of the problem: Key Descriptor Key Validator Valid Keys Storage

▪ Acquire the user code


▪ Validate the code, and
▪ Enable access and assist user’s arrival Key Reader File or Database
activities
DIP Example
Low Level Dependency Issue
❑ Client classes make direct references to concrete classes
❑ changes require change multiple classes
❑ tightly coupled
DIP Example
Dependency Inversion
❑ If clients are dependent on higher-level generalizations than low level
implementations can be changed or replaced with more ease later on.
❑ This is a form of looser coupling.
❑ Client class is dependent on
expected behaviors, not
on implementation
Dependency Inversion Pattern
Package diagram
Defined by policy-package owner
Policy Package

depends-on «interface»
client : PolicyClass («uses») PolicyServiceInterface

❑ Note the dependencies from


bottom to top developer A
❑ Both Policy Class and Policy
depends-on
Service Class depend on Policy («implements»)
Mechanism Package
Service Interface
but the former uses (and defines)
the interface and the latter server : PolicyServiceClass

implements the interface

developer B
DIP Example: Smart Home
Scenario: replace numeric-
PhotoSObsrv Key KeyStorage
code based keys with – code_ : string
+ isDaylight() : boolean + getNext() : Key
magnetic card or RFID chip k
– timestamp_ : long
– doorLocation_ : string
sensor validKeys
▪ What part of the system
needs to be replaced? Controller
# numOfAttemps_ : long
▪ What is the “interface” # maxNumOfAttempts_ : long

seen by the rest of the + enterKey(k : Key)


– denyMoreAttempts() KeyChecker
system that needs to
checker + checkKey(k : Key) : boolean
remain invariant? devCtrl – compare(k : Key, sk : Key) : boolean

DeviceCtrl
reader
# devStatuses_ : Vector
KeyReader + activate(dev : string) : boolean
+ deactivate(dev :string) : boolean
+ acquireKey() : Key + getStatus(dev : string) : Object
DIP Summary
Dependency Inversion
❑ Change the referencing of concrete classes from being direct to indirect
❑ Generalization the behaviors of your concrete classes into abstract
classes and interfaces
❑ Client classes interact with your system through a generalization rather
than directly with concrete resources
❑ Put an emphasis on high level dependency over low level concrete
dependency

You might also like