Design [A&N 16 – 19, 25]. “Design” work flow (UP) “Design” WF in UP focuses on refining...
-
Upload
claude-dorsey -
Category
Documents
-
view
220 -
download
0
Transcript of Design [A&N 16 – 19, 25]. “Design” work flow (UP) “Design” WF in UP focuses on refining...
Design[A&N 16 – 19, 25]
2
“Design” work flow (UP)
• “Design” WF in UP focuses on refining the analysis models towards implementation :– refined class diagrams– refined seq. diagrams– deciding your subcomponents, interfaces, and deployment model
Inception Elaboration Construction Transition
Iteration: 1 2 3 4 5 ...
• requirement
• analysis
• design
• implementation
• test
3
Analysis vs design in UP
Product+ code : String+ name : String +price : int+ applyDiscount(discount:Float)
ProductnamepriceapplyDiscount(discount)
<<trace>>
Analysis: what are your system functionalities?
Design: how do you realize those functionalities ?Bearing in mind e.g. reusability , extensibility, implementation language.
…
…
Also, fully specify the relations …
4
Refining association aggregation
Refine “consists-of”-like association to aggregation.
Basket Itemconsists of
*
Basket Item*
Folder
contains >
*
Folder *
But aggregation should be asymmetric a composite cannot be a direct or indirect ‘part’ of itself.
f : Folder
g : Folderh : Folder
f : Folderf : Folder
5
Composition
• Or refine to a stronger kind of aggregation called composition.
• Composition is an aggregation (so it is also asymmetric), but furthermore imposes that:– parts do not exist outside its containing composite– parts cannot be shared by multiple composites
Basket Itemconsists of
*
Basket Item*
Basket Item*
6
Specifying collection properties
Basket Item*{ ordered, unique }
Ordered : there is a concept of k-th elementUnique : every element occurs just once
O, -U list u = [ 1 , 4 , 4 ] , u0 = 1 -O, -U bag u = { 1, 4, 4 } , u0 = undefined -O, U set u = { 1, 4 } , u0 = undefined O, U ordered-set u = { 1, 4 } , u0 = 1
7
Example
• Work out the details (types, associations, etc)• Work out things you need to realize “charge”• Work out sequence diagrams for “charge”.
BasketItemnameprice
*Customeremailcharge()
Currencyname
8
Example
Basket+price(c : Currency) : Amount
Item- name : String- price : Amount+ getPrice() : Amount
*
Customer- email : String# charge()
Currency- name : String
PaymentMethod# charge(a : Amount)
Amount+ amount : int+ convert(c : Currency) : Amount+ add(a : Amount) : void
1
1
1
1
1
CreditCardname : Stringnr : StringvalidUntil : String
MasterCard
VisaCard
IDEAL# login()
c : Customer b : Basket : PaymentProtocolcharge() price(c.currency)
sumcharge(sum)
ordered, non-unique
0..1
0..1
9
Delegation
Improving Customer’s cohesion, at the cost of coupling...
Customer- email : String# charge()
PaymentMethod# charge(a : Amount)
1 0..1
10
Guidelines for design class
• Complete & sufficient
• Balance cohesion and coupling …
• complete the set of attributes and operations• fully specify them• so that the class can also support its client classes to realize their responsibilities• No less, no more
Ideally, a class offers a set of strongly related responsibilities. Too much disparities make it difficult to understand the class; maybe you should split the class.
Associate a class with just enough classes to realize its responsibility. More coupling reduces extensibility and maintainability.
11
Expressing class constraints
• Informally e.g. as comments or backplane, or formally with “Object Constraint Language” (OCL) part of UML
• Ch 25 A&N, supplementary material• We only discuss it at the surface; more in the course Software
Engineering
Itemprice : intfinalPrice() : int
Discount- val : int+ getValue() : intgets *
discounts
We want to constraint them: • Price should be non-negative.• Total value of the discounts should not exceed the item’s (original) price.
[0..1]{ ordered,nonunique}
12
“Class invariant”
• We want to constraint the objects in our system; so that “at any time” their states are “legal”.
• Here, a class-inv is a formula specifying what “legal” is.• “System invariant” would be a better name; “class” simply
means that the inv is formulated from the perspective of a certain class.
• “at any time” could not mean literally that (would be unrealistic)
• No further specification from UML of what this supposed to mean
• It should mean “at any time when the system is stable” … assuming we have a concept of what “stable” is.
13
Class inv in OCL
Itemprice : int
Discount- val : int+ getValue() : intgets
{ ordered,nonunique}
discounts
Constraints: • Price should be non-negative.• Discount should be non-negative
[0..1] *
context x : Iteminv : x.price 0
context d : Discountinv : d.getValue() 0
calling an object operation in a constraint is only “safe” if the operation is side-effect free. In UML: tag it with “isQuery”.
14
Constraining related objects
Itemprice : int
Discount- orgPrice : int- val : intgets
discounts
1 *
item
context d : Discountinv : d.orgPrice = d.item.price
note the navigation!
context x : Iteminv : x.discounts forall( d | d.orgPrice = x.price)
We can also formulate it like this...
{ ordered,nonunique}
15
Collections in OCL
• Set, Bag, Sequence– Navigation gives you a set, unless you specify it using association-end
prop.
• operations on collections:– forall, exists– collect (map), select (filter)– sum, count– isEmpty, includes – ...
• Syntax, as in: S forall( x | x.atr = 0)• OCL collection-operations are all functional/non-destructive.
E.g. select returns a new collection, containing the selected objects (but it doesn’t clone the objects).
16
A bit more sophisticated example
Itemprice : int
Discount- val : int+ getValue() : intgets
{ ordered,nonunique}
discounts
Constraint : total value of the discounts should not exceed the item’s (original) price.
[0..1] *
context x : Iteminv : x.discounts.getValue()sum() x.price
context x : Iteminv : x.discounts collect( d | d.getValue())sum() x.price
17
A bit more sophisticated example
Itemprice : int
Discount- val : int+ getValue() : intgets
{ ordered,nonunique}
discounts
Constraint : the total of pct-discounts on an item above 1000 eur. should be at most 10%.
[0..1]DiscountOnPct- pct : Float*
context x : Iteminv : x.price > 1000 implies x.discounts select( d | d.oclsKindOf(DiscountOnPct)) collect( d | d.pct) sum() 10.0
18
Specifying operations
Item- price : int+ getPrice(n:int) : int
Discount- val : int+ getValue() : intgets
{ ordered,nonunique}
discounts
[0..1] *
context x : Item :: getPrice(n:int)pre : n 0post : result 0
context x : Item :: getPrice(n:int)pre : n 0post : result = n*(x.price – x.discounts.getValue()sum())
Just a partial specification:
But you can also write a specification that fully specifies the method:
19
Using operations to specify each other
Item- price : int+ getPrice(n:int) : int+ totDiscount () : int
Discount- val : int+ getValue() : intgets
discounts
0..1 *
Writing a complete specification, as in the previous example, is not trivial. If a class has enough operations, we can alternatively use them to specify each other, and still get a pretty strong specification in that way.
context x : Item :: getPrice(n : int)pre : n 0 post : result = n*(price – totDiscount())
20
Other use of OCL• In activity diagram, state machine, sequence diagram ... whenever you
need to formally express a constraint.
c : Customer b : Basket
getTotalPrice()
i : Item u : CreditCard
getPrice()totprice
charge(totprice)
reset()
{ totprice > 0 }
{ b.items isEmpty() }
opt { b.items notEmpty() }
21
Template : class with parameter
QueueManager- q : T[MaxSize]+ in(x : T)+ out() : T
T, MaxSize
CustomerQueue
ShipmentQueue
<<bind>> T Customer, MaxSize = 10
<<bind>> T ShipmentOrder, MaxSize = 3
C : CustomerQueue- q : Customer[10]+ in(x:Customer)+ out() : Customer
S : ShipmentQueue-q : ShipmentOrder[3]+ in(x:ShipmentOrder)+ out() : ShipmentOrder
Possible instance :
QueueManager- q : Item[]+ in(x : Item)+ out() : Item
CustomerQueue
ShipmentQueue
22
Nested class, to resolve naming issue
Customername
ProfilevisitCount : intbuyCount : int
x : Customername
p : Customer.ProfilevisitCount : intbuyCount : int
Only accessible from a Customer
x : Customername
p : Customer.ProfilevisitCount : intbuyCount : int
Only accessible from a Customer; furthermore an implicit link to the Customer that creates it (e.g. this allows p to access x’s properties).
Whereas this implementation is called (Java’s terminology) “inner class” :
(In Java’s term, this Profile is called static nested class)
anchor containment relation
The class Profile is considered to live in Customer’s “namespace”. So, we should refer it as Customer.Profile. So, now you can also have Product.Profile, etc.
Additionally, UML requires this to be only accessible from Customer. Java does not impose this. In Java you also have “inner” class.
23
Choice of implementation language may influence your design models...
• Does your lang. support multiple inheritance?
• Most languages doesn’t have first class association nor association class.
24
Factoring out multiple inheritance
ItemgetName()price
Song
MediagetName()play()
ItemgetName()price
Song
<<interface>>MediagetName()play()
ItemgetName()price
SongMediagetName()play()
1
ItemgetName()price
SongMediaImpl1
<<interface>>MediagetMediaName()play()
(keeping in mind that Java interface can’t have attributes)
25
Refining and reifying associations
• Refining– turning “consists of ” association to aggregation or
composition (has been discussed)– refining 1-to-many association
• Reifying = making concrete, to prepare towards implementation. A&N use this term to handle:– bidirectional– many-many– association class
26
Refining 1-to-many association
Product Supplier1*
But if your implementation language does not have collection, you may want to refine this to :
< supplies class Supplier { products : Set<Product> ...}
Can be implemented e.g. like below in Java. Java’s collection gives you support to e.g. add/remove products into/from the association:
Product1* SupplierProductsArray
Your own class, to support adding/removing products to/from association.
27
Bi-directional navigation
Product Supplier* 1
Most implementation languages has no direct support for bi-directional navigation. But, you can think that the above automatically induces :
< supplies
class Supplier { products : Set<Child> ...}
Can be implemented e.g. like this in Java:
Product Supplier* 1< supplies
1*
A&N advice you to do this reification. But it seems rather overkill.
class Product { supplier : Supplier ...}
28
Many-to-many
Product Supplier** < supplies class Supplier { products : Set<Product> ...}
Can be implemented e.g. like this in Java:
S : Supplier
T : Supplier
p : Product
q : Product
So we can have this situation in Java (which is ok) :
But we can’t attach attributes to those links…, e.g. the delivery cost a supplier charges for a product.
29
Reifying many-to-many
Product Supplier**
A&N suggest this solution (supplier-centric; for product-centric reverse the aggregation/composition direction) :
< supplies
1 1Product Supplier** SuppyRelation
S : Supplier
T : Supplier
a : SuppyRelation
b : SuppyRelation
c : SuppyRelation
p : Product
q : Product
Example of instance :
(now you can add attributes to SupplyRelation)
Some assoc. class
30
Reifying association class
SupplierProduct**
< supplies
SupplyPropertytransportCost
SupplierProduct*1
SupplyPropertytranportCost * 1
S : Supplier
T : Supplier
a : SupplyPropertytransportCost = 1000
b : SupplyPropertytransportCost = 1000
c : SupplyPropertytransportCost = 10
p : Product
q : Product
Example of instance :
31
“Component”
• UML: a component is a part of a system, that is replaceable within its environment.
• In practice people also expect that “component” is also easily replaceable.
• An attractive idea! – you can thus update a component with minimum hassle– you can replace it with another one from a different
vendor
• An object would also be a “component”, but it’s runtime environment does not usually let easy replacement.
32
“Interface”
Here: a contract on a set of public features; usually the contract is just on the signatures of these features.
“Interface” in a class diagram:
Album Song<<interface>>Mediaplay()
Player
Player Album
Lollipop notation, to emphasis the “assembly” of interface supplier and consumer.
Media
Lyric
*
0..1
<<use>>
*
33
Modeling component in UML
• Modeled with structured class, with a set of required and offered interface to the outside world.
• A structured class is a class with internal structure.
Albumtitle Song
Lyric
*
0..1
usual class diagram modeling. Notice the use of composition above, which suggests containment “structures”.
<<component>>Album
songs : Song [0..100]
lyrics : Lyric[0..100]0..1
Media
Now modeling Album as a component..
title : String
34
What make it a component…
• So, logically a component, from UML perspective, is still just an instance of class.
• But additional technology/middleware is typically needed to deploy it as a component.
• To facilitate such deployment, typically your component must be well encapsulated; and interacts to its environment only through its interface.
35
Modeling your global decomposition to subsystems
<<subsystem>>GUI
ItemManagement
<<subsystem>>Business Logic
<<subsystem>>Persistence
TransactionManagement
Data Access Management
You may want to partition your system into several subsystems. Each is to be treated as a component.
36
Not used, future backup
37
Design work flow
architectural design
“design” use case
“design” class design subsystem
architect
use caseengineer
componentengineer
analysis models
[outlined] deployment model[outlined] subsytem model
We’ll talk about subsystem and deployment model later...
38
Using operations to specify each other
Item- price : int+ getPrice(n:int) : int+ addDiscount(e : Discount)/ netPrice : int
Discount- val : int+ getValue() : intgets
discounts
[0..1] *
context x : Item :: netPricederive: x.getPrice (1)
context x : Item :: addDiscount(e : Discount)pre : ...post : x.netPrice = x.netPrice@pre - e.getValue()
39
Example
Basketprice(currency) : Amount
Item- name : String- price+ getPrice() : Amount
*
Customer- email : String# charge()
Currency- name : String
Amount+ amount : int+ convert(c : Currency) : Amount+ add(a : Amount) : void
PaymentProtocol# charge(a : Amount)
1
1
1
1
default currency
item’scurrency
1
ordered, non-unique
1. Constrain basket total value of its items does not exceed 1 million eurocent.
2. Constrain price of each item in the basket should be at least 1, in the customer’s currency.
3. Give specifications for (a) “price” (red), (b) “charge”(blue), and (c) yellow
40
• 1
• 2
• 3.a
context b : Basketinv : b.items forall ( x | x.getPrice().convert(b.owner.currency).amount 1)
context b : Basketinv : b.price(EURO) ≤ 1000000
context b : Basket :: price(c : Currency) : Amountpre : c nullpost : result.amount = b.items collect ( x | x.getPrice().convert(b.owner.currency).amount ) sum()
41
• 3b is problematic; the class offers too little of its self to facilitate specification. We can provide more properties, to enable at least partial specification. e.g :
• 3c (convert) is hard to specify; but we can specify it indirectly as we specify add:
context c : Customerpre : -post : result null implies result.amount = c.basket.price().amount
Customer- email : String# charge() : Amount
context o : Amount :: add(a : Amount)pre : a nullpost : o.amount = o.amount@pre + a.convert(o.currency).amount