Requirement tracking language
This cookbook will guide you through the Requirement tracking sample project. This sample projects implements language-agnostic requirement tracking. Along the way it illustrates several useful language constructs:
Node attributes to annotate nodes of different languages
Multiple editors (presentations) per concept and switching between them with editor hints
Programmatic access to the selected editor hints as well as programmatic selection of an editor
Reference scoping to avoid repetition in collections of references
The Requirement tracking sample project comes bundled with MPS, so you'll find it among the other sample projects in your home directory.
Most of software as well as other project start with requirement gathering. During this phase the client specifies the desired functionality of the system that should be built. The specification is then used by the developers to lead their decisions during the implementation phase. Typically the specification is written in some form of textual documents, while software is delivered as code. This approach suffers from several limitations:
Tracking which piece of code implements which requirements becomes tedious manual work with high probability of errors.
Answering questions like "Which requirement mandates a particular piece of code" or "Where in code is a particular requirement implemented" is not instant and automated.
Analysis of impact of individual requirements on software modules is not trivial.
When a requirement changes, listing all impacted pieces of code is not reliable.
The Requirement Tracking sample illustrates a possible automated solution to requirement tracking, which handles all the listed deficiencies of manual tracking.
Code, be it XML, Java or any other MPS language, is annotated with requirement traces - brief summaries of the requirements implemented by that particular piece of code. The requirement traces can be attached to nodes on any granularity level - to a class, method or a statement, for example.
The requirement traces can be added, edited and removed at will.
Intentions are utilised to add/remove requirement traces to nodes.
Since the requirements have not been written in some text editor external to MPS, but in MPS using a language designed specifically for writing requirements, the standard Go To Declaration Ctrl+Space action will open the referenced requirement in the editor and the user can quickly navigate to the full description of the requirement.
Show Usages Alt+F7 for a particular requirement will bring up a list of all places in code, from where the requirement is referred to with a requirement trace:
The requirement traces can be made visible or hidden through the standard MPS mechanism for handling multiple projections/editors - editor hints:
When the ShowTraces hint is not selected, no requirement traces are shown to the user.
Specifications are written in MPS, so that they are well structured and referencable from code. They can be generated into plain text documents. If additional generators are provided, the specification could be generated into PDF or other text formats.
Requirement traces refer to the particular entries in the specification, show a summary of the referred requirement entry and allow navigation.
Any node in any language can have requirement traces attached - BaseLanguage and XML were two example languages given, but any DSL code could be annotated just as well, e.g. Kaja.
The RequirementDefinitions languages enables users to write their requirements/specifications in MPS. A simple TextGen defined in that language generates plain text files containing the requirements.
The Specification solution is an example of requirements specification. The requirements are organized into models by their respective concerned sub-systems.
The ProjectCode solution simulates the actual code of a project that must conform to the specification contained in the Specification solution. The code is organized by functionality into models. Each model imports the relevant specification models from the Specification solution. The code, both Java and XML is annotated with requirement traces. The traces are only visible, when the ShowTraces editor hint is pushed. With intentions additional traces can be added or removed.
The Traces languages defines an attribute that can be attached to any node (BaseConcept). The attribute holds references to the requirement entries in the requirement specifications. Two editors are available - a default one, which only shows the original code, and a "ShowTraces" one, which displays the requirement traces next to the code. "Push hints" can be used to switch between the two editors. An intention is available to attach/detach the attribute to nodes. When the RequirementTrace attribute is being added through the intention to a node, the "ShowTraces" editor hint is selected programmatically, so that the user can instantly see the requirement traces in the code. Multiple traces can be specified for an attribute. Scoping for RequirementEntryReference ensures that the user cannot enter a specific trace multiple times for the same attribute.
This language must be imported by solutions that should contain requirement specifications. The language introduces two concepts with editors and textgen.
The Entry concept uses the jetbrains.mps.lang.text language to allow free text editing in the description part. Custom presentation is defined for Entry to accommodate for the optional reference id value, which may be absent.
This solution uses the RequirementDefinition language to define requirements for a hypothetical system. The requirements are split into two models:
coreRequirements - to specify the business logic of the future system
uiRequirements - to specify the user interface of the application
Within each model multiple specification documents can be created.
Each document contains a collection of requirement entries, each of which has a name, description and an optional reference id.
The specification models have to import at least two languages - jetbrains.mps.samples.requirementTracking.RequirementDefinition and jetbrains.mps.lang.text.
The ProjectCode solution contains the actual implementation of the system. The project consists of three models, each of them hypothetically implements a different part of the system.
On top of the languages used for development the models must import the Traces language in order to define requirement traces.
The Dependencies of the models must hold the models of the Specification solution, the requirements of which are relevant for code in the model. The persistence model, for example, depends on coreRequirements.
The ui model depends on uiRequirements.
This allows requirement traces to be inserted into code. An intention is available to add/remove traces to a node.
The traces can then be edited directly.
The Traces language glues together the specifications and code. It contains two concepts:
RequirementEntryReference - a smart reference to a single requirement document entry
RequirementTrace - a node attribute that can be attached to any node (BaseConcept) and holds a collection of RequirementEntryReferences.
The header of the RequirementTrace concept defines:
multiple: false - cardinality of the attribute is 0..1 (at most one can be attached to a node)
role: requirement trace - to access the attribute from code, "node.@requirement trace" will be used
attributed concept: BaseConcept - it can be applied to BaseConcept
RequirementTrace provides two editors:
The default editor only shows the attributed node, which makes the requirement traces invisible
The ShowTraces editor shows the traces next to the attributed node
The ToggleRequirementTrace intention not only adds/removes traces, but also activates the ShowTraces editor hint, when a trace is added, so that the traces become visible, if they were not prior to invoking the intention. This is a natural usability feature.
The RequirementEntryReference editor uses the customized presentation of Entry to optionally show the reference id. RequirementEntryReference implements scoping in a way that filters out the requirements already referred to from the same requirement trace.