1 / 41

Design [A&N 16 – 19, 25]

Design [A&N 16 – 19, 25]. “Design” work flow (UP). Inception. Elaboration. Construction. Transition. “Design” WF in UP focuses on refining the analysis models towards implementation : refined class diagrams refined seq. diagrams

dante
Télécharger la présentation

Design [A&N 16 – 19, 25]

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Design[A&N 16 – 19, 25]

  2. “Design” work flow (UP) Inception Elaboration Construction Transition • “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 • requirement • analysis • design • implementation • test Iteration: 1 2 3 4 5 ...

  3. Analysis vs design in UP Design: how do you realize those functionalities ? Bearing in mind e.g. reusability , extensibility, implementation language. … Analysis: what are your system functionalities? … Product + code : String + name : String +price : int + applyDiscount(discount:Float) Product name price applyDiscount(discount) <<trace>> Also, fully specify the relations …

  4. Refining association  aggregation Refine “consists-of”-like association to aggregation. consists of Basket Item * Basket Item * * Folder f : Folder contains > * f : Folder g : Folder Folder f : Folder h : Folder But aggregation should be asymmetric a composite cannot be a direct or indirect ‘part’ of itself.

  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 consists of Basket Item * Basket Item * Basket Item *

  6. Specifying collection properties * { ordered, unique } Basket Item Ordered : there is a concept of k-th element Unique : 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 Currency name • Work out the details (types, associations, etc) • Work out things you need to realize “charge” • Work out sequence diagrams for “charge”. Customer email charge() Item name price * Basket

  8. Amount + amount : int + convert(c : Currency) : Amount + add(a : Amount) : void Example 1 Customer - email : String # charge() 0..1 1 1 PaymentMethod # charge(a : Amount) • Currency • name : String 1 0..1 CreditCard name : String nr : String validUntil : String 1 Item - name : String - price : Amount + getPrice() : Amount * Basket +price(c : Currency) : Amount ordered, non-unique IDEAL # login() MasterCard VisaCard : PaymentProtocol b : Basket c : Customer charge() price(c.currency) sum charge(sum)

  9. Delegation Customer - email : String # charge() 0..1 1 PaymentMethod # charge(a : Amount) Improving Customer’s cohesion, at the cost of coupling...

  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 Discount - val : int + getValue() : int Item price : int finalPrice() : int discounts [0..1] * gets { ordered, nonunique} • We want to constraint them: • Price should be non-negative. • Total value of the discounts should not exceed the item’s (original) price.

  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 Discount - val : int + getValue() : int discounts Item price : int [0..1] gets * { ordered, nonunique} • Constraints: • Price should be non-negative. • Discount should be non-negative context x : Item inv : x.price 0 context d : Discount inv : 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 Discount - orgPrice : int - val : int discounts item Item price : int 1 gets * { ordered, nonunique} context d : Discount inv : d.orgPrice = d.item.price note the navigation! We can also formulate it like this... context x : Item inv : x.discounts forall( d | d.orgPrice = x.price)

  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 Discount - val : int + getValue() : int discounts Item price : int [0..1] gets * { ordered, nonunique} Constraint : total value of the discounts should not exceed the item’s (original) price. context x : Item inv : x.discounts  collect( d | d.getValue())sum()  x.price context x : Item inv : x.discounts.getValue()sum()  x.price

  17. A bit more sophisticated example Discount - val : int + getValue() : int discounts Item price : int DiscountOnPct - pct : Float [0..1] gets * { ordered, nonunique} Constraint : the total of pct-discounts on an item above 1000 eur. should be at most 10%. context x : Item inv : x.price> 1000 impliesx.discounts  select( d | d.oclsKindOf(DiscountOnPct))  collect( d | d.pct) sum()  10.0

  18. Specifying operations Discount - val : int + getValue() : int Item - price : int + getPrice(n:int) : int discounts [0..1] gets * { ordered, nonunique} Just a partial specification: context x : Item :: getPrice(n:int) pre : n  0 post : result  0 But you can also write a specification that fully specifies the method: context x : Item :: getPrice(n:int) pre : n  0 post : result = n*(x.price – x.discounts.getValue()sum())

  19. Using operations to specify each other 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. Item - price : int + getPrice(n:int) : int + totDiscount () : int Discount - val : int + getValue() : int discounts gets 0..1 * 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. b : Basket u : CreditCard i : Item c : Customer opt { b.items notEmpty() } getTotalPrice() getPrice() totprice { totprice > 0 } charge(totprice) reset() { b.items isEmpty() }

  21. Template : class with parameter QueueManager - q : Item[] + in(x : Item) + out() : Item CustomerQueue ShipmentQueue T, MaxSize QueueManager - q : T[MaxSize] + in(x : T) + out() : T <<bind>> T  Customer, MaxSize = 10 CustomerQueue <<bind>> T  ShipmentOrder, MaxSize = 3 ShipmentQueue C : CustomerQueue - q : Customer[10] + in(x:Customer) + out() : Customer • S : ShipmentQueue • q : ShipmentOrder[3] • + in(x:ShipmentOrder) • + out() : ShipmentOrder Possible instance :

  22. Nested class, to resolve naming issue containment relation anchor 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. Profile visitCount : int buyCount : int Customer name p : Customer.Profile visitCount : int buyCount : int x : Customer name Only accessible from a Customer (In Java’s term, this Profile is called static nested class) Whereas this implementation is called (Java’s terminology) “inner class” : p : Customer.Profile visitCount : int buyCount : int x : Customer name 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).

  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 Media getName() play() Item getName() price <<interface>> Media getName() play() Item getName() price Song (keeping in mind that Java interface can’t have attributes) Song <<interface>> Media getMediaName() play() Item getName() price Item getName() price Media getName() play() 1 1 Song MediaImpl Song

  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 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: 1 < supplies * Supplier Product class Supplier { products : Set<Product> ... } But if your implementation language does not have collection, you may want to refine this to : 1 * ProductsArray Supplier Product Your own class, to support adding/removing products to/from association.

  27. Bi-directional navigation 1 * < supplies Product Supplier Most implementation languages has no direct support for bi-directional navigation. But, you can think that the above automatically induces : 1 * < supplies A&N advice you to do this reification. But it seems rather overkill. Product Supplier * 1 Can be implemented e.g. like this in Java: class Supplier { products : Set<Child> ... } class Product { supplier : Supplier ... }

  28. Many-to-many Can be implemented e.g. like this in Java: class Supplier { products : Set<Product> ... } < supplies * * Product Supplier So we can have this situation in Java (which is ok) : S : Supplier p : Product T : Supplier q : Product 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 Some assoc. class < supplies * * Product Supplier A&N suggest this solution (supplier-centric; for product-centric reverse the aggregation/composition direction) : 1 1 * * Product SuppyRelation Supplier Example of instance : a : SuppyRelation S : Supplier p : Product b : SuppyRelation q : Product c : SuppyRelation T : Supplier (now you can add attributes to SupplyRelation)

  30. Reifying association class < supplies Product Supplier * * SupplyProperty transportCost SupplyProperty tranportCost Product Supplier 1 * 1 * Example of instance : a : SupplyProperty transportCost= 1000 p : Product b : SupplyProperty transportCost= 1000 S : Supplier q : Product c : SupplyProperty transportCost = 10 T : Supplier

  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: Lyric 0..1 <<interface>> Media play() * Album Song Player * <<use>> Lollipop notation, to emphasis the “assembly” of interface supplier and consumer. Media Player Album

  33. Modeling component in UML <<component>> Album • 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. Lyric 0..1 title : String Media Album title Song * songs : Song [0..100] usual class diagram modeling. Notice the use of composition above, which suggests containment “structures”. lyrics : Lyric[0..100] 0..1 Now modeling Album as a component..

  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 Transaction Management Item Management <<subsystem>> Business Logic Data Access Management <<subsystem>> Persistence 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 [outlined] deployment model [outlined] subsytem model analysis models architectural design architect use case engineer “design” use case component engineer design subsystem “design” class 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() : int discounts [0..1] gets * context x : Item :: netPrice derive: x.getPrice (1) context x : Item :: addDiscount(e : Discount) pre : ... post : x.netPrice = x.netPrice@pre - e.getValue()

  39. Example Amount + amount : int + convert(c : Currency) : Amount + add(a : Amount) : void 1 default currency Customer - email : String # charge() 1 1 PaymentProtocol # charge(a : Amount) • Currency • name : String 1 item’s currency 1 Item - name : String - price + getPrice() : Amount * Basket price(currency) : Amount ordered, non-unique Constrain basket  total value of its items does not exceed 1 million eurocent. Constrain  price of each item in the basket should be at least 1, in the customer’s currency. Give specifications for (a) “price” (red), (b) “charge”(blue), and (c) yellow

  40. context b : Basket inv : b.price(EURO) ≤ 1000000 • 1 • 2 • 3.a context b : Basket inv : b.items forall ( x | x.getPrice().convert(b.owner.currency).amount  1) context b : Basket :: price(c : Currency) : Amount pre : c  null post : result.amount = b.items  collect ( x | x.getPrice().convert(b.owner.currency).amount )  sum()

  41. Customer - email : String # charge() : Amount • 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 : Customer pre : - post : result  null implies result.amount = c.basket.price().amount context o : Amount :: add(a : Amount) pre : a  null post : o.amount = o.amount@pre + a.convert(o.currency).amount

More Related