🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Constraints
This page was created by Alexandra on 2017-05-14. Last edited by Wikiadmin on 2026-07-29.

You can define class-level business rules as constraints in MDriven Designer and show users when an object does not meet those rules; this page is for modelers who need rules beyond association cardinality and state-machine guards.

What constraints do

A constraint is an OCL expression on a class that must evaluate to true. When it evaluates to false, the constraint is broken.

Use constraints for rules that apply to an object regardless of which ViewModel presents it. For example, a Car must have a brand:

self.BrandOfCar->notEmpty

When BrandOfCar has no associated object, this expression is false, so the constraint is broken.

Constraints complement, rather than replace, other model rules:

Rule mechanism What it controls Example
Association-end cardinality How many related objects are allowed or required. A 1..4 association end is broken when no related objects exist.
Class constraint A named OCL business rule on an object. A car must have a brand.
State-machine guard Whether a transition may be taken. Production may start only when the deposit is paid.
Delete constraint Whether an object may be deleted through MDriven's Delete operator. A car with a deposit may not be deleted unless it is scrapped.
Association-end business delete rule What must happen to related objects when an object is deleted. A brand may not be deleted while cars remain in its car association.

Create a class constraint

  1. Select the class in MDriven Designer. For example, select Car.
  2. In the Property Inspector, find Constraint and select ....
  3. Add a constraint.
  4. Enter an OCL expression that returns a Boolean value. The expression must return true when the object is valid.
  5. Give the constraint a meaningful name and write a user-facing description.
  6. Choose the error level: Information, Warning, or Error.
  7. Save the model and test the rule in the debugger or an AutoForm by changing data so that the expression becomes false and then true again.

For the Car example, use:

self.BrandOfCar->notEmpty

Use a description such as:

Cars MUST have a Brand!

Set its error level to Warning if users should be informed but may continue, or Error if the rule represents an error condition in the user interface. Use Information for a non-blocking informational rule.

Write constraint expressions

MDriven uses OCL (Object Constraint Language) to evaluate constraints. In an OCL expression, self is the object being checked.

Keep the expression focused on the rule and use the names from your model. For example:

Requirement Constraint expression Broken when
A car must have a brand. self.BrandOfCar->notEmpty No brand is associated with the car.
Production requires both a paid deposit and a brand. self.DepositPaid and self.TheBrandOfTheCar->notEmpty The deposit is not paid, the brand is missing, or both.

A constraint expression is evaluated against each object of its class. Do not write a constraint that describes a one-time screen action; use a ViewModel validation or an action rule when the rule belongs only to that interaction.

Make the message useful

The constraint description is the message associated with the rule. Write it so that a user can understand what to correct.

You can include string-representation information in a description with <asString>. Constraint descriptions also support <AsString:attributeX> to include the string representation of a named attribute. If the message needs navigation to another class or other complex logic, create a derived attribute for that value and reference the attribute from the description. See constraint descriptions and AsString placeholders.

For example, instead of a generic message such as Invalid car, describe the needed correction: Cars MUST have a Brand!.

Use delete constraints

A delete constraint is a class constraint that applies when MDriven executes the Delete operator for an object. Use it to document and enforce a rule that specifically governs deletion.

For example, the domain may forbid deletion of a Car while it has a deposit, unless the car is in the Scrapped state. Define that rule as a delete constraint on Car. When MDriven deletes the car through the Delete operator, it checks the delete constraint.

A delete constraint answers, “May this object be deleted?” It does not replace the business delete rules on association ends.

Configure association-end delete behavior

Business delete rules exist on all association ends. Decide the appropriate rule independently for each direction of an association.

For a Brand and Car association, you may decide:

  • Deleting a Brand is not acceptable while objects remain in AllCarsOfThisBrand. Set that association end to MustBeEmpty.
  • Deleting a Car while it has a brand association is acceptable. Set the association end in that direction to NeedNotBeEmptyNoWarning.

This distinction matters: one association can have different deletion requirements depending on which object is being deleted.

Present constraints in ViewModels

Constraints automatically appear in ViewModels. You can opt them out for an individual ViewModel when that ViewModel should not present them. See opting out actions and related ViewModel configuration.

Use the automatic presentation for general feedback. When a ViewModel needs a specific validation rule, connect it to the named class constraint rather than duplicating the OCL expression. ViewModel validations describes this pattern: look up the constraint by name and verify that it is not broken.

For a walkthrough of class constraints in ViewModel validation, see Documentation:Turnkey session 4: ViewModel validation.

Query constraint status in OCL

Use self.constraints when you need constraint metadata and current status in an OCL expression. It returns a collection of tuples with these values:

Value Meaning
Name The constraint name.
Description The constraint description.
IsDeleteConstraint Whether the constraint is a delete constraint.
ErrorLevel #Information, #Warning, or #Error.
Broken Whether the constraint is currently broken. The state is evaluated and subscribed.

For example, check that no Error-level constraint is broken:

self.constraints->select(c|(c.ErrorLevel = #Error) and c.Broken)->isEmpty

Return the messages for broken Warning-level constraints:

self.constraints->select(c|(c.ErrorLevel = #Warning) and c.Broken)->collect(c|c.Description)

You can use the returned values to filter, sort, or present constraint information in a ViewModel. Because the broken state is subscribed, a presentation based on it updates as the underlying constraint state changes.

Earlier versions returned an array of Boolean results from this operator. To reproduce the Boolean-style check, use the Broken property explicitly:

self.constraints->forAll(c|c.Broken=false)

For the complete operator definition and additional examples, see Documentation:OCLOperators constraints.

Reuse constraints as state-machine guards

When the same rule must be valid before several state transitions, define it once as a constraint and associate it with transitions through GuardConstraints. This avoids repeating the OCL expression and lets users see the constraint message that explains why a trigger is unavailable.

To associate constraints with a transition, right-click the transition in the state diagram and choose Edit GuardConstraints…. See Documentation:GuardConstraints for the procedure and behavior.

See also