60-322 Object-Oriented Analysis and Design Week 11, 2009 Ch 18. Use Case Realization for NextGen POS Process Sale Scenario : Cashier makeNewSale Simple cash-only Process Sale scenario: 1. Customer arrives at a POS checkout with goods and/or services to purchase. 2. Cashier starts a new sale. 3. Cashier enters item identifier. 4. System records sale line item and presents item description, price, and running total. Cashier repeats steps 3-4 until indicates done. 5. System presents total with taxes calculated. 6. Cashier tells Customer the total, and asks for payment. 7. Customer pays and System handles payment. ... loop [ more items ] enterItem(itemID, quantity) description, total endSale total with taxes makePayment(amount) change due, receipt 2 Mar 26, 2008 :System Ch 18. Use Case Realization for NextGen POS Records-sale-of Ledger Product Description Product Catalog Contains 1 1 1..* 1 1 Recordsaccountsfor 0..1 Sales LineItem itemID description price Used-by Describes * * Store Item Stocks quantity 1 1..* Contained-in name address 1 Logscompleted 1 1..* Houses Register Captured-on 1 0..1 dateTime / total * 1..* * Sale 1 id 1 1 Paid-by 1 CashPayment 1 Works-on Is-for 1 Customer amountTendered 3 1 Cashier id Mar 26, 2008 Ch 18. How to Design makeNewSale? by Creator and Controller Register creates a Sale by Creator :Register makeNewSale create :Sale create this execution specification is implied to be within the constructor of the Sale instance Records-sale-of Ledger Product Description Product Catalog Contains 1 1 1..* 1 1 Recordsaccountsfor 0..1 Sales LineItem itemID description price Used-by Describes * * Store Item Stocks quantity 1 1..* Contained-in name address * 1..* Houses 1..* * Sale Register Captured-on 1 0..1 dateTime / total 1 1 Logscompleted 1 id 1 1 Paid-by 1 CashPayment 4 amountTendered 1 Is-for by Creator, Sale creates an empty collection (such as a List) which will eventually hold SalesLineItem instances Works-on 1 1 Customer Cashier id Mar 26, 2008 lineItems : List<SalesLineItem> How to Design enterItem? by Creator by Controller enterItem(id, qty) :Register 2: makeLineItem(desc, qty) :Sale 1: desc = getProductDesc(id) 2.1: create(desc, qty) :Product Catalog by Expert sl: SalesLineItem 1.1: desc = get(id) 2.2: add(sl) : Map<ProductDescription> lineItems : List<SalesLineItem> add the newly created SalesLineItem instance to the List Records-sale-of Ledger Product Description Product Catalog Contains 1 1 1..* 1 1 Recordsaccountsfor 0..1 Sales LineItem itemID description price Used-by Describes * * Store Item Stocks quantity 1 1..* Contained-in name address 1 Logscompleted 1 * 1..* Houses 1..* * Sale Register Captured-on 1 0..1 dateTime / total 1 id 1 1 Paid-by 5 1 CashPayment Mar 26, 2008 amountTendered 1 Is-for Works-on 1 1 Customer Cashier id How to Design enterItem? ProductDescription ProductCatalog 1 catalog ... descriptions description : Text {Map} price : Money 1..* itemID: ItemID getProductDesc(...) ... description 1 Sale Register ... isComplete : Boolean time : DateTime currentSale enterItem(...) ... 6 1 makeLineItem(...) ... Mar 26, 2008 lineItems {ordered} 1..* SalesLineItem quantity : Integer ... How to Design endSale endSale( :Register by Controller 7 1: becomeComplete by Expert Mar 26, 2008 s :Sale Ch 18. Use Case Realization for NextGen POS Process Sale Scenario : Cashier makeNewSale Simple cash-only Process Sale scenario: 1. Customer arrives at a POS checkout with goods and/or services to purchase. 2. Cashier starts a new sale. 3. Cashier enters item identifier. 4. System records sale line item and presents item description, price, and running total. Cashier repeats steps 3-4 until indicates done. 5. System presents total with taxes calculated. 6. Cashier tells Customer the total, and asks for payment. 7. Customer pays and System handles payment. ... loop [ more items ] enterItem(itemID, quantity) description, total endSale total with taxes makePayment(amount) change due, receipt 8 Mar 26, 2008 :System How to Design getTotal()? Simple cash-only Process Sale scenario: 1. Customer arrives at a POS checkout with goods and/or services to purchase. 2. Cashier starts a new sale. 3. Cashier enters item identifier. 4. System records sale line item and presents item description, price, and running total. Cashier repeats steps 3-4 until indicates done. 5. System presents total with taxes calculated. 6. Cashier tells Customer the total, and asks for payment. 7. Customer pays and System handles payment. ... by Expert by Expert tot = getTotal :Sale 1 * [i = 1..n]: st = getSubtotal UML: note the selector notation to select elements from the lineItems collection lineItems[ i ]: SalesLineItem 1.1: pr = getPrice :ProductDescription 9 •Not all interaction diagrams start with a system operation message. •They can start with any message for which the designer wishes to show interactions. Mar 26, 2008 loo Ch 18. Use Case Realization for NextGen POS Process Sale Scenario : Cashier makeNewSale Simple cash-only Process Sale scenario: 1. Customer arrives at a POS checkout with goods and/or services to purchase. 2. Cashier starts a new sale. 3. Cashier enters item identifier. 4. System records sale line item and presents item description, price, and running total. Cashier repeats steps 3-4 until indicates done. 5. System presents total with taxes calculated. 6. Cashier tells Customer the total, and asks for payment. 7. Customer pays and System handles payment. ... loop [ more items ] enterItem(itemID, quantity) description, total endSale total with taxes makePayment(amount) change due, receipt 10 Mar 26, 2008 :System How to Design makePayment? by Controller makePayment(cashTendered) by Creator and Low Coupling :Register 1: makePayment(cashTendered) :Sale 1.1: create(cashTendered) :Payment makePayment() 1: create() : Register p : Payment Remember this? bad design! 2: addPayment(p) 11 Mar 26, 2008 :Sale Logging a Sale - How to Design makePayment? 12 Mar 26, 2008 Logging a Sale - How to Design makePayment? Who is responsible for knowing all the logged sales and doing the logging? Store or SalesLedger? Sale Sale ... ... ... ... * * Logs-completed Logs-completed 1 1 Store SalesLedger ... ... addSale(s : Sale) ... addSale(s : Sale) ... Store is responsible for knowing and adding completed Sales. SalesLedger is responsible for knowing and adding completed Sales. Acceptable in early development cycles if the Store has few responsibilities. 13 Suitable when the design grows and the Store becomes uncohesive. Mar 26, 2008 Logging a Sale - How to Design makePayment? Stick with Store for now, may change to SalesLedger later during desing? note that the Sale instance is named 's' so that it can be referenced as a parameter in messages 2 and 2.1 makePayment(cashTendered) :Register 2: addSale(s) s :Sale 1.1: create(cashTendered) by Expert :Payment :Store 2.1: add(s) completedSales: List<Sale> 14 1: makePayment(cashTendered) Mar 26, 2008 Calculating balance • The Process Sale use case implies that the balance due from a payment be printed on a receipt and displayed somehow. • • Because of the Model-View Separation principle, we should not concern ourselves with how the balance will be displayed or printed. • But we must ensure that it is known. •No class currently knows the balance, so we need to create a design of object interactions that satisfies this requirement. 15 Mar 26, 2008 Calculating balance – the Reasoning To calculate the balance, we need the sale total and payment cash tendered. Therefore, Sale and Payment are partial Experts on solving this problem. If the Payment is primarily responsible for knowing the balance, it needs visibility to the Sale, to ask the Sale for its total. Since it does not currently know about the Sale, this approach would increase the overall coupling in the design it would not support the Low Coupling pattern. In contrast, if the Sale is primarily responsible for knowing the balance, it needs visibility to the Payment, to ask it for its cash tendered. Since the Sale already has visibility to the Payment -as its creator. This approach does not increase the overall coupling and is therefore a preferable design. { bal = pmt.amount - s.total } bal = getBalance 16 s :Sale 26, 2008 2: tMar = getTotal 1: amt = getAmount pmt: Payment The Final NextGen DCD for Iteration -1 Store address : Address name : Text catalog 1 ProductDescription ProductCatalog addCompleteSale(...) 1 catalog ... descriptions description : Text {Map} price : Money 1..* itemID: ItemID getProductDesc(...) ... description register 1 Sale Register ... endSale() enterItem(...) makeNewSale() makePayment(...) isComplete : Boolean time : DateTime currentSale 1 lineItems {ordered} becomeComplete() makeLineItem(...) makePayment(...) getTotal() completedSales {ordered} 1..* * Payment amount : Money ... Mar 26, 2008 quantity : Integer getSubtotal() payment 1 17 SalesLineItem 1 How to Connect the UI Layer to the Domain Layer? 18 Common designs by which objects in the UI layer obtain visibility to objects in the domain layer include the following: – An initializer object (for example, a Factory object) called from the application starting method (e.g., the Java main method) creates both a UI and a domain object and passes the domain object to the UI. – A UI object retrieves the domain object from a wellknown source, such as a factory object that is responsible for creating domain objects. Mar 26, 2008 Controller (in Coding) 19 Mar 26, 2008 How to Connect the UI Layer to the Domain Layer? Once the UI object has a connection to the Register instance (the facade controller in this design), it can forward system event messages, such as the enterItem and endSale message presses button Cashier actionPerformed( actionEvent ) UI Layer :ProcessSale JFrame 1: enterItem(id, qty)? 20 Domain Layer :Register Mar 26, 2008 system event Initialization and the 'Start Up' Use Case Most systems have either an implicit or explicit Start Up use case and some initial system operation related to the starting up of the application. Although abstractly, a startUp system operation is the earliest one to execute, delay the development of an interaction diagram for it until after all other system operations have been considered. This practice ensures that information has been discovered concerning the initialization activities required to support the later system operation interaction diagrams. 21 Mar 26, 2008 How do Applications Start Up? The startUp or initialize system operation of a Start Up use case abstractly represents the initialization phase of execution when an application is launched. In all cases, a common design idiom is to create an initial domain object or a set of peer initial domain objects that are the first software "domain" objects created. 22 To understand how to design an interaction diagram for this operation, you must first understand the contexts in which initialization can occur. How an application starts and initializes depends on the programming language and operating system. This creation may happen explicitly in the starting main method or in a Factory object called from the main method. Mar 26, 2008 How do Applications Start Up? Often, the initial domain object (assuming the singular case), once created, is responsible for the creation of its direct child domain objects. 23 For example, a Store chosen as the initial domain object may be responsible for the creation of a Register object. Mar 26, 2008 Choosing the Initial Domain Object Guideline Choose as an initial domain object a class at or near the root of the containment or aggregation hierarchy of domain objects. This may be a facade controller, such as Register, or some other object considered to contain all or most other objects, such as a Store. 24 In this application, we chose the Store as the initial object. Mar 26, 2008 Choosing the Initial Domain Object By reflecting on the prior interaction designs, we identify the following initialization work: 25 Create a Store, Register, ProductCatalog, and ProductDescriptions. Associate the ProductCatalog with ProductDescriptions Associate Store with ProductCatalog. Associate Store with Register. Associate Register with ProductCatalog. Mar 26, 2008 Choosing the Initial Domain Object pass a reference to the ProductCatalog to the Register, so that it has permanent visibility to it create 2: create(pc) :Store by Creator :Register create an empty collection object 1: create 1.1: create pc: ProductCatalog 1.2.2*: put(id, pd) descriptions: Map<ProductDescription> 1.2.1*: create(id, price, description) 1.2: loadProdSpecs() the * in sequence number indicates the message occurs in a repeating section 26 Mar 26, 2008 pd: ProductDescription Process: Iterative and Evolutionary Object Design The essential point: Keep it light and short, move quickly to code and test, and don't try to detail everything in UML models. Model the creative, difficult parts of the design. 27 Mar 26, 2008 Ch 19. Designing For Visibility Visibility is the ability of one object to see or have reference to another. This chapter explores this basic but necessary design issue; those new to object design sometimes don't think about and design to achieve necessary visibility. 28 Mar 26, 2008 Visibility Between Objects Message are passing around among object…… For a sender object to send a message to a receiver object, the sender must be visible to the receiver - the sender must have some kind of reference or pointer to the receiver object. 29 Mar 26, 2008 Visibility Between Objects class Register { ... private ProductCatalog catalog; ... } enterItem (itemID, quantity) : Register : ProductCatalog desc = getProductDesc( itemID ) public void enterItem( itemID, qty ) { ... desc = catalog.getProductDesc(itemID) ... } When creating a design of interacting objects, it is necessary to ensure to support message interaction 30 that the necessary visibility Maris 26,present 2008 What is Visibility? In common usage, visibility is the ability of an object to "see" or have a reference to another object. More generally, it is related to the issue of scope: Is one resource (such as an instance) within the scope of another? There are four common ways that visibility can be achieved from object A to object B: 31 Mar 26, 2008 What is Visibility? – Attribute visibility – Parameter visibility – B is a (non-parameter) local object in a method of A. Global visibility B is a parameter of a method of A. Local visibility – B is an attribute of A. B is in some way globally visible. The motivation to consider visibility is this: For an object A to send a message to an object B, B must 32 Mar 26, 2008 be visible to A. Attribute Visibility Attribute visibility from A to B exists when B is an attribute of A. It is a relatively permanent visibility because it persists as long as A and B exist. This is a very common form of visibility in objectoriented systems. public void enterItem(itemID, qty) { ... desc = catalog.getProductDesc(itemID) ... } class Register { ... private ProductCatalog catalog; ... } enterItem (itemID, quantity) : Register : ProductCatalog desc = getProductDesc( itemID ) 33 Mar 26, 2008 Parameter Visibility Parameter visibility from A to B exists when B is passed as a parameter to a method of A. It is a relatively temporary visibility because it persists only within the scope of the method. After attribute visibility, it is the second most common form of visibility in object-oriented systems. enterItem(id, qty) 2: makeLineItem(desc, qty) :Register :Sale 1: desc = getProductDesc(id) 2.1: create(desc, qty) :Product Catalog makeLineItem(ProductDescription desc, int qty) { ... sl = new SalesLineItem(desc, qty); ... } 34 Mar 26, 2008 sl : SalesLineItem Parameter Visibility It is common to transform parameter visibility into attribute visibility. enterItem(id, qty) :Register 2: makeLineItem(desc, qty) :Sale 2: desc = getProductDesc(id) 2.1: create(desc, qty) :Product Catalog sl : SalesLineItem // initializing method (e.g., a Java constructor) SalesLineItem(ProductDescription desc, int qty) { ... description = desc; // parameter to attribute visibility ... } 35 Mar 26, 2008 Local Visibility Local visibility from A to B exists when B is declared as a local object within a method of A. Two common means by which local visibility is achieved are: – – 36 It is a relatively temporary visibility because it persists only within the scope of the method. After parameter visibility, it is the third most common form of visibility in object-oriented systems. Create a new local instance and assign it to a local variable. Assign the returning object from a method invocation to a local variable. As with parameter visibility, it is common to transform locally declared visibility into attribute visibility. Mar 26, 2008 Local Visibility enterItem(id, qty) { ... // local visibility via assignment of returning object ProductDescription desc = catalog.getProductDes(id); ... } enterItem (itemID, quantity) : Register : ProductCatalog desc = getProductDesc( itemID ) 37 Mar 26, 2008 Global Visibility Global visibility from A to B exists when B is global to A. It is a relatively permanent visibility because it persists as long as A and B exist. It is the least common form of visibility in objectoriented systems. One way to achieve global visibility is to assign an instance to a global variable, which is possible in some languages, such as C++, but not others, such as Java. The preferred method to achieve global visibility is to use the Singleton pattern [ch 26], which is discussed in a later chapter. 38 Mar 26, 2008 Ch 20 Mapping Designs to Code With the completion of interaction diagrams and DCDs for the current iteration of the case studies, there's more than enough thought and detail to cut some code for the domain layer of objects. The UML artifacts created during the design work - the interaction diagrams and DCDs - will be used as input to the code generation process. In UP terms, there exists an Implementation Model. – 39 This is all the implementation artifacts, such as the source code, database definitions, JSP/XML/HTML pages, and so forth. Thus, the code being created in this chapter can be considered part of the UP Implementation Model. Mar 26, 2008 Programming and Iterative, Evolutionary Development The prior design modeling should not be taken to imply that there is no prototyping or design-whileprogramming; modern development tools provide an excellent environment to quickly explore and refactor alternate approaches, and some (often lots) design-while-programming is worthwhile. The creation of code in an OO language - such as Java or C# - is not part of OOA/D, it's an end goal. The artifacts created in the Design Model provide some of the information necessary to generate the 40 code. Mar 26, 2008 Creativity and Change During Implementation Some decision-making and creative work was accomplished during design work. It will be seen during the following discussion that the generation of the code in these examples a relatively mechanical translation process. However, in general, the programming work is not a trivial code generation step - quite the opposite! Realistically, the results generated during design modeling are an incomplete first step; during programming and testing, myriad changes will be made and detailed problems will be uncovered and resolved Expect and plan for lots of change and deviation from the design during programming. That's a key and pragmatic attitude in iterative and evolutionary 41 methods. Mar 26, 2008 Mapping Designs to Code Implementation in an object-oriented language requires writing source code for: – – class and interface definitions method definitions The following sections discuss their generation in Java (as a typical case). The discussion is more-or-less independent of using a UML tool for code generation or working from some wall sketches. 42 Mar 26, 2008 Creating Classes from DCDs DCDs depict the class or interface name, superclasses, operation signatures, and attributes of a class. This is sufficient to create a basic class definition in an OO language. If the DCD was drawn in a UML tool, it can generate the basic class definition from the diagrams. 43 Mar 26, 2008 Creating Classes from DCDs public class SalesLineItem { private int quantity; private ProductDescription description; public SalesLineItem(ProductDescription desc, int qty) { ... } public Money getSubtotal() { ... } } ProductDescription SalesLineItem description description : Text price : Money 1 itemID : ItemID quantity : Integer getSubtotal() : Money ... 44 Mar 26, 2008 Creating Methods from Interaction Diagrams The sequence of the messages in an interaction diagram translates to a series of statements in the method definitions. The enterItem interaction diagram illustrates the Java definition of the enterItem method. For this example, we will explore the implementation of the Register and its enterItem method. A Java definition of the Register class is shown 45 below. Mar 26, 2008 Creating Methods from Interaction Diagrams enterItem(id, qty) :Register 2: makeLineItem(desc, qty) 1: desc = getProductDesc(id) :Sale 2.1: create(desc, qty) :Product Catalog sl: SalesLineItem 1.1: desc = get(id) 2.2: add(sl) : Map<ProductDescription> 46 lineItems : List<SalesLineItem> Mar 26, 2008 Creating Methods from Interaction Diagrams public class Register { private ProductCatalog catalog; private Sale currentSale; ProductCatalog public Register(ProductCatalog pc) {...} public void endSale() {...} public void enterItem(ItemID id, int qty) {...} public void makeNewSale() {...} public void makePayment(Money cashTendered) {...} } catalog 1 ... getProductDesc(...) Sale Register ... currentSale endSale() enterItem(id: ItemID, qty : Integer) makeNewSale() makePayment(cashTendered : Money) 47 Mar 26, 2008 1 isComplete : Boolean time : DateTime becomeComplete() makeLineItem(...) makePayment(...) getTotal() Creating Methods from Interaction Diagrams { ProductDescription desc = catalog.ProductDescription(id); currentSale.makeLineItem(desc, qty); } enterItem(id, qty) 2: makeLineItem(desc, qty) :Register 1: desc := getProductDescription(id) :Product Catalog 48 Mar 26, 2008 :Sale Collection Classes in Code public class Sale { ... Sale isComplete : Boolean time : DateTime SalesLineItem lineItems private List lineItems = new ArrayList(); } becomeComplete() makeLineItem() makePayment() getTtotal() A collection class is necessary to maintain attribute visibility to all the SalesLineItems. 49 Mar 26, 2008 1..* quantity : Integer getSubtotal() Exceptions and Error Handling Exception handling has been ignored so far in the development of a solution. This was intentional to focus on the basic questions of responsibility assignment and object design. However, in application development, it's wise to consider the large-scale exception handling strategies during design modeling (as they have a large-scale architectural impact), and certainly during implementation. 50 Mar 26, 2008 One final example (Sale.makeLineItem method) { lineItems.add( new SalesLineItem(desc, qty) ); } enterItem(id, qty) 2: makeLineItem(desc, qty) :Register :Sale 2.2: add(sl) lineItems : List<SalesLineItem> 51 Mar 26, 2008 2.1: create(desc, qty) sl: SalesLineItem Order of Implementation Store 7 address : Address name : Text 1 ProductCatalog addSale(...) 1 2 ProductDescription 3 ... 1..* description : Text price : Money itemID : ItemID getProductDesc(...) ... 1 Classes need to be implemented (and ideally, fully unit tested) 5 1 Sale 6 from least-coupled to most-coupled. Register isComplete : Boolean time : DateTime ... endSale() enterItem(...) makeNewSale() makePayment(...) 1 becomeComplete() makeLineItem(...) makePayment(...) getTotal() ... 1..* Payment 1 amount : Money ... Mar 26, 2008 quantity : Integer getSubtotal() * 52 4 SalesLineItem 1 Summary As demonstrated, there is a translation process – – from UML class diagrams to class definitions, and from interaction diagrams to method bodies. There is still lots of room for creativity, evolution, and exploration during programming work. The code example for the NextGen POS case study… The main point of this listing is to show that there is a translation from design artifacts to a foundation of code. This code defines a simple case; it is not meant to illustrate a robust, fully developed Java program with synchronization, and so on. 53 exception handling, Mar 26, 2008