Transcript Slide 1
Software Engineering,
CPSC-4360-01, CPSC-5360-01,
Lecture 9
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
1
Review of Last Lecture
Design Patterns:
Abstraction-Occurrence
General-Hierarchy
Composite
Façade
Player-Role
State
Singleton
Observer
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
2
Overview of This Lecture
Basic Implementation Steps.
Implementing Classes:
Class Association:
7/16/2015
Navigation direction;
Multiplicity constraint;
Qualified associations;
Association classes.
CPSC-4360-01, CPSC-5360-01, Lecture 9
3
Where are we now?
Requirement
Analysis
Design
Implement
Translate Design into
Code
Test
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
4
Implementation: Overview
Inputs:
Activities:
Detailed Class Diagram;
Interaction Diagram;
Statechart.
Implementation of class diagram;
Reminder:
7/16/2015
Interaction diagrams show the basic behavior of some of the
operations.
A statechart describes a complete lifetime for classes with
complex behavior (next lecture – statecharts implementation).
CPSC-4360-01, CPSC-5360-01, Lecture 9
5
Basic Steps in Implementation
Define method interface:
Decide the order of implementation:
Give a formal/informal description of the
functionality of an operation;
Useful in reducing misunderstanding;
Allows splitting the workload.
Which class/subsystem to start.
Implement the design using a suitable
programming language.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
6
Defining Method Interface
During design:
However, the functionality is not formally defined:
Detailed information about the method header are defined:
Returned Type, Parameter Type;
Accessibility.
What should the method do?
What are acceptable values for the parameter?
Etc…
Even more important for complicated operations.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
7
Operation Contract
Writing the operation contract is one possible way to
define the functionality.
Define the precondition:
Express the constraint regarding the attributes of the class
and the actual parameter.
Define the postcondition:
Express the effect of an operation:
Instance Creation/Deletion;
Attribute Modification;
Association Formed/Broken.
Description can scale in formality.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
8
Operation withdraw()Contract: Example
BankAccount
-balance
+deposit( amt : float )
+withdraw( amt: float )
Precondition:
- amt > 0
- amt <= balance
Postcondition:
- New balance = Old balance - amt
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
9
Order of Implementation
Many classes with dependencies in the design:
Need an order of implementation.
Two basic strategies:
Top-Down:
Bottom-Up:
7/16/2015
Starts with high-level components.
Then continue to implement the dependent components.
Starts with the lower level classes, i.e., classes with least
dependency.
Then proceed to code classes that make use of the
implemented classes.
CPSC-4360-01, CPSC-5360-01, Lecture 9
10
Example
myB
A
methodA()
B
methodB()
{
myB.methodB();
}
A
B
A depends on B, i.e., A makes use of B
may be an attribute in class A of class B;
The navigability is one possible indicator of the dependency.
myB
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
11
Top Down Implementation
Starts with Class A, then Class B.
Advantages:
Class A represents a higher level component as it makes use
of other classes.
Starting with high level components enables early validation
of the overall system.
Disadvantages:
7/16/2015
Need temporary implementation (known as stub) for lower
classes.
Example:
A temporary implementation of methodB() is needed for
the implementation of methodA().
CPSC-4360-01, CPSC-5360-01, Lecture 9
12
Bottom Up Implementation
Starts with Class B, then Class A.
Advantages:
Low level classes can usually stand alone.
No need for stub.
Disadvantages:
7/16/2015
Have to postpone the generation of a complete
executable program.
CPSC-4360-01, CPSC-5360-01, Lecture 9
13
Class Diagram
Implementation
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
14
Implementing Classes
Basic mapping:
A UML Class is implemented by a class in Java,
C++, etc;
Attributes are implemented by fields;
Operations are implemented by methods.
There may be some language specific issues:
7/16/2015
E.g., the implementation of abstract classes,
interfaces, and generalization.
CPSC-4360-01, CPSC-5360-01, Lecture 9
15
Example: The Booking Class
public abstract class Booking {
protected int covers;
protected Date date;
#
#
+
+
+
protected Booking(int c, Date d) {
covers = c;
date = d;
}
public void setCovers(int c) {
covers = c;
}
public Date getDate() { return date; }
public void setArrivalTime(Time t) { }
}
The getCovers(c:Integer) operation should be setCovers(c:Integer).
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
16
Example: Generalization
public class WalkIn
extends Booking {
public WalkIn(...) { ... }
}
public class Reservation
extends Booking {
Time arrivalTime ;
public Reservation(...) { ... }
public void setArrivalTime(Time t) {
arrivalTime = t ;
}
}
The setArrivalTime() operation should be setArrivalTime(Time t).
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
17
Implementing Associations
Associations (Class Diagram) describe properties of links
(Object Diagram).
Guarantor
:Account
:Guarantor
A link gives one object access to another and enables message
passing.
Java: References (C++: Object Pointer) share these properties, so
associations can be implemented with references.
References support only one direction of navigation.
Account
Should restrict navigability to make implementation easier.
References should not be manipulated explicitly by other classes.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
18
Optional Unidirectional Association
Distinction between associations:
Reference variables can hold:
direction;
multiplicity.
a reference to another object;
or the null reference.
So the ‘default’ multiplicity of a reference is ‘0..1’.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
19
Implementation
The association is defined by a field in the
Account Java class holding a reference to an
instance of the DebitCard Java class:
public class Account
{
private DebitCard theCard ;
...
}
Account
7/16/2015
0..1
DebitCard
CPSC-4360-01, CPSC-5360-01, Lecture 9
Good match for
simple object
reference.
20
Maintaining the Association
As only Account is “aware” of this association, it
should also maintain the association:
Setup/Removal of the link;
Appropriate methods for accessing the linked object.
e.g.
public DebitCard getCard(){
return theCard;
}
public void setCard(DebitCard card){
theCard = card;
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
Return the
linked object
to outsider
Changing the
linked object
21
Mutability for Association
The last example assumes that the DebitCard
association is mutable:
An Account object can be linked to a different
DebitCard object during its lifetime.
Hence, it makes sense to have the following methods
for setup/removal the link:
public void setCard(DebitCard card){
theCard = card;
}
public void removeCard( ) {
theCard = null;
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
22
Immutable Association
Some associations are immutable:
once assigned, a link must not be altered.
The designer can state this in the class diagram:
{Immutable}
The programmer has to check the link’s existence
explicitly:
public void setCard(DebitCard card) {
if (theCard != null) {
// throw ImmutableAssociationException
}
theCard = card ;
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
Explicit Check
to maintain
Immutable link
23
Compulsory Association
Multiplicity with lowerbound larger than 0 is compulsory,
i.e., “At all times, the link(s) cannot be null”.
Example:
The above means “An Account object must have exactly
one link to a Guarantor object at all times”.
Programmers have to check explicitly to ensure this is true.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
24
Implementation
The earliest possible opportunity to setup the link
is in the constructor method:
public Account(Guarantor g) {
if (g == null) {
// throw NullLinkError
}
theGuarantor = g ;
}
Make sure we
have a
guarantor
If the association is mutable, similar checks must be
performed in methods that changes the link, e.g.:
public setGuarantor(Guarantor g) {
if (g == null) {
// throw NullLinkError
}
theGuarantor = g ;
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
Make sure we
have a
guarantor
25
1-to-Many Unidirectional Association
Some associations require more than one link to
be stored:
Data structures, such as arrays and vectors, can be used to
store the references.
For a specific upper bound, e.g., “0…8”, specific checks must be
implemented:
public class Manager {
private Vector theAccounts ;
public void addAccount(Account acc) {
theAccounts.addElement(acc) ;
}
Stores *
Accounts
references.
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
26
Bidirectional Association
Some associations need to be navigated in both
directions:
because references are unidirectional, it will take two
references to implement a bidirectional link;
the association can be implemented by including a
suitable field in each of the associated classes.
Account
Account
theCard: DebitCard
7/16/2015
DebitCard
theCard
theAccount
Bidirectional Association
stated in Class Diagram
DebitCard
theAccount: Account
CPSC-4360-01, CPSC-5360-01, Lecture 9
Closest
implementation of
the Class Diagram
in Java or C++
27
Bidirectional Association Implementation
DebitCard is optional (“0..1” from Account).
Account is compulsory (“1” from DebitCard).
Hence, the best way to satisfy the conditions is:
Create the Account first, then the DebitCard:
{
Account acc1 = new Account() ;
DebitCard aCard = new DebitCard(acc1) ;
acc1.setCard(aCard) ;
}
Question: Why is that the order of associations creation to satisfy the conditions?
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
28
Referential Integrity
The bidirectional association is implemented as two
separate references, it is important to keep them consistent.
The links should be “inversed” one to each other.
Known as referential integrity.
Example of referential integrity violation:
Account acc1 = new Account() ;
Account acc2 = new Account() ;
DebitCard aCard = new DebitCard(acc1);
acc2.setCard(aCard) ;
acc2: Account
acc1: Account
7/16/2015
theCard
aCard: DebitCard
theAccount
CPSC-4360-01, CPSC-5360-01, Lecture 9
The two links do not
correspond to a
valid bidirectional
association!
29
Maintaining Referential Integrity
The problem with the example code on slide 29:
creation and reference setup (setCard() method)
are two separate operations.
Responsibility of programmer to make sure the two
operations are performed in a consistent fashion.
DebitCard
To minimize the human error, delegate one of the classes
to maintain the referential integrity instead.
Example:
public class Account {
private DebitCard theCard ;
public void addCard() {
theCard = new DebitCard(this);
}
// other methods as well
Account class
handles both the
DebitCard creation
and reference setting.
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
30
Joint Creation of Objects
Suppose an association is intended to be immutable
and also needs to be traversed in both directions.
Constructors of both classes should take in an
instance of the other to satisfy the constraint
specified by the class diagram.
7/16/2015
Java and C++ do not allow simultaneous object creation.
Must create one of the objects with the default constructor,
i.e., to violate the constraint for a short time.
CPSC-4360-01, CPSC-5360-01, Lecture 9
31
Code Example
Attempts to satisfy the compulsory link:
Account a = new Account(g) ;
Guarantor g = new Guarantor(a) ;
g is not
initialized.
Account a = new Account(new Guarantor(a)) ;
Guarantor g = a.getGuarantor( ) ;
a is not
initialized.
Have to violate the constraint for a while:
Guarantor g = new Guarantor( ) ;
Account a = new Account(g) ;
Setup the reference
after Account a is
properly initialized.
g.setAccount(a) ;
7/16/2015
g is initialized by
default constructor, no
Account reference.
CPSC-4360-01, CPSC-5360-01, Lecture 9
32
Implementing Bidirectional Association
Domain Model
myG
Account
myG: Guarantor
Guarantor
myA
getMyG( ): Guarantor
setMyG( Guarantor )
myA: Account
getMyA ( ): Account
setMyA ( Account )
Some likely
methods
Class Diagram
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
33
Maintaining Bidirectional Association
Methods that change the reference should maintain
referential integrity.
Take setMyG() for example:
Have to set the reversed link too.
If Account has already a Guarantor:
Either do not allow the link change.
OR, remove the link with previous Guarantor.
a :Account
oldG: Guarantor
newG: Guarantor
The Reverse link
has to be
removed too.
a.setMyG(newG)
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
34
Code Example
//Class Account
public void setMyG(Guarantor newG) {
if (newG == null)
//throw NullLinkError
if (myG != null && myG != newG) {
//previous Guarantor exists
myG.removeMyA(this);
}
//Class Guarantor
void removeMyA(Account a) {
if (myG == newG)
return;
//only allows holder of
//the reverse link call
//this method
myG = newG;
//set the reverse link
myG.setMyA(this);
}
7/16/2015
if (a == myA)
myA = null;
}
CPSC-4360-01, CPSC-5360-01, Lecture 9
35
Code Example (Cont)
//Class Guarantor
public void setMyA(Account newA) {
if (newA == null)
//throw NullLinkError
if (myA != null && myA != newA) {
//previous Guarantor exists
myA.RemoveMyG(this);
}
//Class Account
void RemoveMyG(Guarantor g) {
if (myA == newA)
return;
//only allows holder of
//the reverse link call
//this method
myA = newA;
//set the reverse link
myA.setMyG(this);
}
7/16/2015
if (g == myG)
myG = null;
}
CPSC-4360-01, CPSC-5360-01, Lecture 9
36
Observations
Even with the complicated code, there are still some
problems:
The old guarantor will be without an Account object.
Mutual recursive functions:
setMyA calls setMyG, which calls setMyA.
Very easy to get into infinite loop.
Should avoid compulsory bidirectional association if
possible.
If bidirectional association must be used,
immutability is recommended to curb the coding
complexity.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
37
One-to-Many Association
Raise no new issues:
Customer holds a collection of references.
Account holds a non-null reference.
is a better choice as the “maintainer”
for the referential integrity:
Customer
7/16/2015
It provides a method like addAccount() that
creates a new account and setup the reference.
Similar to the addCard() method on slide 30.
CPSC-4360-01, CPSC-5360-01, Lecture 9
38
Many-to-Many Association
Previously discussed implementation techniques
can be used.
Recommendation:
7/16/2015
Allows only one of the classes to modify the links.
E.g., It makes sense to allow only the Customer to change
links to Accounts and maintain the reversed link also.
Simplify the implementation as the coding logic can be
considered from one direction only.
CPSC-4360-01, CPSC-5360-01, Lecture 9
39
Many-to-Many Association
Another implementation technique is to reify the association:
The new class (e.g., Signatory in the example above) is in a
good position to maintain referential integrity.
:Account
7/16/2015
:Signatory
CPSC-4360-01, CPSC-5360-01, Lecture 9
:Customer
40
Qualified Association
The purpose of a qualifier is often to provide efficient
access to linked objects:
7/16/2015
For example, to access accounts given only the account
number;
Also to avoid a linear search through all accounts.
CPSC-4360-01, CPSC-5360-01, Lecture 9
41
Implementing Qualifier
The run-time structure involves some kind of index
to accounts:
Using
accno as
index.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
42
Code Example
Hash Table is a good choice to implement the index:
public class Bank{
private HashTable theAccounts;
public void addAccount (Account a) {
theAccounts.put(new Integer(a.getNumber()), a);
}
put (Object Key, Object Value)
public void removeAccount(int number) {
theAccounts.remove(new Integer(number));
}
}
public Account lookupAccount(int number) {
return
(Account) theAccounts.get(new Integer(number));
}
get(Object Key): Object
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
43
Hash table - reminder
It means a data structure that associates keys with
values.
The primary operation it supports efficiently is a
lookup: given a key (e.g., a person's name), find the
corresponding value (e.g., that person's telephone
number).
It works by transforming the key using a hash
function into a hash, a number that is used to index
into an array to locate the desired location ("bucket")
where the values should be.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
44
Hash table - reminder
Like arrays, hash tables provide constant-time O(1)
lookup on average, regardless of the number of items
in the table.
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
45
Association Class
Common strategy:
7/16/2015
Transform the association class into a simple class;
replacing it by two associations.
CPSC-4360-01, CPSC-5360-01, Lecture 9
46
Implementing Association Class
*
Module
Student
Module
Student
1
Registration
*
Mark: Integer
Class
Diagram
Registration
Mark: Integer
Class
Diagram
:Module
:Student
:Module
:Student
:Registration
:Registration
Mark = 76
Mark = 76
:Student
:Student
:Registration
:Registration
Object
Diagram
7/16/2015
Mark = 89
Object
Diagram
CPSC-4360-01, CPSC-5360-01, Lecture 9
Mark = 89
47
Code Example
public class Module {
private Vector registrations;
public void enrol(Student st) {
registrations.addElement( new Registration(st) );
}
...
Maintain the link
Pass the
}
to Registration
Student to
Registration.
class Registration {
private Student student;
private int mark;
Registration(Student st) {
student = st; mark = 0;
}
...
}
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
Registration
keeps track of
the Student
reference.
48
Where are we now?
Requirement
Analysis
Design
Implement
Class diagram implementation
Test
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
49
Summary
Basic Implementation Steps
Implementing Class:
Class Association:
7/16/2015
Navigation direction
Multiplicity constraint
Qualified associations
Association classes
CPSC-4360-01, CPSC-5360-01, Lecture 9
50
Reading Suggestions
Chapter 13 of [Priestley; 2004]
Chapter 8 of [Bimlesh, Andrei, Soo; 2007]
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
51
Coming up next
Chapter 8 of [Bimlesh, Andrei, Soo; 2007]
Chapter 13 of [Priestley; 2004]
Chapters 8 and 12 of [Budd; 2000] “Understanding Object-Oriented Programming
with Java (Updated Edition)”, Addison-Wesley
Chapters 6 and 7 of [Eckel; 2000] - “Thinking in
Java “, 3rd Ed, http://www.mindview.net/Books
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
52
Thank you for your attention!
Questions?
7/16/2015
CPSC-4360-01, CPSC-5360-01, Lecture 9
53