article
Use Case Modeling Patterns in SysML v2
- published =
- author = Tim Weilkiens

This post walks through four iterations of one SysML v2 use case. It is an example of a modeling approach from a simple use case via a use case with messages to a use case with actions.
The example is a delivery drone handing over a parcel. The drone hovers above the drop zone. The recipient enters a delivery code in an app, the drone verifies it and prompts the recipient, and the recipient requests the release of the parcel.
The iterations are:
- The first idea: subject, actor, objective. Nothing more.
- 2a: A first message: the actor sends a message to the subject, between named event occurrences.
- 2b: Message-owned events: the same semantics, but the events are the message’s own ends, so no names need to be invented.
- 3: Performed actions: the subject’s message ends become actions the system performs in the context of the use case.
The four iterations live side by side in one package so they can be compared. In a real model, it is one use case that evolves. The shared definitions are:
package DeliveryDroneUseCases {
part def <DD> DeliveryDrone {
action verifyRecipient;
action releaseParcel;
}
part def Recipient;
item def DeliveryCode;
item def HandoverPrompt;
item def ReleaseRequest;
// use case definitions of the iterations follow
}
The actions verifyRecipient and releaseParcel are needed only in iteration 3. In practice, they are discovered there and then added to the system of interest.
Iteration 1: The first idea
The first iteration captures only who is involved and why the use case exists. The subject is the system of interest, the actor is outside of it, and the objective states the goal in the stakeholders’ words.
use case def HandOverParcel1 {
subject drone : DeliveryDrone;
actor recipient : Recipient;
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
}
Figure 1: General View created with Cameo Systems Modeler
This is enough to agree on scope and naming. It says nothing yet about how the recipient and the drone interact. That is the question for the next workshop.
Iteration 2a: A first message between events
The second iteration adds the first message: the recipient transmits the delivery code to the drone. This is the beginning of a sequential communication, and it is the part that can be elaborated very well in a workshop with stakeholders: “And then? What does the drone answer?”
use case def HandOverParcel2a {
subject drone : DeliveryDrone {
event occurrence deliveryCodeReceived;
}
actor recipient : Recipient {
event occurrence deliveryCodeSent;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode
from recipient.deliveryCodeSent to drone.deliveryCodeReceived;
}
Figure 2: Sequence View created with AI
The important detail: the message ends are event occurrences, not the actor and the subject themselves. The ends of a message are events (similar to UML and SysML v1). A part has events: its creation and termination. With from recipient to drone, the message would be sent when the recipient ceases to exist and received when the drone comes into existence. That is nonsense, at least in most cases. The event occurrences are the points in the lifetime of the actor and the subject where sending and receiving happen.
Iteration 2b: Let the message own its events
Iteration 2a has a small annoyance: every message needs two event names, and deliveryCodeSent and deliveryCodeReceived carry no information that the message name does not already carry. Iteration 2b is a variant with a different textual notation but the same meaning.
use case def HandOverParcel2b {
subject drone : DeliveryDrone {
event transmitDeliveryCode.targetEvent;
}
actor recipient : Recipient {
event transmitDeliveryCode.sourceEvent;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode;
}
The message is declared without from and to. Instead, the actor and the subject each declare an event that reference-subsets the message’s own source or target event. The semantics are the same as in 2a: the event in the recipient is where the message is sent, the event in the drone is where it is received. There is no need to invent names for the events anymore. The message name is the only name, and it is the one the stakeholders use.
Iteration 3: Message ends become performed actions
In the workshop, the conversation continues: the drone verifies the code, prompts the recipient, and releases the parcel on request. The drone does something in between the messages. Iteration 3 makes this explicit. The message ends in the subject are no longer events but actions the drone performs in the context of the use case. Successions between the messages define the order.
use case def HandOverParcel3 {
subject drone : DeliveryDrone {
perform action check ::> verifyRecipient;
perform action release ::> releaseParcel;
}
actor recipient : Recipient {
event occurrence deliveryCodeSent;
event occurrence releaseRequested;
event occurrence handoverPromptReceived;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode
from recipient.deliveryCodeSent to drone.check;
message promptHandover of HandoverPrompt
from drone.check to recipient.handoverPromptReceived;
message requestRelease of ReleaseRequest
from recipient.releaseRequested to drone.release;
first transmitDeliveryCode then promptHandover;
first promptHandover then requestRelease;
first start then drone.check;
first drone.check then drone.release;
first drone.release then done;
}
Figure 3: AI-generated view. It is based on the SysML v2 Sequence View, but the actions on the right lifeline are not part of SysML v2.
Three things change compared to iteration 2:
- The actions are owned by the system of interest.
verifyRecipientandreleaseParcelare defined inDeliveryDrone. The use case only references them withperform action … ::>. The use case describes how the system behaves in this context; it does not own the system’s behavior. - The semantics fit. A message is received at the start of its target occurrence and sent at the end of its source occurrence. With actions as ends, this is exactly what we want: when
transmitDeliveryCodeis received,checkstarts; whencheckends,promptHandoveris sent. - The actor still uses events. The recipient is outside the system of interest. We do not model its behavior, only the points where it sends and receives messages.
The successions first … then … define the order of the performed actions within the use case, from start to done. These successions implicitly also specify the order of the messages and make the successions between them obsolete, but we kept them to be more explicit. The messages and the successions together form a consistent picture: check must complete before release can start, and release starts only when requestRelease arrives.
Iteration 3 as an action flow view
The same use case definition can be shown in an action flow view. The sequence view emphasizes the communication between the recipient and the drone; the action flow view emphasizes the flow of performed actions inside the use case.
Figure 4: View created with AI based on a view created with Cameo Systems Modeler. The view is valid SysML v2. The AI has added the messages.
Both views show one model, not two. The successions are the solid arrows, the messages are the dashed arrows into and out of the performed actions. This is where the use case meets the functional architecture: the performed actions are references to actions of the system of interest, ready to be refined in the functional and logical architecture.
The complete model
package DeliveryDroneUseCases {
part def <DD> DeliveryDrone {
action verifyRecipient;
action releaseParcel;
}
part def Recipient;
item def DeliveryCode;
item def HandoverPrompt;
item def ReleaseRequest;
use case def HandOverParcel1 {
subject drone : DeliveryDrone;
actor recipient : Recipient;
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
}
use case def HandOverParcel2a {
subject drone : DeliveryDrone {
event occurrence deliveryCodeReceived;
}
actor recipient : Recipient {
event occurrence deliveryCodeSent;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode
from recipient.deliveryCodeSent to drone.deliveryCodeReceived;
}
use case def HandOverParcel2b {
subject drone : DeliveryDrone {
event transmitDeliveryCode.targetEvent;
}
actor recipient : Recipient {
event transmitDeliveryCode.sourceEvent;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode;
}
use case def HandOverParcel3 {
subject drone : DeliveryDrone {
perform action check ::> verifyRecipient;
perform action release ::> releaseParcel;
}
actor recipient : Recipient {
event occurrence deliveryCodeSent;
event occurrence releaseRequested;
event occurrence handoverPromptReceived;
}
objective {
doc /* The recipient receives the parcel at the drop zone,
* and only the authorized recipient can release it. */
}
message transmitDeliveryCode of DeliveryCode
from recipient.deliveryCodeSent to drone.check;
message promptHandover of HandoverPrompt
from drone.check to recipient.handoverPromptReceived;
message requestRelease of ReleaseRequest
from recipient.releaseRequested to drone.release;
first start then drone.check;
first drone.check then drone.release;
first drone.release then done;
}
}




