Advent of SysML v2 | Lesson 22 – Requirements

Hello and welcome back to the Advent of SysML v2 – a daily, hands-on mini-course designed to bring you up to speed with the new SysML v2 standard and the modern Syside tooling that makes you productive from day one.

By the end of this lesson, you will:

  • Learn about modeling requirements
  • Learn how to specialize and decompose requirements

If you want to dive deeper into the world of SysML v2, check out The SysML v2 Book, where this topic is also discussed in more detail.

High-Level Requirements

Requirements in SysML v2 provide powerful mechanisms for modeling the various conditions that a system must satisfy. They are first-class modeling elements, completely integrated with other aspects of the language. Consequently, we can leverage everything you learned in the first week: requirements can be modeled with definitions and usage, can specialize each other, and can have virtually any kind of feature or parameter. This may be confusing at first, especially after the simplistic approach of SysML v1.

In this lesson, we will learn some useful patterns that exploit these capabilities and turn confusion into unprecedented expressivity.

1
2
3
4
5
6
7
8
9
package SantaSleighSpecification {
    part def SantaSleigh;
}
package UserRequirements {
    requirement def <UR1> DeliverGifts {
        subject sleigh : SantaSleighSpecification::SantaSleigh;
        doc /* Santa’s sleigh shall deliver gifts to all nice children. */
    }
}

Let us start simple. To model standalone requirements, it is best to use requirement definitions. As you already know, definitions do not need a context, and a requirement as a general “shall” statement is usually like that. In the example above, line 5 illustrates how to declare a requirement definition.

A requirement, at the very least, must have a name, an identifier, and a “shall” statement. According to the specification’s recommendations, we can use the declared name for the requirement name, the short name (enclosed in “< >”) for the identifier, and the “doc” comment for the shall statement. There are other ways, also discussed in The SysML v2 Book, and we will show some alternatives in the lesson as well.

Although this is already a requirement, the example takes it one step further. In line 6, we model a subject parameter that captures what the requirement is about (the subject before the “shall” in the requirement text). By declaring the definition for that parameter in line 2, we can immediately establish a link between the requirements and the root of our design.

It is important to note that a part definition does not necessarily satisfy a requirement just because it is the type of its subject. We just declare that this “shall” statement is about this element. We will see how to model satisfaction in the last lesson.

Requirement Specialization Instead Of Derivation

Once we have identified the high-level requirements in the problem space, we typically move to the solution space and begin decomposing our system into subsystems. As this happens, several requirements will be derived from the high-level ones by either concretizing them in accordance with design decisions or mapping them to subsystems. In SysML v1, probably the best way to capture this was the “deriveReqt” relationship. Although it is still available in v2 in a library, requirement specialization offers a significantly better approach in most cases.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package SantaSleighSpecification {
    part def SantaSleigh;
}
package UserRequirements {
    requirement def <UR1> DeliverGifts {
        subject sleigh : SantaSleighSpecification::SantaSleigh;
        doc /* Santa’s sleigh shall deliver gifts to all nice children. */
    }
}
package SantaSleighDesign {
    part def SantaSleigh specializes SantaSleighSpecification::SantaSleigh {
        // …
    }
}

package RequirementBreakdown {
    private import SantaSleighDesign::*;

    requirement def <TR1> DeliverGifts specializes UserRequirements::DeliverGifts {
        subject redefines sleigh : SantaSleigh;
        // …
    }
    // …
}

Observe line 19, where we declare a new requirement that specializes the first, high-level one. What does this mean exactly? With this specialization, we promise that every instance of this new requirement will also be a legal instance of the specialized one. What is a requirement instance? Good question. If you imagine a requirement model element as a logical statement with parameters (for example, the subject is a parameter), then an instance of that is a logical statement where the values of the parameters are fixed, and the whole statement can be evaluated to either true or false. 

Most of the time, a more special requirement will limit the set of values parameters can have, or strengthen the statement. In this case, the former happens when we redefine the subject in line 20 to be defined by the design version of Santa’s sleigh from line 11. Essentially, this new requirement is now about a more special kind of sleigh only.

This pattern can effectively support refinement-based modeling by refining the requirements in conjunction with the system design.

Subrequirements

The other typical thing to do for a more special requirement is adding more constraints by refining or elaborating the original “shall” statement with more subrequirements. In SysML v2, these are now modeled with actual composition rather than model-level containment, and we can even map the subrequirements to subsystems.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// …
package SantaSleighDesign {
    part def SantaSleigh specializes SantaSleighSpecification::SantaSleigh {
        part cockpit;
        part cargoBay : CargoBay;
        ref part santa;
        // …
    }
    abstract part def CargoBay {
        item payload [*] : Bag;
    }
    abstract item def Bag {
        item gifts [*];
    }
    // …
}

package RequirementBreakdown {
    private import SantaSleighDesign::*;

    requirement def <TR1> DeliverGifts specializes UserRequirements::DeliverGifts {
        subject redefines sleigh : SantaSleigh;

        requirement : CockpitForSanta; // subject is by default bound
                                       // to parent requirement’s subject
        requirement : CargoCapacity {
            // subject can also be a subcomponent
            subject :>> cargoBay = sleigh.cargoBay;
        }
    }

    requirement def <‘TR1.1> CockpitForSanta {
        subject sleigh : SantaSleigh;
        doc /* The sleigh must have a cockpit for Santa. */
    }

    requirement def <‘TR1.2> CargoCapacity {
        subject cargoBay : CargoBay;
        doc /* The cargo bay must be able to accommodate any number of gifts. */
    }
}

At this stage, we already know that Santa’s sleigh will have a cockpit and a cargo bay (further modeled with other part definitions), and it will be piloted by Santa (lines 4 to 6). We will refine the “DeliverGifts” requirement by adding two more requirements derived from it. Lines 31–34 and 36–39 capture the new requirements in two requirement definitions. The subject of “CockpitForSanta” is Santa’s sleigh, but “CargoCapacity” is about a “CargoBay”.

We will now model that the “DeliverGifts” requirement can be satisfied only if these two additional requirements are also met. To achieve this, we add two requirement usages to “DeliverGifts”. 

In line 24, we declare an unnamed requirement usage typed by the requirement definition “CockpitForSanta”. The subject of subrequirements is, by default, the same as the subject of the parent requirement. This means that when evaluating “DeliverGifts” on a concrete sleigh, the subrequirement will be evaluated on the same sleigh. 

In contrast, line 27 shows how to manually redefine the subject for this context, and we use this to set it to the sleigh’s cargo bay. Consequently, when evaluating “DeliverGifts” on a given sleigh, the “CargoCapacity” requirement will be evaluated on the cargo bay of that specific sleigh.

With this pattern, we can either decompose a complex requirement into simpler ones or specify a system requirement in terms of subsystems.

Challenge for Tomorrow

Your challenge is to experiment with requirement decomposition and specialization. Head over to Syside Cloud and do the following tasks by extending the example model from the lesson.

  1. Create a new high-level requirement about the sleigh, requiring the capability to go into stealth mode.
  2. Specialize the requirement to the design model, and add two child requirements.
    1. The field generator subsystem shall generate a distortion field that bends light around the sleigh.
    2. The power subsystem must be able to power stealth mode for the entire trip.
  3. Add the corresponding subsystems to the sleigh design model. Decide and set the subjects of the subrequirements.

Summary

In this episode, you learned how powerful SysML v2 requirements are simply because they are a first-class citizen in the language. Next time, we will dive even deeper and see how to formalize requirements, which is a whole new level of power. It is now time to try it at Syside Cloud by doing the challenge. Don’t forget to come back tomorrow for another episode of the Advent of SysML v2!

Cookies

Learn SysML v2 through the Advent of SysML v2 Challenge!