Hello,
I am currently learning SysML v2 and working on a simple example system.
I have a question about how lists / collections should be modeled and handled in SysML v2.
For example, in my current model I have:
item def Address {
attribute street : String;
attribute city : String;
}
part def Customer {
//...
attribute savedAddresses : Address [*];
}
I have now reached the point where I need actions such as:
-
Add a new address to savedAddresses
-
Remove an existing address from savedAddresses
-
Possibly update an address later
At the moment, I am not sure what the proper or recommended way is to represent this behavior.
Should this be done through direct assignment/update inside actions, or is there a better modeling pattern for list operations in SysML v2?
Also, if there are any recommended resources, examples, or documentation that explain this topic, I would really appreciate it.
Any guidance or small examples would be greatly appreciated.
Thank you.
Short answer: assignment inside an action is an idiomatic way to express add/remove on a collection-valued feature, so what you’re thinking is great. Combine the assignment action (assign feature := expr) with the KerML sequence operators ->including(...) and ->excluding(...). The assignment semantics for a collection-valued feature are atomic — the whole new collection takes effect at the done snapshot of the action. See The SysML v2 Book (Weilkiens & Molnár) §26.6.1 (Assignment Action) for the semantics, and §30.2.2 (Sequence Functions) for the full menu of operators (including, includingAt, excluding, union, intersection, head, tail, subsequence, etc.). See is §85.14 if you want every detail.
Two small things to know:
-
The target of an assignment must be an occurrence — Customer needs to be a part def, not an attribute def. The book flags this in §26.6.1 (footnote).
-
->including / ->excluding return new sequences; the assignment is what binds the new value to the feature. So conceptually you’re saying “at done, savedAddresses is what it was at start, plus/minus this address,” not stepping through an in-place edit.
That’s the lightest-weight pattern. There are heavier options worth knowing about:
-
action def with in/out parameters — when the before/after collections flow through a larger action chain rather than belonging to a long-lived Customer.
-
State machines — a SysML v2 state machine lets you say what savedAddresses is allowed to look like in each state of the customer’s life, and how it can change when the customer transitions from one state to the next. For example, if a suspended customer can’t add addresses, but an active one can. The SysML v2 Book Chapter 28, especially §28.4 (Exhibiting States).
-
Item / succession flows — model addresses as items flowing into and out of the customer along typed edges, when where addresses come from and go to is part of the design.
Is Customer long-lived in your model with savedAddresses evolving across snapshots, or are you transforming customer values? And does the lifecycle constrain when addresses can be added/removed?
For wider reading on SysML v2, the community keeps a curated list here: Useful SysML v2 Resources
Thank you very much for the detailed explanation and the references, I really appreciate it. This was very helpful.
To clarify the context of my example: I am building a use case model for a simple Online Food Delivery System, where the customer is a long-lived part in the system context, and savedAddresses is intended to evolve over time across snapshots.
I updated my example and would like to ask about the whole use case flow, to make sure I am using the right direction for a use case model.
This is my current structure:
part def LoggedInUser :> User {
attribute name : String;
attribute email : String;
attribute password : String;
attribute phoneNumber : String;
attribute savedAddresses : Address [*];
}
// ...
part def SystemContext {
part mySystem : 'Online Food Delivery System';
part myCustomer : LoggedInUser;
// ...
use case manageProfile : ManageProfile {
subject :>> system = mySystem;
actor :>> customer = myCustomer;
attribute choice : String;
action updateName {
in name;
assign customer.name := name;
}
action updateEmail {
in email;
assign customer.email := email;
}
action updatePassword {
in password;
assign customer.password := password;
}
action updatePhoneNumber {
in phoneNumber;
assign customer.phoneNumber := phoneNumber;
}
action addAddress {
in newAddress : Address;
assign customer.savedAddresses :=
customer.savedAddresses->including(newAddress);
}
action removeAddress {
in addressToRemove : Address;
assign customer.savedAddresses :=
customer.savedAddresses->excluding(addressToRemove);
}
first start;
then action selectProfileManagement;
then merge loopStart;
then action operationChoice {
in userChoice;
assign choice := userChoice;
}
then decide;
if choice == "update name" then updateName;
if choice == "update email" then updateEmail;
if choice == "update password" then updatePassword;
if choice == "update phone number" then updatePhoneNumber;
if choice == "add address" then addAddress;
if choice == "remove address" then removeAddress;
if choice == "exit" then exitPoint;
then loopStart;
then merge exitPoint;
then action exitProfileManagement;
then done;
}
}
My questions are:
-
For the list updates, am I now using the correct pattern based on your explanation?
-
For updating fields such as name, email, choice, etc., is assign the correct choice here, or should I use bind instead?
Thank you again for your help.
Hi Hadeel,
Yes on both.
The ->including / ->excluding pattern is right. You’ll need private import SequenceFunctions::*; (or import the two functions directly) for those operators to resolve — they live in the Kernel Function Library, not under Collections.
For the scalar fields, assign is what you want. A binding connector (bind) asserts that two features are equal across every snapshot of the model — a static structural constraint. bind customer.name = name would constrain customer.name to be equal to the updateName action’s input parameter for all time, which isn’t the semantics you mean. An assignment action, by contrast, asserts that once the action completes, the referent feature has the new assigned value on the target occurrence (§8.3.17.5) — equality from the completion of that action onward, not across all snapshots. That’s the right shape for name, email, password, phoneNumber, choice, and the savedAddresses updates alike.
One side note: attribute savedAddresses : Address [*] violates §8.3.7.3 (validateAttributeUsageFeatures — an AttributeUsage’s features must all be non-composite, and Address as an item def brings in composite features); change it to ref item savedAddresses : Address [*]. The just-released SySIDE 0.9.0 flags this; earlier versions let it through.
Adam Layne, PhD