tags: review diagrams toc title: /Review/Diagrams/Sequence Diagrams type: text/vnd.tiddlywiki \rules except dash This is the sequence diagram tutorial from INFO201. You can use VS Code in the Linux lab to create a new file with the extension `.pu`, or one of the various online PlantUML editors. !PlantUML Sequence Diagram Documentation http://plantuml.com/sequence-diagram !Conventions in this Tutorial <mark style="background:lime">Green highlighting shows that code has been added since the last example.</mark> <mark style="background:aqua">Blue highlighting is code that has changed since the last example.</mark> <mark style="background:fuchsia">Pink highlighting shows that code has been removed (or moved elsewhere) since the last example.</mark> You should incrementally change the code as shown so that you can see the effect of each modification. If you get totally lost you can click the diagram to open it in PlantText. !Simple Example The simplest example looks like: ``` @startuml A -> B : do stuff @enduml ``` [[plantuml[ @startuml A -> B : do stuff @enduml ]]] `A` and `B` are both //participants// (which would usually represent Java classes) and //do stuff// is a message (usually a method call) from `A` to `B`. The footer boxes are just clutter, and the default arrows make it hard to see the difference between the different forms of messages, so we will usually put PlantUML into Strict UML mode: <pre>@startuml <mark style="background:lime">' use strict UML mode skinparam style strictuml</mark> A -> B : do stuff @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml A -> B : do stuff @enduml ]]] !Method Call with Return <pre>@startuml ' use strict UML mode skinparam style strictuml A -> B : <mark style="background:aqua">getName()</mark> <mark style="background:lime">return name</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml A -> B : getName() return name @enduml ]]] This represents `A` calling the `getName()` method on `B`, and `B` returning a `name` to `A`. Solid lines represent method calls, and dashed lines represent the response to calling those methods. !Participants Our participants are a bit boring. Let's beef them up a bit: <pre>@startuml ' use strict UML mode skinparam style strictuml <mark style="background:lime">participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>></mark> <mark style="background:aqua">editor -> book</mark> : getName() <mark style="background:aqua">return name</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> editor -> book : getName() return name @enduml ]]] The names in the speech marks are independent of the alias (the bits defined by the `as`). This is handy for large diagrams because it means that we can change the displayed name of a participant without needing to change all references in the source code. We can also use much shorter names for the aliases which makes referring to the participants much easier. The stereotypes (the bits in the `<< >>`) are additional information that describe the type or role of a class. They are a handy way of adding additional information about a class particularly if it is not that obvious what role the class plays from the class name alone. Note that stereotypes are optional, but handy, so we will use them for most classes. ! Self Calls We can show an object performing internal processing, or making calls on itself using a self-call: <pre>@startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> <mark style="background:aqua">' self call editor -> editor : getText() </mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' self-call editor -> editor : getText() @enduml ]]] !Variables and Parameters Here is how to show variables and parameters: <pre>@startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' get the author from the text component editor -> editor : getText() <mark style="background:aqua">: author</mark> <mark style="background:lime">' set the author field in the book editor -> book : setAuthor(author)</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' get the author from the relevant text component editor -> editor : getText() <color red>: author</color> ' set the author field in the book editor -> book : setAuthor(<color red>author</color>) @enduml ]]] The `getText` call introduces a variable (`author`) that is then passed to the book as a parameter in the `setAuthor` call. Note that we will sometimes used a dashed line for these self-calls that return values since the call and response are combined — using the dashed line makes it more obvious that the call is returning something important: <pre>@startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' get the author from the text component editor <mark style="background:cyan">--></mark> editor : getText(): author ' set the author field in the book editor -> book : setAuthor(author) @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book : setAuthor(author) @enduml ]]] !Actors We can show users interacting with the system using an `actor`: <pre>@startuml ' use strict UML mode skinparam style strictuml <mark style="background:lime">actor "User" as user</mark> participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> <mark style="background:lime">' user enters book details and clicks the save button user -> editor: enters book details user -> editor : clicks save button</mark> ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book : setAuthor(author) @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor: enters book details user -> editor : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book : setAuthor(author) @enduml ]]] !Activation Bars Activation bars show when an object is active. This will often be as a result of a method call on the object. Activation bars can be helpful to show where a method call finishes and ends, and generally make the diagram easier to understand: <pre>@startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save button user -> editor<mark style="background:aqua">++</mark> : enters book details <mark style="background:lime">editor--</mark> user -> editor<mark style="background:aqua">++</mark> : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book<mark style="background:aqua">++</mark> : setText(author) <mark style="background:lime">book-- editor--</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book++ : setAuthor(author) book-- editor-- @enduml ]]] You use `++` and `--` to control the activation bars on an object. A `return` will also deactivate an object. !Object Construction We can show an object being created as follows: <pre>@startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author <mark style="background:lime">' construct the book object create book editor -> book : <<construct>></mark> ' set the author field in the book editor -> book++ : setAuthor(author) editor-- @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author create book editor -> book : <<construct>> ' set the author field in the book editor -> book++ : setAuthor(author) book-- editor-- @enduml ]]] If we wanted to pass the details into the Book constructor instead of using the set method: <pre>@startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author create book editor -> book : <mark style="background:aqua"><<construct(author)>></mark> <mark style="background:fuchsia"> </mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button ' get the author from the relevant text component editor --> editor : getText() : author create "Book" as book <<domain>> editor -> book : <<construct<color red>(author)</color>>> @enduml ]]] ! Variables and Construction We will usually do something with an object when we create it, so we need a variable name for representing the constructed object: <pre>@startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "<mark style="background:aqua">book: </mark>Book" as book <<domain>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button create book <mark style="background:aqua">editor -> book : <<construct>></mark> <mark style="background:lime">' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book++ : setAuthor(author) book-- ' create a DAO create "BookListDAO" as dao <<DAO>> editor -> dao : <<construct>> ' save book editor -> dao++ : save(book) dao-- editor--</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "BookEditor" as editor <<form>> participant "<color:red>book : </color>Book" as book <<domain>> participant "BookListDAO" as dao <<DAO>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button create book editor -> book : <<construct>> ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book++ : setAuthor(author) book-- ' create a DAO create dao editor -> dao : <<construct>> ' save book editor -> dao++ : save(<color red>book</color>) dao-- editor-- @enduml ]]] !Object Destruction We sometimes want to show when an object is destroyed, or at least no longer active. This is useful for showing when a form is no longer being displayed on the screen. If you have a main menu that creates other forms in response to the user clicking buttons, then destroying one of those other forms would imply that the user is back at the main menu again, and can longer interact with the destroyed form. <pre>@startuml ' use strict UML mode skinparam style strictuml actor "User" as user <mark style="background:lime">participant "MainMenu" as menu <<form>></mark> participant "BookEditor" as editor <<form>> participant "book : Book" as book <<domain>> <mark style="background:lime">'user clicks add new book button user -> menu++: click 'Add New Book' create editor menu -> editor : <<construct>></mark> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button create book editor -> book : <<construct>> ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book++ : setAuthor(author) book-- ' create a DAO create "BookListDAO" as dao <<DAO>> editor -> dao : <<construct>> ' save book editor -> dao++ : save(book) dao-- editor-- <mark style="background:lime">destroy editor</mark> @enduml </pre> [[plantuml[ @startuml ' use strict UML mode skinparam style strictuml actor "User" as user participant "MainMenu" as menu <<form>> participant "BookEditor" as editor <<form>> participant "book : Book" as book <<domain>> participant "BookListDAO" as dao <<DAO>> 'user clicks add new book button user -> menu++: click 'Add New Book' create editor menu -> editor : <<construct>> ' user enters book details and clicks the save book button user -> editor++ : enters book details editor-- user -> editor++ : clicks save button create book editor -> book : <<construct>> ' get the author from the relevant text component editor --> editor : getText() : author ' set the author field in the book editor -> book++ : setAuthor(author) book-- ' create a DAO create dao editor -> dao : <<construct>> ' save book editor -> dao++ : save(book) dao-- editor-- destroy editor @enduml ]]] !Level of Detail We don't want a one-to-one mapping between diagram elements and source code. That would produce a messy diagram that doesn't help us much. What we are aiming for is to see the most important bits of the system, particularly the interaction between the objects. It is a bit of a balancing act — too much detail results in a diagram that is effectively unreadable, and too little results in a diagram that is not a useful representation of the system. We want to show how the classes and methods that appear in the class diagrams are used to complete a particular use case. It is the interactions between the classes and the method calls that we want to see in a sequence diagram. If a programmer is given accurate domain and system model class diagrams, and a sequence diagram for a use case, then there should be just enough detail in the diagram to show the programmer how to use the classes in the class diagrams to implement the use case, and no more detail than that. Note: Normally we wouldn't bother showing getter and setter calls like we have in this tutorial. We wanted to keep it simple, and use something that you might have seen before if you have done some basic java programming.