We are starting with a simple example, involving only two objects and a single message. A master object asks a servant object to execute a task. The servant finishes the task and answers "done".
The text starts with two lines declaring the objects (name of the object followed by : and the class name). The object declaration is terminated by an empty line. It follows the single message in the form: caller:answer=callee.message.
m:Master s:Servant m:done=s.executeTask()
Every object has to have its own name. They can however be declared anonymous [a], so their name will not appear on the diagram.
m:Master[a] s:Servant m:done=s.executeTask()
Now we assume that the servant object needs some information from the master in order to complete its task, so it makes a call back to the master, who is reached by the program flow for the second time then. This is represented by a second lifeline stacked upon the master's first lifeline.
m:Master[a] s:Servant d:Database m:done=s.executeTask() s:information=m.getSomeInformation() m:result=d.query()
In the previous example, right after the servant has asked the master for an information, the latter queries a database, presumably for finding the required information.
But the master could as well give the information instantly and query the database thereafter, for finding out something else. In this case the getSomeInformation() call must be terminated before the query is made. This can be achieved by a "[1]" behind the caller name, which means: terminate 1 level of execution in which the object is involved, then send the message.
m:Master[a] s:Servant d:Database m:done=s.executeTask() s:information=m.getSomeInformation() m[1]:result=d.query()
The servant might create a new object for completing his task. This new object must already be a part of the object section, with its name prefixed by "/". It appears on the diagram as soon as it receives a "new" message. It cannot receive other messages before that.
m:Master s:Servant /f:File m:done=s.executeTask() s:f.new()
Any object (not just newly created ones) can be explicitly removed from the diagram when it is no longer needed. This can be accomplished by a "destroy" message.
m:Master[a] s:Servant /f:File m:done=s.executeTask() s:f.new() s:f.save() s:f.destroy()
You can make Quick Sequence Diagram Editor find out on its own when an object is no longer needed, which means that it is not and will not be involved in an interaction anymore.
Objects with the "x" flag set are treated like this. They will be destroyed automatically.
m:Master[a] s:Servant /f:File[x] m:done=s.executeTask() s:f.new() s:f.save() m:s.destroy()
We might use a separate thread on which the servant completes his task, so the master can do something else instead of just waiting for the servant.
When in a message the caller is separated from the callee by ":>" and not just ":" (m:>s.executeTask() instead of m:s.executeTask) a new thread is created. The caller can now send other messages without interfering with the activity started by the callee.
m:Master s:Servant /f:File[x] d:Database m:>s.executeTask() s:f.new() m:d.query() s:f.save() s:m.done()
In the previous example, the master's call to the database seems to take a long time to complete. This is because the master does not start any other activity and there is no need for the call-flow to return to the master.
But often this is not intended, e. g. because the call to the database actually is performed very quickly. When you add & as a suffix to a message (m:d.query()&) the call-flow returns instantly to the caller.
m:Master s:Servant /f:File[x] d:Database m:>s.executeTask() s:f.new()& m:d.query()& s:f.save() s:m.done()
In the previous examples, the servant sends a done() message to the master in order to indicate that he has finished his task. It might seem inappropriate that, as a consequence of the done() message, the yellow thread's call-flow remains for some time at the master.
A combination of thread-creation and instant returning comes in handy here (s:>m.done()&). It results in an arrow indicating only a signal without actually creating a new call-flow or continuing an existing one.
m:Master s:Servant /f:File[x] d:Database m:>s.executeTask() s:f.new()& m:d.query()& s:f.save() s:>m.done()&
We can put notes on the diagram and associate them to lifelines or messages. A note is declared inside the message section, it starts with + or * followed by a unique number and the name of a lifeline and is terminated by + or * followed by the same number. For example:
+1 s1
This is a note to appear beside s1
+1
+ creates a note that consumes its own vertical space, whereas a note declared with * is just placed on the right side of the indicated lifeline without adding any space, which might lead to a collision.
Any note that is ever declared on a diagram can be associated to any number of lifelines and messages before or afterwards. An association to a lifeline is accomplished by the note number in parentheses followed by the lifeline name, for example
(1) s1
whereas an association to a message is made when the message is prefixed by the parenthised note number, for example
(3) s1:data=f.read()
m:Master s1:Servant[x] s2:Servant[x] /f:File[x] d:Database m:>s1.start() +1 s1 Starting the 1st thread +1 (1) s1 m:>s2.start() *2 s2 Starting the 2nd thread *2 +3 d This happens on the 1st thread +3 (3) s1:f.new +4 s1 This happens on the 2nd thread +4 (4)s2:result=d.query (3) s1:data=f.read() s2:>m.done()& s1:>m.done()&
When an object is destroyed or removed automatically, the column where its lifeline was displayed is no longer used, so it might be reused by objects that are created thereafter. This applies only to objects with the [v] variable flag set.
m:Master /s1:Servant[x] /s2:Servant[xv] /s3:NoReuseSpace /s4:Servant[v] /s5:Servant[v] m:s1.new() m:s1.executeTask() m:s2.new() m:s2.executeTask() m:s3.new() m:s3.executeTask() m:s3.destroy() m:s4.new() m:s5.new()
If you want to style arrows and texts with individual colors, e. g. for grouping them visually, you can insert a comment starting with #! before the messages you want to style.
The comment should read like a CSS block on a single line. The property "color" defines the color of the arrow and the text, whereas "background-color" defines the text's background color.
An empty comment (#!) resets your color settings, texts will be black, arrows will be colored normally.
a:A b:B c:C #!color:#00FF00;background-color:gray; a:b.green on gray #!color:orange; b:c.orange without background #!color:black;background-color:#FFFF00; c:a.black on yellow a:c.black on yellow again #! a[1]:_ a:b.default style
http://stackoverflow.com/questions/1850096/using-quick-sequence-diagram-editor-for-sequence-diagrams
When a new thread is started (and a message from an user always starts a new thread) it does not stop until it is explicitly stopped or until the diagram ends. E.g. atm:stop terminates the atm thread
here a first attempt (everything in multithreaded mode):
al:Actor bill:Actor atm:ATM[a] bank:Bank[a] al:atm.give me $10 atm:al has $3=bank.check al's account balance atm:al.you only have $3 atm:stop bill:atm.give me $20 atm:bill has $765=bank.check bill's account balance atm:yes I'm sure, bill has $765=bank.hmm are you sure? atm:bill.here's $20, now go away atm:great, he's a cool dude=bank.I just gave Bill $20
(arguably the messages should be asynchronous, since they are transmitted over the network. Anyway now all arrows look the same)
">" at the start of a message starts a new thread (all messages from users and processes start a new thread by default.)
"&" at the end means that the call returns immediately, and the new thread is not shown. you can use this to simulate sending messages to existing threads. (all messages TO users and processes always return immediately by default. )
al:Actor bill:Actor atm:ATM[a] bank:Bank[a] al:atm.give me $10 atm:>bank.check al's account balance bank:>atm.al has $3& bank:stop atm:al.you only have $3 atm:stop bill:atm.give me $20 atm:>bank.check bill's account balance bank:>atm.bill has $765& bank:stop atm:>bank.hmm are you sure? bank:>atm.yes I'm sure, bill has $765& bank:stop atm:bill.here's $20, now go away atm:>bank.I just gave Bill $20 bank:>atm.great, he's a cool dude& bank:stop
it is unclear from the example when exactly a thread in ATM should stop. ATM seems to be acting more like a user or process, not an object. So the example does not necessarily make sense
al:Actor bill:Actor atm:ATM[a] bank:Bank[a] al:atm.give me $10 atm:al has $3=bank.check al's account balance al:atm.what time is it atm:al.it's now atm:stop atm:al.stop bugging me atm:al.you only have $3 atm:bill.and don't you open your mouth bill:atm.who asked you?& atm:stop bill:atm.give me $20 al:atm.hey, I'm not finished!& atm:bill has $765=bank.check bill's account balance atm:yes I'm sure, bill has $765=bank.hmm are you sure? atm:bill.here's $20, now go away atm:great, he's a cool dude=bank.I just gave Bill $20 atm:_ atm:stop al:atm.what about my $10? atm:al.read my lips: you only have $3