Bibliographie

Software Engineering
G22.2440-001
Session 7 – Sub-Topic 4
Micro/Macro Architectures
Dr. Jean-Claude Franchitti
New York University
Computer Science Department
Courant Institute of Mathematical Sciences
1
Bibliographie
•
•
•
•
•
•
•
•
UML Distilled Fowler&Scott
UML Toolkit Eriksson&Penker
Applying UML and Patterns Larman
Design pattern GOF
System of patterns Buschman&al
Penser objet avec UML&Java Lai
Object oriented Analysis Spadounakis
UML Specification www.rational.com
2
1
Example
•
•
•
•
A die
The player throws die 10 x 2
When total is 7, player scores 10 points
At the end of the game, the score is
collected in a score map
3
Requirements Analysis
•
•
•
•
First Use Case
Identify Actors?
Identify possible Sytem use cases
External functionality !
4
2
First Use Case
• Play:
– Actor: Player
– Descr: Player rolls the dices
10 times, whenever total is
7, +10pts
Play
Player
• View High Score
View High Score
– Actor: Player
– Descr: Player looks up
highest score in read-only
mode
5
Use Case
•
•
•
•
•
Very important diagram !
A must for requirements analysis
A must to present an application !
MUST BE formally commented
Used as a reference for all remaining
modeling stages
6
3
Activity Diagram
• Looks awfully close to a flow diagram
• Identify activities based on a use case
• Identify transitions between activities
7
Activity Diagram
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
Roll
Dice
turn++
[true]
Turn<10
[false]
Update
highscore
8
4
Activity Diagram
menu
[highscore]
view
Highscore
Play
[start]
[exit]
Start
turn=0
Player
Roll
Dice
turn++
[true]
View High Score
Turn<10
[false]
Update
highscore
9
Activity Diagram
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
Roll
Dice
turn++
[true]
Turn<10
[false]
Update
highscore
10
5
Activity Diagram
• Requirements analysis or analysis phase?
• More business process than object
• Provide message calling sequence and detail
Use-cases
• Very useful for tests...
11
Analysis
• Model the real world
• Implementation independent
• Determine real world classes: first class
diagram
• Model system’s dynamics: collaboration
diagram
12
6
Collaboration Diagram
• Identify the Objects
• Identify relationships between Objects
(objects graph)
• Identify messages and message calling
sequence between objects
13
Collaboration Diagram
d1 : Die
2: r1=roll( )
game : Dice
Game
1: play( )
3: r2=roll( )
d2 : Die
Momo : Player
• Display the objects
• Display relationships
between objects
• Display message
calling sequence on
individual objects
14
7
Collaboration Diagram
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
d1 : Die
Roll
Dice
turn++
2: r1=roll( )
game : Dice
Game
1: play( )
3: r2=roll( )
[true]
Turn<10
d2 : Die
Momo : Player
[false]
Update
highscore
15
Class Diagram
• Identify classes
• Identify static and dynamic relationships
between classes
• Identify relationships’ cardinality
• Identify class attributes
• Identify methods and their parameters
16
8
Class Diagram
Player
name : String
score : int = 0;
Die
faceValue : int = 1
Rolls
(from Use Case View)
1
2
roll()
1
play()
1
Plays
Includes
1
DiceGame
1
1
Scoring
1
HighScore
17
Class Diagram
Player
d1 : Die
name : String
score : int = 0;
2: r1=roll( )
game : Dice
Game
1: play( )
Die
faceValue : int = 1
Rolls
(from Use Case View)
1
2
3: r2=roll( )
1
d2 : Die
Momo : Player
roll()
1
play()
Plays
Includes
1
DiceGame
1 1
Scoring
1
HighScore
18
9
Sequence Diagram
• Dynamic modeling (~same as collaboration)
• Focuses on message sequencing
• Identify objects, their messages, and the
message calling sequence
19
Sequence Diagram
: DiceGame
1: play( )
d1 : Die
: Player
d2 : Die
2: roll( )
3: roll( )
Activation Duration !
20
10
Sequence Diagram
d1 : Die
: DiceGame
2: r1=roll( )
game : Dice
Game
1: play( )
1: play( )
d1 : Die
: Player
d2 : Die
2: roll( )
3: r2=roll( )
3: roll( )
d2 : Die
Momo : Player
Reference!
21
Sequence Diagram
: DiceGame
: RealPlayer
1: DiceGame( )
d1 : Die
d2 : Die
: Player
2: Die( )
3: Die( )
4: start( )
5: Player(String)
The player is only created at the beginning of the game !
22
11
State Diagram
• Identify the states of an object
• Identify state transitions
23
State Diagram for a « game » object
ca ncel
/ S tart game
Ready to play
start
Player ready
e ntry: ge t player name
Quit
Cancel
play
roll dices[ turn<1 0 ]
[ turn>=10 ]
In progress
entry: turn++
24
12
State Diagram
Cancel ?
cancel
menu
[highscore]
/ Start game
Ready to play
[start]
start
[exit]
Player ready
entry: get player name
Quit
view
Highscore
Start
turn=0
Cancel
play
roll dices[ turn<10 ]
Roll
Dice
turn++
[ turn>=10 ]
In progress
entry: turn++
[true]
Turn<10
[false]
Cancel ?
Update
highscore
25
Modify Schema...
menu
[highscore]
view
Highscore
[start]
Start
turn=0
Roll
Dice
turn++
[exit]
cancel
cancel
[true]
Turn<10
[false]
Update
highscore
26
13
Modify Schemas ?
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
Roll
Dice
turn++
[true]
Turn<10
[false]
Update
highscore
27
End of Analysis ?
• Verify coverage for use-case and activity
diagrams…
• Use case « view highscores » ?
• Use case « play » partially handled
28
14
Diagram Coverage
menu
[highscore]
view
Highscore
Play
[start]
[exit]
Start
turn=0
Player
Roll
Dice
turn++
[true]
View High Score
Turn<10
[false]
Partially handled
Update
highscore
29
Not handled
Sequence Diagram
: RealPlayer
: DiceGame
1: DiceGame( )
d1 : Die
d2 : Die
: HighScore
2: Die( )
3: Die( )
4: Highscore( )
30
15
Sequence Diagram
: DiceGame
d1 : Die
: Player
d2 : Die
new : Entry
: HighScore
1: Player(String)
2: play( )
3: roll( )
4: roll( )
5: Entry(name:String,score:int)
6: add(Entry)
31
Class Diagram
<<Actor>>
Player
name : String
score : int = 0;
play()
Player()
Die
faceValue : int = 1
Rolls
1
1
2
Plays
roll()
Die()
1
1
DiceGame
Includes
DiceGame()
1
start()
1
Scoring
1
HighScore
Highscore()
1
add()
Entry
name:String : type = initval
score:int : type = initval
0..*
Entry(name:String,score:int)()
32
16
End of Analysis ?
• Coverage is « pretty » good
• Consistency across schemas is correct
• 14/20
– Dynamic model lacks detail (dynamic model for
cancel?)
– Schemas are not described in enough detail…
– Sequence diagrams for the game are not detailed
enough : a few methods are missing…
33
Design
• Take implementation into account
– Handle the GUI portion
– Handle highscores persistence
• Define a logical architecture
• Define a physical architecture
• Add technical classes allowing the
implementation of such architecture !
34
17
Architecture Design
Presentation
Application
Play
Persistence
View High Score
File or DBMS
35
Layered Architecture...
• One possible architecture, others exist (seeo
« A system of patterns » Bushcmann »)
• Layers must be as independent as possible
• « Separate » layers by relying on interfaces
+ abstract classes (design patterns)
36
18
Logical « packaging »
<<layer>>
UI
<<layer>>
Core
• Map the architecture
on « layered »
packages
• Express dependencies
<<subsystem>>
Util
<<layer>>
Persist
37
« core » Layer
• Classes representing the application logic
• In fact, these are the analysis classes which
are being revisited for realization purpose
38
19
Core « Layer »:First Diagram
Analysis
Design
HighScore
$ hs : HighScore = null
Highscore()
add()
load()
save()
Entry
name:String : type = initval
score:int : type = initval
0..*
1
Entry(name:String,score:int)()
<<Actor>>
Player
name : String 1
score : int = 0;
Rolls
2
Die
faceValue : int = 1
roll()
Die()
play()
Player()
Plays1
DiceGame
$ dg = null
1
Singleton...
1
DiceGame
DiceGame()
getInstance()
start()
2
-dies
Die
faceValue : int = 1
-player
1
roll()
Die()
display()
Includes
DiceGame() 1
start()
1
Scoring
Player
name : String
score : int = 0;
1
HighScore
Player()
display()
Highscore()
1
add()
Entry
name:String : type = initval
score:int : type = initval
0..*
Entry(name:String,score:int)()
39
Graphical Interface Layering:
MVC
Observable
(from util)
changed : boolean = false
<<Interface>>
Observer
Observable()
addObserver()
deleteObserver()
notifyObservers()
notifyObservers()
deleteObservers()
setChanged()
clearChanged()
hasChanged()
countObservers()
(from util)
0..*
update(o : Observable, arg : Object) : void
Die
(from Core)
DieView
faceValue : int = 1
Player
(from Core)
name : String
score : int = 0;
Player()
display()
DieView(die : Die)
update(o : Observable, arg : Object) : void
roll()
Die()
display()
PlayerView
PlayerView(player : Player)
update(o : Observable, arg : Object) : void
40
20
Views ?
<<Interface>>
Observer
(from util)
update(o : Observable, arg : Object) : void
DieView
DieView(die : Die)
update(o : Observable, arg : Object) : void
PlayerView
PlayerView(player : Player)
update(o : Observable, arg : Object) : void
41
Attention ...
Observable
(from util)
changed : boolean = false
<<Interface>>
Observer
Observable()
addObserver()
deleteObserver()
notifyObservers()
notifyObservers()
deleteObservers()
setChanged()
clearChanged()
hasChanged()
countObservers()
(from util)
0..*
update(o : Observable, arg : Object) : void
Panel
(from awt)
Panel()
Panel()
constructComponentName()
addNotify()
Die
(from Core)
DieView
faceValue : int = 1
Player
(from Core)
name : String
score : int = 0;
Player()
display()
DieView(die : Die)
update(o : Observable, arg : Object) : void
roll()
Die()
display()
setValue()
PlayerView
PlayerView(player : Player)
update(o : Observable, arg : Object) : void
42
21
MVC in action: 1 Setup
: RollForm
:
Playe
1: display( )
: PlayerView
: Die
: DieView
2: PlayerView(Player)
3: addObserver(Observer)
4: return component
5: display()
6: DieView(Die)
7: addObserver(Observer)
8: return component
43
MVC in action: 2 state change
: Die
: Randomizer
: DieView
1: getValue( )
2: setValue(int)
3: notifyObservers( )
4: update(Observable, Object)
44
22
MVC
• Java AWT Java: Delegation Model
– Event propagation from user interface to core
application classes
• MVC:
– State change propagation to graphical objects
45
Put the views in the « forms »
• Implement graphical interfaces containing
views as needed…
• The UI « layer » ...
46
23
UI « Layer »
Frame
(from awt)
PlayerForm
ok_action()
cancel_action()
PlayerForm()
0..1
MainForm
HighScoreForm
ok_action()
RollForm
quit_action()
start_action()
high_action()
MainForm()
roll_action()
0..1 cancel_action()
RollForm()
1
PlayerView
HighScoreView
2
PlayerView()
update()
update()
DieView
DieView()
update()
<<Interface>>
Observer
(from util)
47
update()
UI Mapping Class, UI
PlayerForm
ok_action()
cancel_action()
PlayerForm()
MainForm
RollForm
quit_action()
start_action()
high_action()
MainForm()
roll_action()
0..1 cancel_action()
RollForm()
1
PlayerView
PlayerView()
update()
2
DieView
DieView()
update()
48
24
Object Diagram: rollform
: Label
d1 : Die
View
theDieView
: Roll
Form
theDieView
d2 : Die
View
thePlayerView
momo :
PlayerView
: Label
: Label
: Label
: Panel
roll :
Button
cancel :
Button
49
: RealPlayer
: DiceGame
1: getInstance( )
: MainForm
: PlayerForm
:
Playe
: RollForm
2: MainForm( )
3: start_action( )
4: PlayerForm( )
5: ok_action( )
6: start( String playerName)
7: Player(String)
8: RollForm( )
50
25
: RollForm
:
Playe
1: display( )
: PlayerView
: Die
: DieView
2: PlayerView(Player)
3: addObserver(Observer)
4: return component
5: display()
6: DieView(Die)
7: addObserver(Observer)
8: return component
51
UI/Core Separation...
HighScore
$ hs : HighScore = null
Highscore()
add()
load()
save()
Entry
name:String : type = initval
score:int : type = initval
1
0..*
Entry(name:String,score:int)()
DiceGame
$ dg = null
<<Interface>>
Displayable
Singleton...
DiceGame()
getInstance()
start()
display()
2
-dies
Die
faceValue : int = 1
roll()
Die()
display()
setValue()
-player
1
Player
name : String
score : int = 0;
Player()
display()
52
26
Layered Architecture...
RollForm
(from UI)
Technical classes
UI
roll_action()
cancel_action()
RollForm()
DieView 2
(from UI)
UI
+thePlayerView
PlayerView
(from UI)
1
+theDieView
PlayerView()
update()
DieView()
update()
Interface and
<<Interface>>
Displayable
Observable
(from util)
Die
faceValue : int = 1
Analysis classes
(from util)
0..*
abstract classes handling decoupling
Core
<<Interface>>
Observer
roll()
Die()
display()
setValue()
Player
name : String
score : int = 0;
Player()
display()
53
Util « subsystem »
• Need for random numbers
• Use java.util « random » functionality…
• The random number generator is shared by
the die…
• Another singleton...
54
27
Subsystem « util »
Random
(from util)
$ serialVersionUID : long = 3905348978240129619L
seed : long
$ multiplier : long = 0x5DEECE66DL
$ addend : long = 0xBL
$ mask : long = (1L << 48) - 1
$ BITS_PER_BYTE : int = 8
$ BYTES_PER_INT : int = 4
nextNextGaussian : double
haveNextNextGaussian : boolean = false
Singleton
Randomizer
1
getInstance()
getValue()
Random()
Random()
setSeed()
next()
nextBytes()
nextInt()
nextInt()
nextLong()
nextBoolean()
nextFloat()
nextDouble()
nextGaussian()
55
« Util » Dynamic Model
: Player
: Die
1: roll( )
: Randomizer
: Random
2: getInstance( )
3: Randomizer( )
4: Random( )
Singleton !
5: getValue( )
6: nextInt(int)
56
28
« Persist » Layer
• Technical classes used for persistence
• Ensures Core/Persist independence
– Ability to switch « persistent engine »
• For example:
– Persistence by « Serialization »
– Persistence via a relational DBMS (JDBC)
57
Isolation : Pattern Fabrication
HighScore
(from Core)
$ hs : HighScore = null
Abstract product
Concrete product
Concrete factory
Abstract factory
Highscore()
add()
load()
save()
HighScoreSr
$ filename : String = "/tmp/high.score"
HighScoreJDBC
Highscore()
load()
save()
Highscore()
load()
save()
SrKit
JdbcKit
makeKit()
makeKit()
PersistKit
makeKit()
58
29
« Persist » Dynamic Model
: RealPlayer
: DiceGame
: S rK it
: HighScoreSr
1: SrKit( )
A ttention!
DiceGame voit S rK it comme
un P ersistKit e t HighScoreSr
comme un HighS core
2: getInstance( )
3: DiceGame( )
4: makeKit( )
5: HighScoreSr( )
6: load( )
7: quit( )
S eul le Realplayer sait qu'il
utilise un S rK it ! DiceGame
non !
8: getInstance( )
9: save( )
59
Using Serialization
• Persistence propagation...
e1 : Entry
: High
Score
e2 : Entry
e3 : Entry
e4 : Entry
60
30
A little bit of code…that’s all folks
class HighScoreSr extends HighScore implements Serializable
{
...
public void save() throws Exception {
FileOutputStream ostream = new FileOutputStream(filename);
ObjectOutputStream p = new ObjectOutputStream(ostream);
p.writeObject(this); // Write the tree to the stream.
p.flush();
ostream.close();
// close the file.
}
public void load() throws Exception {
FileInputStream istream = new FileInputStream(filename);
ObjectInputStream q = new ObjectInputStream(istream);
HighScoreSr hsr = (HighScoreSr)q.readObject();
}
}
61
JdbPersist... Dynamic Model
• A table must be created in a relational DBMS
• Upon creation of HighScoreJDBC: Connection to
DBMS via JDBC
• save:
– Perform « inserts » for each « entry »
• load:
– Select * from ...,
– Follow the result,
– create « entry » objects
62
31
A little bit of code...
public class HighScoreJDBC extends HighScore {
public static final String url="jdbc:odbc:dice";
Connection con=null;
public HighScoreJDBC() {
try {
//loads the driver
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection(url,
"molli","");
} catch (Exception e) {
e.printStackTrace();
new Error("Cannot access Database at"+url);
}
hs=this; // register unique instance !
this.load();
}
63
Jdbc Load
public void load() {
try {
Statement select=con.createStatement();
ResultSet result=select.executeQuery
("SELECT Name,Score FROM HighScore");
while (result.next()) {
this.add(new Entry(result.getString(1),
result.getInt(2)));
}
} catch (Exception e) {
e.printStackTrace();
}
}
64
32
Jdbc Save
public void save() {
try {
for (Enumeration e = this.elements() ;
e.hasMoreElements() ;) {
Entry entry=(Entry)e.nextElement();
Statement s=con.createStatement();
s.executeUpdate(
"INSERT INTO HighScore (Name,Score)"+
"VALUES('"+entry.getName()+"',"+
entry.getScore()+")");
}
} catch (Exception e) {
e.printStackTrace();
}
}
65
Component diagram...
• A component is a « non-trivial, nearly
independent, and replaceable part of a
system that fulfills a clear function in the
context of a well-defined architecture »
• A component conforms to and provides the
physical realization of a set of interfaces.
66
33
Component diagram
• « Realize » : implement interfaces
• « Depend » : Use interfaces
• Interfaces isolate components
67
Component diagram...
DiceSystem
DicePersist
Displayable
Dice
Vizualization
HighScore
Observable
PersistKit
Observer
Randomizer
Random
system
68
34
Deployment Diagrams
• Display the physical architecture
• Associer execution units to associated
handlers
• Identify connections between execution
units
69
Deployment Diagrams
JBDC
Connection
Save/load the
highscore
Game Computer
SGBD computer
Play the
game
File
System
Maybe a Remote
a file system
70
35
Design Complete ?
• Functionality coverage : compare Use-case
and activity diagrams…
• Consistency between diagrams ??
– Some inconsistencies… UI vs Core
– Core/Persist independence partially modeled...
71
Generate code : code mapping
•
•
•
•
Map into any programming language !
OO languages : java, C++, smalltalk
Or: VB, C, Fortran
As well as: SQL, Cobol...
72
36
Java Mapping...
<<Interface>>
Displayable
Observable
(from util)
display()
package Core;
import
import
import
import
Util.Randomizer;
UI.DieView;
java.util.*;
java.awt.Component;
public class Die extends Observable
implements Displayable {
private int faceValue = 1;
public int roll() {
Die
faceValue : int = 1
roll() : int
Die()
display() : java.awt.Component
setValue(value : int) : void
getValue() : int
setValue(Randomizer.getInstance().
getValue());
return getValue();
}
public java.awt.Component display()
{
Component c=new
DieView(this);
this.addObserver((Observer
)c);
return c;
}
public void setValue(int value) {
faceValue=value;
this.setChanged();
this.notifyObservers();
}
public int getValue() {
return
faceValue;}
73
}
Relationships
HighScore
(from Core)
Entry
$ hs : HighScore = null
Highscore()
add()
load()
save()
getInstance()
(from Core)
1
+schedule
name:String : type = initval
score:int : type = initval
0..*
Entry(name:String,score:int)()
package Core;
import java.util.*;
import java.awt.Component;
import UI.HighScoreView;
public abstract class HighScore
extends Observable implements
java.io.Serializable, Displayable {
protected static HighScore hs = null;
public Vector entries=new Vector();
public void add(Entry entry) {
entries.addElement(entry);
this.setChanged();
this.notifyObservers();
}
public Enumeration elements() {
return entries.elements();
}
public abstract void load();
public abstract void save();
public Component display() {
Component c=new HighScoreView(this);
this.addObserver((java.util.Observer)c);
return c;
}
public static HighScore getInstance() {
if (hs==null) {
new Error("No Persist Kit declared");
}
return hs;}
74
37
Programming...
• Use « forward engineering » functionality
provided by tools
• Then « reverse engineering »
• To achieve « round trip engineering » ;-D
• Ensure Programming/Design/Analysis
consistency...
75
Forward engineering
Die
(from Core)
Player
faceValue : int = 1
(from Core)
name : String
score : int = 0
Player()
display()
-thePlayer
+theDiceGame
DiceGame
(from Core)
$ dg = null
DiceGame()
getInstance()
start()
quit()
roll()
Die()
display()
setValue()
-dies
2
// Source file: c:/prout/Core/DiceGame.java
package Core;
public class DiceGame {
private static int dg = null;
private Die dies[];
private Player thePlayer;
DiceGame() {
}
/**
@roseuid 37F877B3027B
*/
private DiceGame() {
}
/**
@roseuid 3802F61403A0
*/
public void getInstance() {
}
/**
@roseuid 37F8781A014D
*/
public void start() {
}
/**
@roseuid 38074E7F0158
*/
public void quit() {
}
}
76
38
Forward Engineering
: RealPlayer
: DiceGame
: SrKit
package Core;
1: SrKit( )
import UI.MainForm;
import Persist.*;
import java.awt.*;
2: getInstance( )
3: DiceGame( )
4: makeKit( )
class Main {
public static void main(String args[]) {
// SrKit srk=new SrKit();
JdbcKit srk=new JdbcKit();
DiceGame dg=DiceGame.getInstance();
Frame f=MainForm.getInstance();
f.setSize(300,300);
f.show();
}
}
77
Reverse Engineering...
Observable
Vector
(from util)
(from util)
Die
faceValue : int = 1
roll()
Die()
display()
setValue()
getValue()
-dies[]
+entries
Player
score : int = 0
turn : int = 0
WIN_NUMBER : int = 7
WIN_SCORE : int = 10
Player()
die1()
die2()
-thePlayerplay()
display()
DiceGame()
getName()
getInstance()
getScore()
start()
getTurn()
getDie()
setTurn()
getPlayer()
-$dg
setScore()
Entry
score : int
Entry()
getName()
getScore()
toString()
DiceGame
HighScore
HighScore()
add()
elements()
load()
save()
display()
getInstance()
#$hs
-name -name
String
(from lang)
78
39
Reverse engineering
• Does not apply to the dynamic model !
• Handle forward+modification+reverse
issues
• Nothing miraculous !
79
Design/Implementation Comparison
O b s e rva b le
V e c to r
(from uti l)
(from util)
CORE
+ e ntrie s
D ie
fa c e V a lue : int = 1
ro ll()
D ie ()
d is p la y()
se tV a lue ()
g e tV a lue ()
H ig h S co re
H ig hS c o re ()
a d d ()
# $ hs
e le m e nts ()
lo a d ()
s a ve ()
d is p la y()
g e tInsta nce ()
-d ie s []
-the P la ye r
D ic e G a m e
D ic e G a m e ()
-$ d g
g e tIns ta nc e ()
sta rt()
g e tD ie ()
g e tP la ye r()
S tring
(from lang)
- nam e
-na m e
P la ye r
sc o re : int = 0
tur n : int = 0
W IN _N UM BE R : int = 7
W IN _S C O RE : int = 1 0
P la ye r( )
d ie1 ()
d ie2 ()
p la y( )
d isplay ()
g etN am e( )
g etS c or e( )
g etT urn( )
se tTur n()
se tS co re ()
E ntry
s co re : int
E ntry()
g e tN a m e ()
g e tS co re ()
to S tring ()
< <Inter fac e >>
D is p la ya b le
d is p la y()
80
40
UI(1)
Frame
ActionListener
(from awt)
(from event)
HighScoreForm
actionPerformed()
HighScoreForm()
-hf
closeAction()
TextField
(from awt)
-mf
RollForm
MainForm
actionPerformed()
quitAction()
+m_MainForm startAction()
highAction() +m_MainForm
MainForm()
getInstance()
-$mf
-rf
-tf
-pf
actionPerformed()
rollAction()
cancelAction()
RollForm()
PlayerForm
actionPerformed()
okAction()
cancelAction()
PlayerForm()
-close -start
-quit
+ok -high
-ok
+cancel
-cancel
Button
(from awt)
81
UI(2)
RollForm
HighScoreForm
actionPerformed()
HighScoreForm()
closeAction()
+m_HighScoreForm
-close
+cancel
+ok
Button
actionPerformed()
rollAction()
cancelAction()
RollForm()
-m_RollForm
+m_RollForm
(from awt)
+theDieView[]
-hv
+thePlayerView
PlayerView
DieView
HighScoreView
HighScoreView()
update()
DieView()
update()
-l
-scoreLabel
-nameLabel
-turnLabel
Label
PlayerView()
update()
(from awt)
-l
List
(from awt)
Observer
(from util)
82
41
Util
Random
-random
(from util)
Randomizer
-$r
getInstance()
getValue()
Randomizer()
83
Persist
Serializable
(from io)
DiceGame
Entry
(from Core)
DiceGame()
getInstance()
start()
getDie()
getPlayer()
PersistKit
-$dg
(from Core)
HighScore
score : int
(from Core)
Vector
+entries
(from util)
HighScore() #$hs
add()
elements()
load()
save()
display()
getInstance()
#$pk
PersistKit()
getInstance()
makeKit()
Entry()
getName()
getScore()
toString()
HighScoreJDBC
HighScoreJDBC()
load()
save()
HighScoreSr
JdbcKit
JdbcKit()
makeKit()
SrKit
makeKit()
SrKit()
load()
save()
HighScoreSr()
84
42
Problems Found
• Dynamic model to handle turns is not
designed properly !
• Who really tests for the end of the game ?
• Design flaw !
85
Here ! Analysis Diagram !!
: DiceGame
d1 : Die
: Player
d2 : Die
new : Entry
: HighScore
1: Player(String)
2: play( )
3: roll( )
4: roll( )
5: Entry(name:String,score:int)
6: add(Entry)
86
43
Problem !
• Not formal enough !
• This analysis diagram was not reviewed at
design time !!!
• (-4)
87
Redo !
: RollForm
: Player
: Die
: Die
1: actionPerformed(ActionEvent)
2: rollAction( )
3: getTurn( )
4: [turn<10]play( )
5: setValue(int)
6: setValue(int)
7: setTurn(int)
88
44
Finally !
89
Does it work ? Testing
• Unit testing : test each class and each
method at a time
– Class diagram
• Integration tests :
– Component diagram
• System test :
– Use Case + Activity diagram
90
45
System Test
• Ok, functionality is
there ...
• And conforms to the
description of the use
case !
• >8->
Play
Player
View High Score
91
System Test
I forgot this one !
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
Roll
Dice
turn++
[true]
Turn<10
[false]
Update
highscore
92
46
System Test
menu
[highscore]
view
Highscore
[start]
[exit]
Start
turn=0
Roll
Dice
turn++
[true]
Turn<10
[false]
• Test all possible paths
!
• Ex:
–
–
–
–
–
1/Start
2/ roll
3/ cancel
4/ highscore
5/ exit
Update
highscore
93
Problems Found
• Scenario 1 :
– start, roll*, highscore, quit : OK
• Scenario 2:
– highscore, : ko ! Bug
– Design bug:
• DiceGame creates Highscore (start)
• If Highscore before start : bug
94
47
Solution
package Core;
import UI.MainForm;
import Persist.*;
import java.awt.*;
class Main {
public static void main(String args[]) {
// SrKit srk=new SrKit();
JdbcKit srk=new JdbcKit();
DiceGame dg=DiceGame.getInstance();
Frame f=MainForm.getInstance();
f.setSize(300,300);
f.show();
}
}
95
Integration Test
DiceSystem
DicePersist
Displayable
Dice
Vizualization
HighScore
Observable
PersistKit
Observer
Randomizer
Random
system
MVC Test
96
48
Test Scenario
• Highscore, start, roll*
• If the MVC works properly, entry of a new
highscore leads to redisplaying the list
which is already opened !!
• Ok, it works…
• It is good to design well ...
97
Summary of this Application Design
• Requirements Analysis
– Use-case + description
– Activity diagram
– UI prototyping
• Analysis
– Dynamic Model : Collaboration, Sequence,
state diagrams
– Static Model : Class Diagram
98
49
Design
• Architecture design (layer)
– Package diagram, component diagram,
deployement diagram
• Technical classes used to ensure isolation :
– MVC pattern,
– Factory pattern
• Technical classes UI and persistence
– *Forms, Highscore*
99
Programming
• Simple conversion of design to Java
• For each UML model, it is possible to build
a translation towards any target language
• Use « round-trip engineering » tools
• Programming PB : Need to update the
analysis/design artifacts !!!
100
50
Feedback Problems Found at Coding !
: RollForm
: Player
: Die
1: actionPerformed(ActionEvent)
2: rollAction( )
3: getTurn( )
4: [turn<10]play( )
5: setValue(int)
6: setValue(int)
7: setTurn(int)
: Die
• « auto-critique » to find
the reason behind the
problem.
• Improve process for next
time !
• Here : analysis diagrams
have not been redone !
• A software process must
emphasize quality !
101
Testing
•
•
•
•
Functionality control : Use-case diagram
Conformance control : Activity diagram
Integration tests : Component diagram
Unit tests : not done
102
51
Paying Attention to Testing !
• Current vision is too simplistic !
• Must integrate testing as part of a quality
management process (change management)
• Regression testing, automated testing (test
suites, test generation, tools!!)
103
Conclusion for this Application
• Phase:
– Requirements analysis, analysis, design,
implementation, etc.
• For each phase:
– Put together views for the same problem
– Static, dynamic, fonctional, architectural views
104
52
Architectural
View
Functional
View
DiceSystem
DicePersist
Dice
Vizuali zation
Displayable
HighScore
Play
Observable
Player
PersistKit
Observer
View High Score
Find Beverage
[ no coffee ]
[ foundcoffee]
Put Coffee in Filter
Add Water toReservoir
[ no cola ]
[ found cola]
Get Cups
Static
View
Get Can of Cola
Put Filter inMachine
Dynamic
View
Consistency !!
Coverage !!
Randomizer
Random
system
JBDC
Connection
name:String
score:int=0; 1
^coffeePot.TurnOn
Die
faceValue:int=1
Rolls
2 roll()
SGBD computer
3: r2=roll( )
1
light goes out
d2: Die
Plays
Drink Beverage
DiceGame
: DiceGame
1 1
d1 : Die
: Player
File
S ystem
Maybe a Remote
a file system
d2 : Die
ca ncel
Scoring
1
HighScore
Play the
game
Momo: Player
Includes
1
Pour Coffee
Game Computer
1: play( )
1
play()
BrewCoffee
game: Dice
Game
Save/load the
highscore
d1: Die
2: r1=roll( )
Player
(fromUseCaseView)
Turn onMachine
1: play( )
/ S tart game
Ready to play
start
Player ready
e ntry: ge t player name
2: roll( )
3: roll( )
Quit
Cancel
play
roll dices[ turn<10 ]
[ turn>=10 ]
In progress
entry: turn++
105
Consistency/Coverage
• Use-cases/Activity Diagrams
– An activity must always be assigned to a usecase
– All use cases must be implemented in the
activity diagrams
106
53
Use-case/Activity
menu
[highscore]
Play
view
Highscore
[start]
[exit]
Start
turn=0
Player
Roll
Dice
turn++
View High Score
[true]
Turn<10
OK !
[false]
Update
highscore
107
Activity/Collaboration
• All possible paths in the activity diagrams
may be represented using collaboration
diagrams !
• Beware of over-analysis !
• Only represent the most relevant scenarios !
108
54
Activity/collaboration
menu
[highscore]
view
Highscore
[start]
1 collaboration diagram
partially handling Roll !!
[exit]
Start
turn=0
d1 : Die
Roll
Dice
turn++
2: r1=roll( )
game : Dice
Game
1: play( )
3: r2=roll( )
[true]
Turn<10
d2 : Die
Momo : Player
[false]
Update
highscore
109
Collaboration/Class diagram
• All the objects in a collaboration diagram
have a type: the class diagram Class
• All the relationships in a collaboration
diagram must exist or may be derived from
the class diagram !
• Messages exchanged are methods in the
class diagram !
110
55
Collaboration/Class Diagram
Player
d1 : Die
name : String
score : int = 0;
2: r1=roll( )
game : Dice
Game
1: play( )
Die
faceValue : int = 1
Rolls
(from Use Case View)
1
2
3: r2=roll( )
1
d2 : Die
Momo : Player
roll()
1
play()
Plays
Includes
1
DiceGame
1
1
Scoring
OK!
1
HighScore
111
Class diagram / collab / sequence
• The complete dynamic model for relations
must appear in at least one sequence or
activity diagram
• Any attribute change must be represented in
at least one activity or sequence diagram
• Object creation or destruction must appear
in at least one dynamic diagram !
112
56
Class/Sequence
KO!
Player
(from Use Case View)
Die
faceValue : int = 1
Rolls
name : String
score : int = 0; 1
2 roll()
: DiceGame
: RealPlayer
1: DiceGame()
d1: Die
d2: Die
: Player
2: Die()
1
play()
1
State Change ?
Plays
3: Die()
Includes
1
DiceGame
4: start()
5: Player(String)
1 1
Scoring
1
HighScore
Creation ?
113
Class/Sequence
• A « good » solution:
– Follow the activity diagram to generate
scenarios
– Follow the possible paths in the activity
diagram
– If the activity diagram is not covered:
• Granularity is not fine enough (it is the case here)
• Class diagram over-specified
114
57
Class/State diagram...
• For each class, ask yourself if its state
evolves with time ?
• If so, put together a state diagram…
• Every transition in the state diagram must
be verified !
115
Class/State diagram !
Where are
these
methods ??
Player
(from Use Case View)
Die
faceValue : int = 1
Rolls
name : String
score : int = 0; 1
2 roll()
1
play()
cancel
/ Start game
Ready to play
start
1
Plays
Includes
1
Player ready
entry: get player name
Quit
DiceGame
Cancel
1 1
Scoring
1
HighScore
play
roll dices[ turn<10 ]
1 Object DiceGame !
[ turn>=10 ]
Where is
this
attribute ??
In progress
entry: turn++
116
58
Class/Package/Component
diagram (Design)
• Each class must be allocated to one
package, which is itself part of the overall
architecture
• Every class must also be part of a
component that implements a set of
functionalities in that architecture !!
• Otherwise the class is not part of the
architecture !
117
Class/Package
awt
(from java)
Singleton
<<Interface>>
Randomizer
getInstance()
getValue()
Randomizer()
MVC: Observer/Observable
Random
(from util)
Random()
Random()
setSeed()
next()
nextBytes()
nextInt()
1 nextInt()
nextLong()
nextBoolean()
nextFloat()
nextDouble()
nextGaussian()
<<layer>>
UI
util
(from java)
<<subsystem>>
Util
<<layer>>
Core
for random !
Random
FUNCTION !
<<layer>>
Persist
118
59
Class/Component
DiceSystem
DicePersist
Displayable
Dice
Vizualization
HighScore
Observable
PersistKit
Observer
Singleton
<<Interface>>
Randomizer
getInstance()
getValue()
Randomizer()
Random
(from util)
Random()
Random()
setSeed()
next()
nextBytes()
nextInt()
1 nextInt()
nextLong()
nextBoolean()
nextFloat()
nextDouble()
nextGaussian()
Randomizer
Random
system
119
Component/Deployment
• Each component must be allocated to one
execution unit in the deployment diagram !
• In general, a component cannot be part of
two execution units…
• Every execution unit must have at least one
component...
120
60
Component Deployment !
DiceSystem
DicePersist
Displayable
Dice
Vizualization
HighScore
Observable
PersistKit
Observer
JBDC
Connection
OOOPPPPSS !
Save/load the
highscore
Randomizer
Game Computer
Random
system
SGBD computer
Play the
game
File
System
Maybe a Remote
a file system
121
General Conclusion on Dice
• How different is it from a « directly coded »
application ??
122
61