Basics of meta modeling for domain models
In this section we describe typical meta modeling tasks. Meta modeling is the creation of a meta model. This defines what can be modeled in a model for that given meta model.
All aspects identified here can be found in a tutorial style in corresponding sections for TextX and Xtext of this documentation.
Introductory example
An example: A meta model for a programming language defines that, e.g., variables can be defined. The model, in turn, is a concrete program with many variable definitions.
A meta model may, thus, be sketched as follows:
A program (domain model) may look as follows:
Overview: aspects of meta modeling
A summary of different aspects to be specified by the meta model is given as follows. This list is inspired by the grammar based toolset Xtext and TextX.
- Which domain objects exist (glossary)?
- How are objects identified (named)?
- Which attributes do objects have?
- What objects are composed of other objects?
- What objects aggregate other objects?
- How do objects reference each other (including context effects/scoping)?
- How can I specialize objects?
- How can I connect objects?
- Modularization: How can an object reference another object from another model (form the same meta model or a different one)?
- Interoperability: How can an object reference something from outside the toolset scope (inter-tool operability)?
- Validation: How can custom rules be checked automatically?
Domain objects: identification and attributes
Domain objects represent a central part of a glossary. Thus, defining such objects is a central part of any software specification and must be using through its design.
Domain objects can represent things, like "Customers", "Computers", "State machines". In our context they can also represent activities and relationships, like "owns" (a customers owns a computer) or "runs" (a computer runs a state machine). Domain objects may have attributes, some of them optional. These attributes may have a scalar value or represent a list of entries. The value of the attributes can be specified to represent some basic type (like a string or a number) or other domain objects.
Importantly, some domain objects need to be identified by a name (like a "Customer"), while other objects do not (like the "Birthday" in our example below).
Note: Domain objects in the meta model represent a blueprint or a class of a concrete instances of such objects in a concrete model.
Composing objects
Domain objects may be composed of other domain objects. Such a relationship can be described by an attribute with a domain object type (like in the last section). An alternative representation is illustrated as follows, but describes exactly the same thing:
Note: in this example, a Customer is composed of a Birthday object. The Birthday object cannot exist without the Customer. This relationship is called composition and has clear ownership semantics.
References and Aggregation
Some domain objects need to reference identifiable objects without having their ownership. This happens, e.g., when describing domain object relationships within the model (e.g. a Customer owns a Computer; relationship "own"). Such relationships themselves can own additional attributes (e.g. "owns since date").
Note: non-owning knowledge of other objects is called aggregation. Simple relationships can be presented by a simple link (without attributes and without own rule/class definition).
Scoping
Scoping is relevant to describe what objects are identifiable when referencing other objects. This is especially of importance, when some default visibility is not valid (most default scoping mechanisms allow all identifiable objects to be referenced globally).
Assume the following meta model snippet, where a "Scenario" is composed of "Configurations" and a "Testcase" references "Scenarios" and "Configurations":
In this case, we want that only "Configurations" of the "Scenario" referenced by a "Testcase" are visible to the "Testcase". This restriction is context specific (to the context of the "Testcase" described by the referenced "Scenario"). Scoping mechanisms allow to define this scope.
Specialization (base classes/base rules)
Sometimes it happens that some domain object is too generic and needs to be specialized. This may happen when the language evolves. During the initial design commonalities are identified which lead to the same pattern (base class and specialization).
Modularization
This happens when a model is splitted in multiple submodels (e.g., different files).
Combining meta models
To foster modularization, meta models can be splitted and still allow to reference domain objects of one meta model from the other meta model. In our last example we could define a meta model for "Testcases" and one meta model for "Scenarios". This feature is more demanding to the underlying technology but allows a modularization of the meta model and, thus, the glossary.
Interoperability with other toolsets or software components
In larger projects external databases or models may need to be referenced. Such external sources of information may be, e.g., an existing database of requirements, some JSON or XML file or similar things. Interoperability with these sources of information allow to link the model to that source.
Validation
The validation of a model consists of additional checks on top of structural consistency defined by the grammar and scoping.
- Error in the structure result in classical syntax errors ("expected 'XY' instead of 'AB'").
- Scoping, in turn, defines the possible references in some context and, thus, yields errors of the category "referenced element 'XY' not found.".
- The validation described in this section is about additional logical checks, once the model is correctly parsed and all references resolved. This additional checks typically have a strong relation to the domain.
Example: Assume a model where "testcases" reference "configurations of scenarios" which have certain "aspects". On the other hand a "testcase" may need certain aspects. If any of the "Aspects" required by a "testcase" is not availabe in the referenced "configuration", a logical error is reported (validation error).
Rationale for choosing a validation over a scoping solution in this case: When modeling a situation where a "configuration" is chosen by a "testcase" without providing the correct "aspects", one would not like to get a "configuration not found", which would result if only "configurations" with matching "aspects" are defined in the scope of a "testcase". In contrast, the validation will allow all "configurations" of the selected "scenario" of a "testcase" to be visible, but some of them will produce a meaningful domain error, such as "configuration 'config_B' does not provide the aspect 'aspect_X' required by testcase 'test_T1'".
The structure defined in the meta model is shown as follows:
A model with validation error ("configuration 'config_B' does not provide the aspect 'aspect_X' required by testcase 'test_T1'") is shown as follows:
scenario scenario_001 { configuration config_A has {aspect_X} configuration config_B has {aspect_Y} } testcase test_T1 { use scenario_001 with config_B and needs {aspect_X} }
A model without validation error is shown as follows:
scenario scenario_001 { configuration config_A has {aspect_X} configuration config_B has {aspect_Y, aspect_X} } testcase test_T1 { use scenario_001 with config_B and needs {aspect_X} }