You can use derived attributes to calculate values such as a bowl's actual contents weight from related objects, without storing a second copy of the value; this tutorial is for MDriven Designer users learning OCL.
What you will build
This third OCL tutorial develops a fruit-bowl example in which a fruit can be used in more than one bowl. You will model the proportion of a fruit used by each bowl and derive values from that proportion.
For example, a 200-gram apple may contribute 50% of its weight to one bowl. Its contribution to that bowl is 100 grams. The bowl's contents weight is the sum of all such contributions.
Watch the derivation-properties walkthrough alongside this page.
Derivation properties
A derived attribute is an attribute whose value is calculated by an OCL expression from the current model data. Use it when the value can be determined from other values and relationships.
In this example:
| Derived value | Meaning | Example |
|---|---|---|
| Fruit usage percentage | The total proportion of a fruit allocated across its bowl parts. | If a fruit is 50% in Bowl A and 60% in Bowl B, its usage is 110%. |
| Actual part weight | The weight contributed by one FruitPart. | A 200-gram fruit at 50% contributes 100 grams. |
| Bowl contents weight | The sum of the actual weights of all FruitParts in the bowl. | A bowl containing contributions of 100 grams and 75 grams weighs 175 grams. |
Derived values are queries: evaluating them must not change model data. For the distinction between OCL queries and data-changing logic, see Learn OCL. For the broader places where MDriven uses OCL, see OCL Expressions.
Model the percentage on an association class
Originally, a fruit may have a direct link to one FruitBowl. When the requirement changes so that a fruit can be in multiple bowls, the relationship must carry information about each individual placement.
Create an association class named FruitPart for the relationship between Fruit and FruitBowl. Add a percentage attribute to FruitPart.
Each FruitPart represents one statement such as: âthis fruit contributes 50% to this bowl.â The percentage belongs on FruitPart, not on Fruit or FruitBowl, because it describes that particular relationship.
| Object | Responsibility in the example |
|---|---|
Fruit
|
Holds the whole-fruit weight and links to its FruitParts. |
FruitBowl
|
Holds the FruitParts that make up its contents. |
FruitPart
|
Connects one fruit and one bowl and holds the percentage used in that bowl. |
Gotcha: changing cardinality and introducing an association class changes the model structure. In the walkthrough, existing test data is no longer available after this change, so the example data is entered again before checking the new derivations.
Derive how much of a fruit is used
Add a derived attribute on Fruit that sums the percentages of its related FruitParts.
The derivation navigates from the current fruit to its FruitParts, selects each part's percentage, and sums the values. Conceptually:
usage percentage = sum of percentage on every FruitPart for this Fruit
Use this value to identify fruit that has been allocated beyond its whole amount. For example, if the calculated usage percentage is greater than 100, the fruit is overused and the application can warn the user.
This is an example of navigating a collection and aggregating a value. Review Part 2 OCL: Operators and OCL operators for the collection and operator concepts used by such expressions.
Derive the actual weight of each FruitPart
The bowl must not add the full weight of every linked fruit. It must add the proportional weight for each FruitPart.
On FruitPart, add a derived attribute for the actual weight. Its calculation is:
actual part weight = (percentage / 100) Ă linked Fruit weight
For example, if the linked fruit weighs 200 and the FruitPart percentage is 50, the actual part weight is 100.
The derivation follows the single link from FruitPart back to its Fruit to read the fruit's weight. In the walkthrough, the calculation is converted to Decimal before converting the result to Int32, because the percentage calculation produces a fractional numeric result while the target weight attribute is Int32.
Gotcha: make the conversion explicit when the derived attribute's type differs from the calculation's result type. A percentage division can produce a decimal value even when the stored source weights are integers.
Derive the bowl's contents weight
Once every FruitPart derives its own actual weight, the FruitBowl derivation becomes smaller and easier to maintain: sum the actual weight of its FruitParts.
bowl contents weight = sum of actual part weight on every FruitPart in this FruitBowl
For example:
- FruitPart 1: a 200-gram fruit at 50% contributes 100 grams.
- FruitPart 2: a 150-gram fruit at 50% contributes 75 grams.
- The FruitBowl contents weight is 175 grams.
This decomposition avoids repeating the percentage calculation in the bowl derivation. Put the calculation at the level where its meaning belongs: the contribution of one FruitPart.
Show useful derived information
A presentation expression can show the fruit type and the amount contributed by a FruitPart, helping you inspect the result in the debugger.
When building such an expression:
- Navigate from the FruitPart to its linked Fruit to obtain the fruit's type or weight.
- Include
selfwhen needed to make clear that navigation starts from the current FruitPart. - Convert numeric values to a string before concatenating them with text.
Gotcha: an Int32 value cannot be concatenated directly with a string in a presentation expression. Convert the numeric value to a string first.
Check the result in the debugger
After you save and reload the model, inspect the FruitBowl and FruitPart values in the MDriven Debugger.
- Create or update test FruitParts with known percentages.
- Check each derived actual part weight against the formula: percentage divided by 100, multiplied by the linked fruit's weight.
- Check that the FruitBowl contents weight equals the sum of those part weights.
- Check each Fruit's derived usage percentage. Any result greater than 100 identifies an overused fruit.
Use small, predictable values during testing. For example, a 100-gram fruit at 25% should contribute 25 grams, which makes incorrect navigation or type conversion easy to spot.
When to use this pattern
Use an association class with derived properties when a relationship has its own business data and calculations. In this example, the relationship between fruit and bowl has a percentage and a calculated contribution weight.
You can also derive association ends. If inherited classes require different derivations, see Derivation expressions. Be aware that derived values have database-related limitations described in Derivation is not available in the database.
