A basic example

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()

Anonymous objects

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()

Stacking

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()

Message levels

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()

Constructor

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()

Destructor

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()

Automatic object

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()

Threads

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()

Returning instantly

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()

Signals

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()&

Notes

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()&

Reusing space

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()

User-defined colors

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

Actors

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

Another version with asynchronous messages

(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

The full example with all the wisecracks

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