Note: the following is adapted from notes I sent tutors in a previous year.
If, after reading this, you are in doubt about something, let me know - for
example, by asking on Piazza, where maybe another student might help before
I did!
- Expect a straight line state diagram that goes through states like
(start) Venue booked, Entertainer booked, Food booked, Deposit paid, Party
over (stop), each transition (except the one from the start marker to Venue
Booked, which happens on object creation, and should be left unlabelled)
triggered by an operation of Party, suitably named. Issues that may arise:
- from which state is it reasonable to do getTotalCost()? Obviously, doing
this should never cause a state change, so this will always trigger a
self-transition, but can we do it from the beginning or only after venue,
entertainer and food are booked? The answer is that this needs to be
discussed further with the customer; if we did it before booking,
presumbably it'd be an estimate of some kind; under what conditions can
costs change anyway?
- what argument types, if any, do these methods have? For example, do we
provide a single pay(x) method that records any payment, or is it only
possible to pay the entire deposit/balance with something else resposible
for checking amounts?
Object diagrams: make sure they know what these are (rectangles for
objects, labelled objectname:Classname underlined, giving values for
attributes e.g. date=10/12/12). Point is just to see associated objects
being created and linked to the Party object as the latter goes through its
lifecycle.
- This will depend on how they did (1), but if they have a general pay(x)
method used both for deposit and balance, it's likely they have this
problem as they didn't use conditions to ensure that the state change
happened only once the right amount had been paid. They could add
conditions [x = deposit] and [x = balance] on the transitions. They should
think about what should happen if pay(x) is called with an x that doesn't
satisfy that condition: will the object maintain a "total paid" field that
records this, and e.g. allows someone to pay more deposit and less balance?
Or will the object insist on being paid the right amount (in which case,
separate methods not taking an argument are probably better). What if too
much is paid?
- They can add a Cancelled state, and put Venue booked.... Deposit paid
inside a superstate (Being planned, perhaps); they they add a transition
from the outside of Being planned to Cancelled (event cancel()). What
happens then? There will be a transition from Cancelled to the stop state
but they should make sure that the right thing happens to the money (what
exactly that is will depend on answers to previous parts and probably also
on negotiation with customer). They'll want a transition from Deposit paid
to Party over (NB not from the whole superstate; a party being over is
different from it being cancelled). Students may wonder whether you can
have a transition from a substate of S direct to another state outside S;
you can. (Although it can be error-prone.)
- The complication is that they have to ensure that the transition to
Deposit paid doesn't happen until everything is booked (if they just
have a payDeposit() transition out of the concurrent superstate, they
may have trouble with this). They'll need to use a join bar to do
this, with a transition out of it into Deposit paid and two
transitions into it from the Food booked and Entertainer booked
states, both labelled with event payDeposit() (or whatever they're
using) - note that it is quite possible for one event to cause two
transitions in parallel regions, like this.
- We don't have any knowledge (at this stage) of a Party object
needing to send messages as part of its reaction to the messages it
receives. We could show, e.g., what happens to its "amount paid"
variable if it has one using actions. E.g., we could have a transition
labelled pay(x)/amountPaid += x (using Java etc. syntax; I'm not
covering the action language).
Note on a good question that arose in a tutorial one year
A tutor
wrote to me:
Some students showed me today in their state diagram
an event on the transition going from the last state to the stop marker,
i.e. they had cancel() on the transition and then the stop marker, and I
was not sure whether this is accepted notation. As far as I understood, the
stop marker means that the object is destroyed or garbage collected- would
it therefore be acceptable to have a message leading to this? I could not
find a convincing statement about this in the documentation.
The
stop marker, like the start marker, is technically a pseudostate; most of
what applies to states also applies to it, with some restrictions such as
(naturally) a pseudostate can't have entry or exit actions (there's nowhere
to write them anyway :-)
In fact Fig 15.35 on p585 of the UML2.4.1 pdf,
which is one of the examples I used with them in class [that year], shows
this; this is inside a composite state, but Fig 15.41 on p594 has an
example where the stop marker is outermost and is still reached by a
transition with a trigger.
(You might prefer to think of the stop
marker as meaning that the object is ready to be destroyed or
garbage collected, perhaps.)
The alternative is to have cancel()
leading to a normal state (Cancelled, maybe) and then to have a transition
without a trigger from that to the stop marker. That transition is
triggered by a "completion event", representing the completion of whatever
was going on inside the state Cancelled. If there is no entry action or
activity inside that state Cancelled, a completion event will be generated
immediately on entering the state (see p599 of the UML PDF), and that will
take control to the stop marker anyway. So the two solutions are
equivalent.
This page is maintained by
Perdita Stevens (
perdita@inf.ed.ac.uk
)