3.6. Generalizations
A generalization is another kind of relationship you typically display on BDDs. This relationship conveys inheritance between two elements: a more generalized element, called the supertype, and a more specialized element, the subtype. You use generalizations to create classification trees (type hierarchies) in your system model.
The notation for a generalization is a solid line with a hollow, triangular arrowhead on the end of the supertype. This relationship is read in English as “is a type of” going from the subtype to the supertype. For example, the BDD in Figure 3.21 shows a generalization from the Gyroscope block to the Sensor block (among others). This relationship conveys that a gyroscope is a type of sensor.
Figure 3.21 Generalization relationships between blocks
When a supertype has more than one subtype shown on the same BDD, modelers often overlap the hollow, triangular arrowheads on the supertype end to conserve space on the diagram (as shown in Figure 3.21). Purists will tell you that overlapping the arrowheads actually conveys a special grouping of subtypes called a generalization set. This is a slightly more advanced feature of the language that you may find useful later. For now, feel free to overlap the arrowheads purely to enhance the readability of your diagrams.
One key point is that generalizations are transitive. The model displayed in Figure 3.21 shows that a star mapper is a type of star sensor, and a star sensor is a type of sensor. Therefore, a star mapper is a type of sensor. Type hierarchies in your model can be arbitrarily deep.
A generalization conveys that a subtype inherits all the features of its supertype: the structural features (properties) and the behavioral features (operations and receptions). In addition to the features it inherits, a subtype may have other features that its supertype doesn’t have. For this reason, modelers often refer to a subtype as a specialization of its supertype.
For example, the Star Sensor block is a specialization of the Sensor block. It inherits the four value properties and three operations from the Sensor block, and then it adds a fifth value property, resolution, that the Sensor block doesn’t have. Similarly, the Star Mapper block inherits the five value properties and three operations from the Star Sensor block, and then it adds two new value properties (hasAutonomousMode and maxNumStarsMapped), which neither of its supertypes have.
You create generalizations to define abstractions in your system design. A supertype (such as Sensor) is an abstraction of its subtypes; it factors out those features that are common among the subtypes. Abstractions let you define a common feature (such as the initialize operation) in one place within the model—in the supertype—and that common feature propagates down the type hierarchy to all the subtypes. Then, if you later need to change that common feature, you simply go back to that one place in the model to make the change, and all sub-types in the model get updated instantly.
Abstraction is a powerful design principle; it conveys substitutability, meaning that a subtype will be accepted wherever its supertype is required. For example, Figure 3.22 shows that the Flight Computer block has a reference property named sensorArray of type Sensor. This model conveys that a flight computer may need access to one or more of the features—structural or behavioral—that are common to all sensors. Therefore, any of the five subtypes of Sensor would be acceptable to a flight computer, because all of them inherit those common features from their supertype, Sensor.
Figure 3.22 Designing to an abstraction
This is an example of designing to an abstraction. This practice creates extensibility in your design. When the customers’ requirements change later in the life cycle and you need to add a new type of sensor to the satellite design, you can simply define a new subtype of the Sensor block within the system model, and that addition will be transparent to all clients (such as Flight Computer) that reference the Sensor block. For all these reasons, building generalizations into your model can significantly reduce the time it takes to modify your system design as the life cycle progresses—and that capability directly translates into cost savings.