Professional Documents
Culture Documents
3. Support dynamic reconfiguration where parts of the software are replaced with new versions
and where backup instruments are switched into the system in the event of system failure.
COMP3297 by Leo Yeung L6 – Design and Implementation 7
Step 1 - System context and interactions
Control
1 system 1
1 1..n
Weather 1 1..n Weather
information station
system
1 1..n
Satellite 1
1
² You identify the major components that make up the system and their
interactions, and then may organize the components using an
architectural pattern such as a layered or client-server model.
² The weather station is composed
of independent subsystems
that communicate by
broadcasting messages on a
common infrastructure.
«subsystem» «subsystem» «subsystem»
Listener Fault manager Configuration manager Power manager Data collection
model
Transmitter Receiver
Communication link
WeatherData
«subsystem» «subsystem» «subsystem»
Communications Data collection Instruments
Report status
Weather
information
system
Restart
Tips
Shutdown
1. Match use case
model
Reconfigure
2. Show what kinds
Control
system Powersave
of data included
Remote
control Application domain objects that are ‘hardware’ objects 3. Use meaningful
related to the instruments in the system. names
COMP3297 by Leo Yeung L6 – Design and Implementation 13
Step 4 - Design models
request (report)
acknowledge
reportWeather ()
send (report)
acknowledge
reply (report)
acknowledge
«interface»
«interface» Remote Control
Reporting
startInstrument(instrument): iStatus
weatherReport (WS-Ident): Wreport stopInstrument (instrument): iStatus
statusReport (WS-Ident): Sreport collectData (instrument): iStatus
provideData (instrument ): string
(Ref: Chapter 8-12 - Agile Software Development, Principles, Patterns, and Practices, PNIE, 1st Edition, by Martin, Robert C.,
published by Pearson, 2013)
Clean Code
² BAD: ² Problems:
§ Two responsibilities:
interface Modem {
public void dial(String pno); • Connection Management
public void hangup(); • Data Communication
public void send(char c);
public char recv();
} à Smell of Rigidity
² GOOD:
§ Separate into two interfaces
interface DataChannel {
public void send(char c);
public char recv();
}
interface Connection {
public void dial(String pno);
public void hangup();
}
Caution!
If the application is not changing in ways that cause two responsibilities, no
need to separate them. Otherwise, Smell of Needless Complexity
² GOOD:
§ Open for extension: Payment
??
subtype of T.”
?
Subtypes Must Be Substitutable For Their Base Types.
² BAD: ² Problems:
class Bird { Eagle Penguin § Penguin can’t fly.
let name: String
let flySpeed: Double § Doesn’t the IS-A
init(name: String, flySpeed: Double) {
self.name = name relationship hold?
self.flySpeed = flySpeed
}
}
class Eagle: Bird { }
class Penguin: Bird {
let swimSpeed: Double
init(name: String, flySpeed: Double, swimSpeed: Double) {
self.swimSpeed = swimSpeed
super.init(name: name, flySpeed: flySpeed)
}
}
let eagle = Eagle(name: "Eagle", flySpeed: 25)
// let penguin = Penguin(name: "Penguin",
// flySpeed: "can’t fly", swimSpeed: 10)
COMP3297 by Leo Yeung L6 – Design and Implementation 29
Examples (updated)
<<interface>> <<interface>>
CanFly Bird CanSwim
² GOOD:
Eagle Penguin
² BAD: ² Problems:
interface Worker { § RobotWorker does not
void work();
void eat(); eat
}
ManWorker implements Worker { à Smell of Needless
void work() {…}; Complexity
void eat() {30 min break;};
} § Worker is a Polluted
RobotWorker implements Worker { Interface
void work() {…};
void eat() {//Not Appliciable
for a RobotWorker};
}
interface Workable {
void work(); ManWorker RobotWorker
}
interface Feedable {
void eat();
}
ManWorker implements Workable, Feedable {
void work() {…};
void eat() {30 min break;};
}
RobotWorker implements Workable {
void work() {…};
}
² BAD:
class FilesystemStorage { DataHandler
func save(_ data: Data) ‹
// Create file->Save data locally
print("Saving locally")
}
} FilesystemStorage
class DataHandler {
let storage = FilesystemStorage()
func handle(_ data: Data) {
storage.save(data)
}
}
let handler = DataHandler()
handler.handle(Data())
² Problems:
§ DataHandler depends on FilesystemStorage. Dependency is
transitive. DataHandler is sensitive to changes all the way down.
COMP3297 by Leo Yeung L6 – Design and Implementation 35
(updated)
DataHandler
Examples
<<interface>>
² GOOD: Storage
protocol Storage {
func save(_ data: Data) Filesystem Cloud
} Storage Storage
class CloudStorage: Storage {
func save(_ data: Data) {
// Connect to cloud > Save in cloud
print("Saving in cloud")
} class DataHandler {
} let storage: Storage
class FilesystemStorage: Storage { init(storage: Storage){
func save(_ data: Data) { self.storage = storage
// Create file > Save data locally }
print("Saving locally") func handle(_ data: Data){
} storage.save(data)
} }
}
let storage = CloudStorage()
let handler = DataHandler(storage: storage)
handler.handle(Data())
COMP3297 by Leo Yeung L6 – Design and Implementation 36
Dependency Inversion Principle (DIP)
² Inversion of ownership:
38
Summary for SOLID