400 likes | 560 Views
Diagramy interakcji - rodzaj diagramów dynamicznych. Autor: Magdalena Maksymowicz. Diagramy interakcji - rodzaj diagramów dynamicznych.
E N D
Diagramy interakcji - rodzaj diagramów dynamicznych Autor: Magdalena Maksymowicz
Diagramy interakcji - rodzaj diagramów dynamicznych • Diagramy interakcji pozwalają pokazać realizacje przypadków użycia jako współdziałanie obiektów klas. Obiekty wysyłają do siebie komunikaty (jest obiekt-nadawca komunikatu i obiekt-odbiorca). W wyniku odebrania komunikatu obiekt-odbiorca wykonuje swoją operację (można powiedzieć, że komunikat jest wywołaniem operacji) lub powstaje sygnał. Działanie programu jest sekwencją komunikatów. • Nie dla wszystkich przypadków użycia może zachodzić potrzeba konstruowania diagramów interakcji, lecz dla przypadków „trudnych", dla których może zachodzić potrzeba rozważenia alternatywnych sposobów realizacji. Niektóre narzędzia CASE potrafią wykorzystać te diagramy do generacji kodu, co może stanowić ważny powód dla ich konstruowania. • UML definiuje dwa rodzaje diagramów interakcji: • diagramy kooperacji (współdziałania), • diagramy sekwencji (przebiegu). • Oba rodzaje diagramów przedstawiają prawie tą samą informację, w nieco inny sposób.
Diagramy interakcji - diagram kooperacji • Diagram kooperacji. • Obiekty klas na diagramie, między którymi są przekazywane komunikaty są połączone. Stanowią one tzw. grupę współdziałania (kooperację, kolaborację) • realizującą dany przypadek użycia. Połączenia odpowiadają powiązaniom między danymi klasami na diagramie klas. Na diagramie interakcji może wystąpić więcej niż jeden obiekt danej klasy.
Diagramy interakcji - diagram kooperacji • Diagram kooperacji. • Obiekty klas mogą być oczywiście przedstawione jako prostokąty. Oznaczenie obiektów kółkami podkreśla, że rozważa się realizacje przypadku użycia jako zadanie analizy, a nie projektowania. • Komunikaty przedstawiane są tu w postaci etykiet strzałek rysowanych wzdłuż połączeń między współpracującymi przy realizacji przypadku użycia obiektami. • Na diagramach interakcji z reguły nie pokazuje się odpowiedzi na wysyłane komunikaty. • Komunikaty mogą być numerowane albo kolejnymi liczbami naturalnymi (jak na poprzednim diagramie), albo stosując tzw. numerację zagnieżdżoną.
Diagramy interakcji - diagram kooperacji Numeracja zagnieżdżona, np. 2.1 ...oznacza, że obiekt otrzymał komunikat o numerze 2 i w odpowiedzi na ten komunikat podejmuje akcje, które zostają ponumerowane zgodnie z kolejnością występowania, a numery poprzedzone prefiksem - 2, wskazującym na ich „powód".
Diagramy interakcji - diagram sekwencji (przebiegu) • Diagram posiada dwa wymiary : • poziomy - stanowią obiekty biorące udział w PU; kolejność obiektów nie ma znaczenia; • pionowy - przyrost czasu, kolejność w czasie; • Obiekt jest przedstawiany jako „linia życia" (linia pionowa przerywana) z prostokątem u góry z podkreśloną nazwą obiektu. • Strzałki prostopadłe do „linii życia" symbolizują komunikaty przesyłane od obiektu-nadawcy do obiektu-odbiorcy. Komunikaty są oznaczone nazwą akcji. Nie ma konieczności ich numerowania, bo pokazana jest kolejność w czasie. Wydłużony prostokąt na „linii życia" oznacza stan aktywny obiektu (najczęściej oznacza to, że odbiera lub wysyła komunikat, jest w trakcie odpowiedzi na odebrany komunikat). • Jeśli obiekt jest tworzony w czasie trwania modelowanego przypadku użycia, prostokąt wieńczący „linię życia" pojawia się w odpowiednim punkcie czasowym.
Diagramy interakcji - diagram sekwencji (przebiegu) • Jeśli obiekt jest likwidowany w czasie trwania przypadku użycia, „linia życia" jest urywana w odpowiednim miejscu ze znakiem "X" na końcu. X
Diagramy interakcji - diagram sekwencji (przebiegu) • Dwa sposoby opisywania czasu: oznaczanie skali czasowej lub nakładanie ograniczeń na upływ czasu. Ograniczenia oznacza się w nawiasach klamrowych, np. {< 5 sek.} może oznaczać, ze reakcja na komunikat nie powinna trwać dłużej niż 5 sekund. • Czasami przydaje się uwidocznienie wartości zwracanej przez komunikat, poprzez instrukcję przypisania. Umożliwia to późniejsze wykorzystanie tej wartości, np. jako argumentu dla innego komunikatu. Może też być wykorzystana do specyfikowania warunku czy iteracji. • Diagram interakcji może wystąpić w dwóch formach: • opisującej jeden z przebiegów, • ogólnej, stanowiącej opis wszystkich przebiegów przypadku użycia (z pokazaniem warunków iteracji).
Diagramy interakcji - diagram sekwencji (przebiegu) Przykłady iteracji: *[i := 1..10] - komunikat będzie wysłany 10 razy, *[x < 10] - komunikat będzie wysyłany dopóki x będzie < 10, *[pozycja znaleziona] - komunikat będzie wysyłany do momentu, gdy pozycja nie zostanie znaleziona (gdy warunek przyjmie wartość FALSE) Jeśli w trakcie wielokrotnego wysyłania komunikatu x, będzie wysyłany także komunikaty, to zostanie on wysłany tyle razy, ile razy wysyłane jest x. Zachowanie spójności diagramów nie wymaga powtarzania symbolu iteracji dla komunikatu y.
Dalej żywcem skopiowany artykuł, którego autorem jest Steven Palmer: Java and UML Interaction Diagrams. Dalej w podróży tej towarzyszyć nam będzie Niedźwiadek z Rowerkiem
Java and UML Interaction Diagrams • Interaction diagrams depict a specific set of interactions between a set of objects. In this fourth article introducing UML from a programmer's perspective, Stephen Palmer compares UML sequence and collaboration diagrams with equivalent Java source code constructs. • We will be using a very simplistic and partially complete sales and tracking system to illustrate sequence and collaboration diagrams. The system consists of six Java classes with the following major methods, in addition to the usual accessor methods for properties and collections: • Sale • calcPayments—Total the amount of all payments made for the sale • calcTotal—Total the cost of all items purchased as part of the sale • complete—Mark the sale transaction as finished • LineItem • calcTotal—Total the cost of one type of item purchased • Product • calcTotal—Total the cost of one type of item purchased • Payment • CreditCardPayment • authorize—Authorize the use of the credit card for this payment • CashPayment • calcChange—Calculate the amount of change to be returned to the purchaser
Java and UML Interaction Diagrams • Figure 1 shows a class diagram for our sales- and payment-tracking classes. Figure 1 Class diagram showing the structure of a simply sales and payment tracking system.
Java and UML Interaction Diagrams • Interaction Diagrams • If we trace through an execution of any Java program, we see that it contains one or more sequences of method invocations on objects and classes. We invoke a method on an object of a class to answer a specific question or perform a specific action. Often, that method will invoke other methods—either on itself, on objects of the same class, or on objects of other classes. These methods, in turn, may invoke other methods and so on until the question is completely answered or the requested action is completely performed (or an exception occurs that prevents the question being answered or the action being performed). • UML interaction diagrams graphically represent sequences of method invocations, and come in two flavors: sequence diagrams and collaboration diagrams.
Java and UML Interaction Diagrams • Sequence Diagrams • UML sequence diagrams typically show some sequence of method invocations that achieve some specific purpose. Figure 2 shows a sequence diagram for calculating the total of a sale transaction. It starts with a call to the method calcTotal() of the Sale class. The relevant snippets of source code are shown below the diagram. • Terminology Note • UML defines an operation as the signature of a method. The term method is reserved for the code that provides the implementation of an operation. In the Java world, it is usual to use term method in both contexts. In sequence diagrams, the invoking of an operation is called sending a message. Sequence diagrams are essentially about the implementation of operations, so I have used the term method throughout this article (occasionally resorting to the term message when describing a particular UML diagram).
Java and UML Interaction Diagrams • Figure 2 A sequence diagram for calculating the total of a sale.
Java and UML Interaction Diagrams • /** • * From the Sale class: • * calculates the total of the sale from the lineItem subtotals • * @return total of the sale • */ • public double calcTotal() { • total = 0.0; • Iterator i = lineItems.iterator(); • while (i.hasNext()) total += ((LineItem)i.next()).calcTotal(); • return total; • } • /** • * From the LineItem class: • * calculates the cost of this amount of this kind of item • * @return the cost of this amount of the item • */ • public double calcTotal() { • total = product.calcTotal(this); • return total; • } • /** • * From the Product class: • * calculates the current cost of a quantity of the product • * @return cost of the line item supplied • */ • public double calcTotal(LineItem li) { • return amount * li.getQuantity(); • }
Java and UML Interaction Diagrams • To get a better overall feel for the sequence, only the method names are shown. More detailed sequence diagrams show method arguments and return types. • Objects that participate in the sequence and exist at the start of the sequence are spread across the top of the diagram. They are displayed using the usual UML notation for an object; the same shape or symbol used for the class of the object (a rectangle by default) with the name of the object followed by a colon, and the name of the class that defines that object. The whole name is underlined (for example, aProduct:Product in Figure 2). Either the object name (for example, :Sale in Figure 2) or class name (for example, Sender in Figure 2) may be omitted, but obviously not both. If the object name is omitted, the colon must be retained. • Time is imagined as running vertically from top to bottom of the diagram. Each object has a lifeline running vertically down the page, immediately below its rectangle. Method invocations are drawn as solid lines with open arrowheads from the lifeline of the calling object to the lifeline of the receiving object. An object's lifeline is widened whenever one of its methods is being executed. These activation bars may be nested to show that another method of the object has been invoked as part of the execution of the previous method; the getQuantity() method in Figure 2 is an example of this. • Optionally, returns from methods may be shown as a dotted line with an open arrowhead (for example, the return arrow from :Sale to Sender in Figure 2) where it makes things clearer to do so.
Java and UML Interaction Diagrams • Where iteration over a collection of objects is needed, an asterisk precedes the method name with an optional condition inside square brackets. An example can be seen in the call from the Sale class to the LineItem class objects in Figure 2. • As with UML class diagrams, what would normally require the inspection of multiple source code files is summarized in one UML diagram. Reverse engineering sequence diagrams from existing source code can help developers new to the code understand how it works, and can help developers communicate to client representatives the way the software works in a form less threatening than source code. • Objects that I Know • When sketching a sequence diagram to explore the problem domain, explicitly prove a class diagram can support a sequence of method invocations that achieve a required goal, or as part of the low-level design of a functional requirement, a common mistake that must be avoided is to invoke a method on an object that the caller has no direct knowledge of. In Java, there are three fundamental ways an object may know of the existence of another object. First, an object's static or instance variables may contain either a reference to the target object, or a name or identifier through which the object might be located via a lookup service of some description (for example, JNDI, Factory class, database query). In this case, this knowledge is usually shown as an association in a class diagram. Second, the calling object may be passed a reference to the target object as a parameter of the invoked method. Third, the calling object may create a new instance of the target object.
Java and UML Interaction Diagrams • More Notation • Figure 3 shows a sequence diagram for the complete() method of the Sale class. This time, we have numbered the messages. The complete() method calls two other methods of the Sale class: calcTotal() and calcPayments(). Figure 3 shows the loopback notation used to indicate that an object is calling method on itself. • Larger sequence diagrams can become too wide to display comfortably on a screen. In Figure 3, a switch in Together ControlCenter's2 options panel displays the class name underneath the object name instead of alongside, reducing the amount of horizontal space required for each object. This can reduce the amount of horizontal space required by the diagram if class names are longer than a few characters and arguably make the diagram a little easier to read. However, to be strictly compliant with the latest UML specification3, the class name should appear to the left of the object name and be preceded by a colon, as shown in Figure 2. • Notation Note • When working collaboratively, I enjoy the convenience of using three-inch square Post-It[tm]notes and marker pens on flipchart pads or whiteboards. I also use a common shorthand convention for the object and class name; form the object name by prefixing the class name with an"a" or "an" as appropriate, and omit the class name.
Java and UML Interaction Diagrams Figure 3 A sequence diagram for completing a sale.
Java and UML Interaction Diagrams • As a result of the call to calcTotal() by the complete() method, our calcTotal() sequence in Figure 2 is a consequence of the complete() sequence in Figure 3. We could have simplified Figure 3 by omitting the Product object and its interactions with the LineItem object and by referring the reader to Figure 2 at that point. Again, the general principle of only showing what is necessary to accurately communicate with the reader applies. For example, few readers of a sequence diagram will benefit from the inclusion of standard Java classes such as iterators, wrappers, and collection classes. Also, although a sequence diagram can show the use of looping and branching constructs, this level of detail is perhaps best examined by reading the actual source code in conjunction with a higher-level sequence diagram. Figure 4 shows the result of using Together ControlCenter to reverse engineer the complete() method of the Sale class and asking it to include as much detail as possible. This level of detail is probably too much for most people. However, Figure 4 does serve one useful purpose: The exception object shows that objects created during a sequence diagram are drawn at the point they are created instead of at the top of the diagram.
Java and UML Interaction Diagrams Figure 4 A highly detailed sequence diagram generated by a tool.
Java and UML Interaction Diagrams • Collaboration Diagrams • The second flavor of UML interaction diagram is the collaboration diagram. Semantically equivalent to a sequence diagram, this type of diagram arranges objects spatially—according to the whim of the user creating the diagram. The sequence of interactions is determined from the message numbering. Some people prefer this approach, and better UML tools allow the user to flip a diagram between sequence and collaboration notations and back again as often as they wish. Some organizations have a convention of using collaboration diagrams to show interactions between components and using sequence diagrams to show interactions between classes within a component. Figure 5 shows the collaboration diagram equivalent of the sequence diagram in Figure 2. Figure 6 does the same for Figure 4.
Java and UML Interaction Diagrams Figure 5 UML collaboration diagram.
Java and UML Interaction Diagrams Figure 6 Collaboration diagram equivalent of Figure 4.
Java and UML Interaction Diagrams • Conclusion • With practice, many required sequences of interactions can be implied from the class diagram, especially when class archetypes and stereotypes are used to indicate particular patterns of behavior and interaction. UML interaction diagrams make those implications explicit and describe clearly scenarios in which the sequence of interactions is not clear from class diagrams. In other words, UML interaction diagrams complement the more static nature of UML class diagrams by making explicit the dynamic interactions involved. • Neither type of diagram is particularly good at showing recursion and the handling of exceptions. For significant interactions of this type, it is best to attach a note to the relevant points in the diagram. • In the last article in the series, we will look briefly at the other five UML diagram types. Until then, I leave you with a quote from Peter Coad (et al): • "Why use scenarios [interaction diagrams]? Here's why: • To find additional objects. • To better distribute and refine responsibilities. • To gain a better understanding of system dynamics. • To assess model completeness. • To test an object model (ultimately, to test the system itself).
Java and UML Interaction Diagrams • Source Code • Sale Class • /** • * One user transaction consisting of purchases of potentially many kinds of product • * @stereotype moment-interval • */ • public class Sale { • /** • * calculates the total of the sale from the lineItem subtotals • * @return total of the sale • */ • public double calcPayments() { • paymentsTotal = 0.0; • Iterator i = payments.iterator(); • while (i.hasNext()) paymentsTotal += ((Payment)i.next()).getAmount(); • return total; • } • /** • * calculates the total of the sale from the lineItem subtotals • * @return total of the sale • */ • public double calcTotal() { • total = 0.0; • Iterator i = lineItems.iterator(); • while (i.hasNext()) total += ((LineItem)i.next()).calcTotal(); • return total; • }
Java and UML Interaction Diagrams • /** • * retrieves the cached total of the sale • * @return total of sale, 0.0 if calcTotal() has not yet been called • */ • public double getTotal() { • return total; • } • /** • * sets the status of the sale to compltete if payments equal price • * @exception Exce[tion thrown if payments do not equal price • */ • public void complete() throws Exception { • if (calcTotal() != calcPayments()) { • throw new Exception("Payments do not equal total price"); • } • status = "Complete"; • } • /** • * adds a line item for a quantity of a type of item • * @param product the type of item being sold • * @param qty the quantity of the item being sold • */ • public void addLineItem(Product product, int qty) throws Exception { • if (status.equals("Incomplete")) { • lineItems.add(new LineItem(product, qty)); • } • else { • throw new Exception("Cannot add items to a completed sale"); • } • }
Java and UML Interaction Diagrams • /** status of sale */ • private String status = "Incomplete"; • /** • * the cost of this quantity of the item the Product is responsible for • * handling quantity discounting or time based special deals, etc • */ • private double total; • /** the total of all the payments made for this sale */ • private double paymentsTotal; • /** • * @link aggregation • * @associates <{LineItem}> • * @supplierCardinality 1..* • * @clientCardinality 1 • */ • private Vector lineItems = new Vector(); • /** • * payments of various kinds • * @associates <{Payment}> • * @supplierCardinality 0..* • * @clientCardinality 1 • */ • private Vector payments = new Vector(); • }
Java and UML Interaction Diagrams • SaleItem Class • /** • * one line in a sale of potentially many kinds of product • * @stereotype mi-detail • */ • public class LineItem { • /** • * mandatory value constructor requires values for all attributes needed to • * put the object in a valid state • * @param product the kind of item being purchased • * @param qty the quanity of the item being purchased • */ • public LineItem(Product product, int qty) { • this.product = product; • this.quantity = qty; • } • /** • * calculates the cost of this amount of this kind of item • * @return the cost of this amount of the item • */ • public double calcTotal() { • total = product.calcTotal(this); • return total; • }
Java and UML Interaction Diagrams • /** • * accessor method for cached cost of this lineItem • * @return price for this quantity of the item at the time of the sale • */ • public double getTotal() { • return total; • } • /** • * accessor method for quantity • * @return the quanity of the item being purchased • */ • public int getQuantity() { • return quantity; • } • /** • * accessor method for quantity • * @param quantity the quanity of the item being purchased • */ • public void setQuantity(int quantity) { • this.quantity = quantity; • }
Java and UML Interaction Diagrams • /** • * the kind of ite being purchased • * @supplierCardinality 1 • * @clientCardinality 0..* • */ • private Product product; • /** cached value of this line item */ • private double total; • /** number of units being purchased */ • private int quantity; • }
Java and UML Interaction Diagrams • Product Class • /** • * Instances represent entries in the inventory catalog • * @stereotype description • */ • public class Product { • /** • * mandatory values constructor requires values for all attributes needed to • * leave the object in a valid state • * @param code the UPC • * @param name short human friendly name for the product • * @param amount the price of one unit of the product • */ • public Product(String code, String name, double amount) { • this.code = code; • this.name = name; • this.amount = amount; • } • /** • * calculates the current cost of a quantity of the product • * @return cost of the line item supplied • */ • public double calcTotal(LineItem li) { • return amount * li.getQuantity(); • } • /** UPC */ • private String code;
Java and UML Interaction Diagrams • Product Class • /** • * Instances represent entries in the inventory catalog • * @stereotype description • */ • public class Product { • /** • * mandatory values constructor requires values for all attributes needed to • * leave the object in a valid state • * @param code the UPC • * @param name short human friendly name for the product • * @param amount the price of one unit of the product • */ • public Product(String code, String name, double amount) { • this.code = code; • this.name = name; • this.amount = amount; • } • /** • * calculates the current cost of a quantity of the product • * @return cost of the line item supplied • */ • public double calcTotal(LineItem li) { • return amount * li.getQuantity(); • } • /** UPC */ • private String code; • /** Human friendly product name */ • private String name; • /** current price of a unit of the product */ • private double amount; • }
Java and UML Interaction Diagrams • Payment Class • /** • * represents a payment of some kind • * @stereotype moment-interval • */ • abstract public class Payment { • /** • * mandatory value constructor requires values for all attributes needed to • * put the new object into a valid state • * • * @param amount the amount of this payment • */ • public Payment(double amount) { • this.amount = amount; • } • /** • * accessor for amount property • * @return the amount property • */ • public double getAmount() { • return amount; • }
Java and UML Interaction Diagrams • /** • * accessor for the amount property • * @param amount the value of the property • */ • public void setAmount(double amount) { • this.amount = amount; • } • /** amount of the payment */ • private double amount; • }
Java and UML Interaction Diagrams • CashPayment Class • /** • * a subclass that extends the Payment class to represent cash payments • * @stereotype moment-interval • */ • public class CashPayment extends Payment { • /** • * mandatory value constructor requires values for all attributes needed to • * put the new object into a valid state • * • * @param amount the amount tendered for this payment • */ • public CashPayment(double amount) { • super(amount); • } • /** • * amount tendered is what was passed into the constructor • * @return amount tendered • */ • public double getAmountTendered() { • return super.getAmount(); • }
Java and UML Interaction Diagrams • /** • * calculate the change to be given for a required amount • * @return value of change • */ • public double calcChange( double requiredAmount ) { • change = super.getAmount() - requiredAmount; • return change; • } • /** • * override superclass to calc actual amount based on change given • * @return amountTendered - change given • */ • public double getAmount() { • return super.getAmount() - change; • } • /** amopunt of change given */ • private double change = 0.0; • }
Java and UML Interaction Diagrams • CreditCardPayment Class • /** • * a subclass that extends the Payment class to represent credit card payments • * @stereotype moment-interval • */ • public class CreditCardPayment extends Payment { • /** • mandatory value constructor requires values for all attributes • needed to put the new object into a valid state • * @param amount the amount of this payment • * @param cardNumber the number of the credit card • */ • public CreditCardPayment(double amount, String cardNumber) { • super(amount); • this.cardNumber = cardNumber; • } • /** • * accessor for cardNumber property • * @return value of property • */ • public String getCardNumber() { • return cardNumber; • }
Java and UML Interaction Diagrams • /** • * accessor for cardNumber property • * @param cardNumber value of property • */ • public void setCardNumber(String cardNumber) { • this.cardNumber = cardNumber; • } • /** • * authorize the payment using an external system somewhere • * @return true if payment valid • */ • public boolean authorize() { • return false; //not yet implemented • } • /** credit card number property */ • private String cardNumber; • }