Professional Documents
Culture Documents
Jason Gorman
Jason Gorman
Display balance
Deposit funds
Print mini-statement
Request postal statement
Withdraw cash
Display balance
importance
Print mini-statement
Deposit funds
Withdraw cash
12 days
Print mini-statement
5 days
Deposit funds
10 days
Request cheque book
3 days
Request postal statement
2 days
© Jason Gorman 2005
11
Do Incremental Deliveries (2-3
weeks long)
Log in
Withdraw cash
Iteration #1
Display balance
importance
Print mini-statement
Iteration #2
Deposit funds
Iteration #3
Request postal statement
Walk to station
Walk to office
fro m station Buy ticket
Card Holder
system
boundary
actor name
Bank System
“communicates”
© Jason Gorman 2005
16
Relationships Between Use Cases
Make tea
<<include>>
Boil water
<<include>>
Logical Implementation
Use Cases
Process Deployment
MethodB()
result := MethodC(1)
Flow of time
Focus of control
ClassC(2) c : ClassC
methodB()
result := methodC(1)
}
}
classBs : ClassB
: ClassA classBs
classBs: :ClassB
ClassB b : ClassB
collection of ClassB
b := [i]
methodB() iteration
*[ for i = 0 to classBs.length – 1 ]
b := [i]
[b.Amount > 25] methodB()
*[ for i = 0 to classBs.length – 1 ]
b := createClassB(10)
ClassB(amount)
b : ClassB
add(b)
: ClassA
privateMethodA()
entity object
doClick()
addItemButtonMouseClicked(evt)
<<create>>
newItem : InvoiceItem
PerformClick()
addItemButtonMouseClicked(evt)
breakpoint
: InvoiceDialog
addItemButton
: JButton
invoice : Invoice
doClick()
addItemButtonMouseClicked(evt)
: JButton
Before calling
AddItem()
invoice : Invoice
: InvoiceDialog
addItemButton Effect #1 :
After calling : JButton InvoiceItem object
AddItem() created
: InvoiceItem
: Invoice items
invoice
Effect #2 :
InvoiceItem object
inserted into items collection
© Jason Gorman 2005
43
UML for Java Developers
Class Diagrams
class Account
class Account
Account
{
{
}
}
class Account
class Account
{
{
private float balance = 0;
private float balance = 0;
Account private float limit;
private float limit;
- balance : Single = 0 }
- limit : Single }
class Account
class Account
{
{
private float balance = 0;
private float balance = 0;
private float limit;
private float limit;
public void deposit(float amount)
public void deposit(float amount)
{
{
balance = balance + amount;
balance = balance + amount;
}
}
Visibility
int getDatabaseId()
int getDatabaseId()
{
{
return databaseId;
return databaseId;
}
}
}
}
Class &
return this.name;
return this.name;
}
}
Instance Scope
public static int getNumberOfPeople()
public static int getNumberOfPeople()
{
{
return numberOfPeople;
return numberOfPeople;
}
}
}
}
1 1 A
A B
b b:B
class A
class A
{
{
public B b = new B();
public B b = new B(); A a = new A();
A a = new A();
}
} B b = a.b;
B b = a.b;
class B
class B
{
{
}
}
1 1 A
A B
a b b:B
class A a:A
class A
{
{
public B b;
public B b;
public A()
public A()
{
{
b = new B(this);
b = new B(this);
}
}
}
} A a = new A();
A a = new A();
B b = a.b;
B b = a.b;
class B
class B A a1 = b.a;
A a1 = b.a;
{
{ assert a == a1;
assert a == a1;
public A a;
public A a;
public B(A a)
public B(A a)
{
{
this.a = a;
this.a = a;
}
}
}
}
© Jason Gorman 2005
51
Association names & role
defaults
Lives at
Person Address
class Person
class Person
{
{
// association: Lives at
// association: Lives at
public Address address;
public Address address;
Equivalent to
class Customer
class Customer
{
{
// accounts[1..*] : Account
// accounts[1..*] : Account
ArrayList accounts = new ArrayList();
ArrayList accounts = new ArrayList();
public Customer()
public Customer()
{
{
Account defaultAccount = new Account();
Account defaultAccount = new Account();
accounts.add(defaultAccount);
accounts.add(defaultAccount);
}
}
}
}
0..1 1..*
Computer HardwareDevice
1 1..*
ShoppingBasket OrderItem
Employee
class Person
class Person
{
{
}
}
OR
Employee Employee
interface Person
interface Person
{
{
}
}
Operations
public void deposit(float amount)
public void deposit(float amount)
{
{
balance = balance + amount;
balance = balance + amount;
}
}
public void withdraw(float amount)
public void withdraw(float amount)
{
{
Account balance = balance - amount;
balance = balance - amount;
# balance : float = 0 }
}
# limit : float = 0 }
}
+ deposit(amount : float) class SettlementAccount extends Account
class SettlementAccount extends Account
+ withdraw(amount : float) {
{
private float debt = 0;
private float debt = 0;
float availableFunds()
float availableFunds()
{
{
SettlementAccount return (balance + limit - debt);
return (balance + limit - debt);
}
-debt : float = 0 }
/ availableFunds : float = balance + limit - debt public void withdraw(float amount) throws InsufficientFundsException
public void withdraw(float amount) throws InsufficientFundsException
+ withdraw(amount : float) {
{
if (amount > this.availableFunds())
if (amount > this.availableFunds())
{
{
throw new InsufficientFundsException();
throw new InsufficientFundsException();
}
}
base.withdraw(amount);
base.withdraw(amount);
}
}
}
}
© Jason Gorman 2005
57
abstract class Account
abstract class Account
{
{
Abstract Operations }
}
B C D B C D
{abstract}
Equivalent to Mammal
Mammal
}
Account }
}
}
+ withdraw(amount : float)
InsufficientFundsException
0..* 0..*
0..* 0..1
Library ISBN Title
item
class Library
class Library
{
{
private HashMap titles = new HashMap();
private HashMap titles = new HashMap();
Classes
ArrayList rentals = new ArrayList();
}
}
class Video
class Video
{
{
Rental rental;
Rental rental;
}
}
class Rental
class Rental
{
{
Customer customer;
Customer customer;
Video video;
Video video;
0..1 0..*
Customer Video
DateT ime dateRented;
DateT ime dateRented;
}
}
class T eam
2..* class T eam
Team Person {
{
# me mbers protected Person[] members;
protected Person[] members;
}
}
class Customer
class Customer
{
0..* {
Customer private static Customer[] allInstances;
private static Customer[] allInstances;
- allInstances
}
}
Jason Gorman
}
{ status = JobApplication.SUBMITTED;
status = JobApplication.SUBMITTED; guard
} }
} accept() reject()
public void accept() / ^applicant.sendNotification(this)
{ public void accept()
{ status = JobApplication.ACCEPTED;
status = JobApplication.ACCEPTED;
applicant.sendNotification(this);
} applicant.sendNotification(this);
}
Accepted Rejected
public void Reject()
{ public void Reject()
{ status = JobApplication.REJECTED;
} status = JobApplication.REJECTED;
}
public int getStatus()
{ public int getStatus()
{ return status;
} return status;
}
}
} action
…
…
private bool active;
private bool active; Active
private Applicant applicant;
private Applicant applicant;
suspend()
public JobApplication(Applicant applicant)
public JobApplication(Applicant applicant)
{ submit() [applicant == null]
{
this.applicant = applicant;
this.applicant = applicant;
active = true;
active = true;
}
} Editing
….
….
public void suspend() submit() [applicant != null]
public void suspend()
{
{
active = false; Submitted
active = false;
}
}
public void reactivate()
{
public void reactivate()
accept()
/ ^applicant.sendNotification(this)
reject()
sub state
{
active = true;
active = true;
}
} Accepted Rejected
Jason Gorman
int i = 5
int i = 5;
int i = 5;
int j = 2;
int j = 2;
int k = i * j;
int k = i * j;
int j = 2 action
for(int n = 1; n < k + 1; n++)
for(int n = 1; n < k + 1; n++)
{
{
System.out.println("Iteration #" + n);
System.out.println("Iteration #" + n);
} int k = i * j
}
try
try
transition
{
{
int read = System.in.read(); int n = 1
int read = System.in.read();
}
}
catch(IOException e)
{
catch(IOException e)
{ [else] [n < k + 1] guard
System.err.println(e.getMessage());
}
System.err.println(e.getMessage()); condition
}
key pressed
System.err.println(e.getMessage()) event
end state
© Jason Gorman 2005
72
Concurrency, Events & Synchronisation
public class EventExample implements Runnable { public class SomeEventListenerImpl implements SomeEventListener {
thread.start() fork
[!listener.getEventDispatched()]
int i =1 System.out.println("waiting...")
[!listener.getEventDispatched()]
i++
[i < 10000]
[else]
signal sent synchronisation bar
dispatcher.fireSomeEvent()
[else]
join
© Jason Gorman 2005
74
Objects & Responsibilities in Java
public class ClassA public class ClassB
public class ClassA public class ClassB
{ {
{ {
private ClassB b = new ClassB(); private ClassC c = new ClassC();
private ClassB b = new ClassB(); private ClassC c = new ClassC();
int i =1
int j = 2
int k = i + j
int n = b.methodB(k)
int b = k * k
return c.methodC(b)
return b - 1
System.out.println(n.toString())
1 *
Customer.class
Invoice
Invoice.class
1
1..*
*
Order
DomainLay er.jar
Order.class
DomainLay er.jar
Customer.classs
DataLay er.jar
Invoice.class Order.class
Application Server
Web Server
<<RMI>>
: BusinessLay er.ear
: ProcessLay er.war
communication
channel
deployment node
© Jason Gorman 2005
80
Packages in Java & UML
package objectmonkey;
package objectmonkey;
objectmonkey
class ClassA
class ClassA
{ ClassA
{
} examples
}
package objectmonkey.examples;
package objectmonkey.examples;
class ClassB
class ClassB ClassB
{
{
b
} 0..1
}
package moreexamples;
package moreexamples;
packages
subpackage
.classpath
ClassB.java
.project
ClassA.java
stereotype
<<Http Servlet>>
SubmissionsController
{ precompile = true }
tagged value
displayAuthorDetails(authorId : int)
doGet(request : HttpRequest, response : HttpResponse)
constraint
Book
children
parents 0..2
parents
valid instance of Bill : Person
parents
*
Person
children
children
children
parents 0..2
parents
not a valid instance of Bill : Person
parents
*
Person
children
children
parents 0..2
ancestors *
Person
* children
* descendants
/family tree
parents 0..2
ancestors *
Person
Q: To what which type this constraint apply? * children
A: Person
* descendants
/family tree
context Person
context Person
inv: ancestors->excludes(self) and descendants->excludes(self)
inv: ancestors->excludes(self) and descendants->excludes(self)
Person
0..1
sex : Sex
optional constraint name spouse
marry(p : Person)
class Person
class Person
{
{
public int sex;
public int sex;
public Person spouse;
public Person spouse;
self
this.spouse = p;
this.spouse = p;
p.spouse = this;
p.spouse = this;
}
}
}
}
Account
balance : Real = 0
deposit(amount : Real)
withdraw(a mount : Real) balance before execution of operation
getBalance() : Real
byte id;
short id;
Eg, 6.7.floor() = 6
© Jason Gorman 2005
98
Operations on String Type
In OCL:
account.holder
Evaluates to a customer object who is in the role holder for that association
And:
customer.accounts
Evaluates to a collection of Account objects in the role accounts for that association
b
A B
1
a.b is allowed
class B
class B
{
{
}
}
Account
id : Integer
status : enum{active, frozen, closed}
balance : Real
nextId : Integer
Account
context Account::withdraw(amount : Real)
balance : Real
context Account::withdraw(amount : Real)
pre: amount <= balance
pre: amount <= balance
deposit(amount : Real) pre: status = AccountStatusKind.ACT IVE
pre: status = AccountStatusKind.ACT IVE
withdraw(a mount : Real) post: balance = balance@pre - amount
post: balance = balance@pre - amount
1 status
<<enumeration>>
AccountStatusKind
ACTIVE
FROZEN
CLOSED
Collections in {
{
public double balance;
public double balance;
public int id;
public int id;
Java }
}
class Customer
class Customer
{
{
Account[] accounts;
Account[] accounts;
return selected;
return selected;
}
}
}
}
© Jason Gorman 2005
106
The OCL Collection Hierarchy
Collection
Elements can be included only Elements can be included Elements can be included
once, and in no specific order more than once, in no more than once, but in a
specific order specific order
collect(expression) Collects all of the elements given by expression into a new collection
sortedBy(expression) Returns a Sequence of all the elements in the collection in the order specified (expression must
contain the < operator
account1 : Account
accounts
id = 2543
balance = 450 holder
holder accounts
account2 : Account
id = 4288
balance = 250
account1 : Account
accounts
id = 2543 tsb : Bank
balance = 450 holder
account2 : Account
customers
id = 4569
accounts
balance = 100 holder antony : Customer
holder
accounts
account4 : Account
accounts
id = 5613
account3 : Account balance = 50
id = 4288
balance = 250
holder
account
Account id Customer
0..1
1
balance : Real
id : Integer
customer.account[3435]
Or
customer.account[id = 3435]
A B
C x
C
A
y
c c
A C B
c
C
c
x
A
y
Person Organisation
accounts holder
Account Customer
* 1
balance : Real
id : Integer
holder accounts
account2 : Account
id = 4288
balance = 250
keyw ords = “”
Solutions Architect London £70,000 p.a.
3 : Results PageLink
pageNo = 3
1 1
Your search for “UML and London” returned 22 results SearchPage SearchBox
Your search for “UML and London” returned 22 results Your search for “UML and London” returned 22 results
Solutions Architect London £70,000 p.a. .NET Architect London £50,000 p.a.
Senior .NET Developer City £55,000 p.a. .NET Developer London £35,000 p.a.
ASP.NET Analyst Programmer London £55 p.h. Lead developer London £60 p.h.
Agile .NET Developer City To 70k Agile .NET Developer City To 70k
Solutions Architect London £70,000 p.a. .NET Architect London £50,000 p.a.
Senior .NET Developer City £55,000 p.a. .NET Developer London £35,000 p.a.
ASP.NET Analyst Programmer London £55 p.h. Lead developer London £60 p.h.
select()
Agile .NET Developer City To 70k Agile .NET Developer City To 70k
: SearchBox
: SearchBox
key words = “”
key words = “”
: ResultsPage : JobSummary
title = “Solutions Architect”
title = “Solutions Architect” : ResultsPage : JobSummary
location = “London” title = “Solutions Architect”
location = “London” title = “Solutions Architect”
key words = “UML and London” package
title = “Solutions
= “£70,000Architect”
p.a.“ location = “London”
package = “£70,000 p.a.“ location = “London”
resultsCount = 22 location = “London” key words = “UML and London” package
title = “.NET
= “£70,000
Architect”
p.a.“
package = “£70,000 p.a.“
pageNo = 1 package = “£70,000 p.a.“ resultsCount = 22 location = “London”
pageNo = 2 package = “£50,000 p.a.“
pageLinks[0] next
pageLinks[0]
pageLinks[1]
1 : ResultsPageLink 2 : ResultsPageLink
1 : ResultsPageLink 2 : ResultsPageLink
pageNo = 1 pageLinks[1] pageNo = 2 select()
pageNo = 1 pageNo = 2
back
pageLinks[2]
next
pageLinks[2]
3 : ResultsPageLink
3 : ResultsPageLink
pageNo = 3
pageNo = 3
: SearchBox
: SearchBox
key words = “” 2. New ResultsPage
inserted into resultsPage key words = “”
role
5. 2nd ten JobSummaries for jobs
1. New ResultsPage created containing keywords “UML and London”
with keywords = old are insrted into the the role jobSummary
ResultsPage keywords and
: ResultsPage : JobSummary
title = “Solutions Architect” results count = old count
title = “Solutions Architect” and pageNo = pageNo of : ResultsPage : JobSummary
location = “London” title = “Solutions Architect”
location = “London” selected ResultsPageLink title = “Solutions Architect”
key words = “UML and London” package
title = “Solutions
= “£70,000Architect”
p.a.“ location = “London”
package = “£70,000 p.a.“ location = “London”
resultsCount = 22 location = “London” keywords = “UML and London” package
title = “.NET
= “£70,000
Architect”
p.a.“
package = “£70,000 p.a.“
pageNo = 1 package = “£70,000 p.a.“ resultsCount = 22 location = “London”
pageNo = 2 package = “£50,000 p.a.“
search
key words
Description:
Description:
select()
showJobDetails(jobSummary)
job := f indJob(jobSummary.jobId)
JobDetailsPage(job)
: JobDetailsPage
Jason Gorman
public class Invoice implements BusinessObject public class InvoiceSerializer implements XmlSerializer
{ {
… public String toXml(BusinesObject obj)
} {
}
}
Now clients only needs to know about
BusinessObject and XmlSerializer, so you only
have to write the same code once. BusinessObject obj = dbQuery.getObject(id);
XmlSerializer serializer = SerializerFactory.getSerializer(obj.getClass());
Dependancy inversion makes code easier to
String xml = serializer.toXml(obj);
change by removing duplication of client code, so
you get to do one thing in one place only – ie, you
only need to change it in one place. A Factory is an object that creates or gets instances of concrete
classes without revealing to the client the specific type of that
object. The client only needs to know about the abstraction.
© Jason Gorman 2005
137
The Open-Closed Principle
public class Customer
{
Event though our original Customer class
was thoroughly tested and working, we have private int id;
chosen here to modify it to add support for private String name;
customers who can earn loyalty points when
// added to support loyalty card customers
they shop with us.
private int loyaltyPoints;
There is now a chance of introducing new
bugs into the Customer class, breaking any …
code that depends on it.
• If Jane asks Jim to change the Blur() method on his Effect class, and to do
this he has to make changes to many of the classes in the ImageManip
source, but no changes to any classes in other packages on which
ImageManip depends, then ImageManip has common closure
• If Jane asks Jim to change the Blur() method on the Effect class and he
doesn’t need to change any of the other classes in ImageManip then the
package does not have common closure
• If Jane asks Jim to change the Blur() method on the Effect class, and he
has to change classes in other projects on which ImageManip depends,
then the package does not have common closure
• If Jane uses the Effect class in ImageManip.jar, and this class uses code in
most of the other classes in the same assembly, then ImageManip.jar has
common reuse
• If Jane uses the Effect class in ImageManip.jar, and this class does not use
code in any of the other classes in the same assembly then ImageManip.jar
does not have common reuse
• If Jane uses the Effect class in ImageManip.jar, and this class relies on
many classes in other assemblies, then ImageManip.jar does not have
common reuse
PersistenceLayer
DomainLayer CommandLayer
AbstractDomainObject
- objectId : int DomainObject
getObjectID() : int
BankingDomain
Account
- balance : float = 0
More concrete -> less stable
+ deposit(amount : float)
+ withdraw(amount : float)
The classes and interfaces in DomainFramework are less likely to change because they are
abstractions, so that package is more stable then BankingDomain, which contains concrete classes
which will change more often. It is appropriate for BankingDomain to reference
DomainFramework, but a dependency the other way would be unwise.
© Jason Gorman 2005
151
UML for Java Developers
Design Patterns
AbstractProductA AbstractProductB
ConcreteFactory X
CreateProductA() : AbstractProductA
CreateProductB() : AbstractProductB ConcreteFactoryY
CreateProductA() : AbstractProductA
CreateProductB() : AbstractProductB
AbstractCreator
AbstractProduct
FactoryMethod() : AbstractProduct
ConcreteCreator
Client
Adaptor
ExpectedMethod()
ConcreteAdaptor Adaptee
ExpectedMethod() AdaptedMethod()
Co mponent *
children
parent
Leaf Composite
0..1
AbstractHandler
next
Client
0..1
HandleRequest(request)
ConcreteHandlerA ConcreteHandlerB
HandleRequest(request) HandleRequest(request)
Observable Observer
observers
*
AddObserver(observer) Update()
Remov eObserver(observer)
NotifyObserv ers()
ConcreteObservable ConcreteObserver
1
state observerState
subject
GetState() Update()
Functional Requirements
ISBN: 0330258648
Price: £6.99
Author’ s Summary:
ISBN: 0201325632
Price: £25.99