This page describes a proposal that should lead to an improvement for documenting requirements that is independent from any standard, and therefore can be mapped to all HL7 product families by aggregating the affected concepts (pre-coordinated) accordingly. It is still under development/improvement and seeks feedback.
- working with data exchange standards is based on using profiles
- for implementation reasons profiles should be organized in hierarchies so that only the differences must be specified and maintained
- maintaining dedicated profile hierarchies, separated by use cases, is a tedious task
- basic hierarchic structure and associated requirements are in principle the same for all data exchange standards
- support can be inherited (cascading down the tree) to simplify profiling
- "supporting" conditions only makes sense in combination of affected elements
- dedicated profile hierarchies can be created from a simplified specification (process) that aggregates requirements (as requirements collectors)
- these set of requirements should be defined according to intended use case actors, and can be generated then
- for testing purposes, only real requirementsmarked with "SHALL" or "SHALL NOT" are testable. "SHOULD (NOT)" can only be useful for architectural decisions are application designers, but are not good for testing.
- use of vocabulary is a different story (and not part of this analysis/proposal) (however, we hope that the same "semantic" data elements will use the same vocabulary regardless of HL7 product family)
Table of Content
Data exchange standards offer a extensive set of options and flexibility for its use. The less optionality and the more the specificity, the smaller is the overall acceptance of such a standard for a general purpose use. Therefore, a reasonable set of freedom and optionality is key. Consequently, this kind of flexibility requires use-case specific constraints, that have to be added to the core framework. The two important conformance constructs are optionality/required/mustSupportand cardinality/repetitions - depending on how the are named in the different product families. This proposal concentrates on the former because it is the anchor to add more constraints or further clarifications.
Note: The terms "implementation requirement" and "development requirement" are synonym as they refer to the requirements that must be fulfilled when developing an interface. Furthermore, the terms "operational requirement" and "runtime requirement" are also synonyms as they express expectations respectively specific behavior that may occur when running the interfaces against a peer.
Working with Profiles
Profiles are normally created to allow for validation.If a profile contains too many requirements or tries to cover different aspectsthey cannot directly be used for this purpose because the relevant details are hidden in the textual description. Therefore a solution should be described that allows for a better formalization of those textual requirements.A solution to that problem is to organize the profile in hierarchies.That helps to combine requirements that are common and to add more requirements for more specific purposes. This is a design principle (with differentials and snapshots) for FHIR, originating from v2 experience, but also used in form of templates with CDA.
The current process to create profiles is done according to the following diagram:
Profiles are created in combination with the definition of implementation guides. They are created as a set and designed for direct use. Therefore, the profiles are taken as a set for development, testing, certification and maybe other purposes. IGs are also a good point where actors can be defined in combination with associated data in form of modules.
An upcoming question is whether the profiles are created dedicated enough to fulfill the necessary requirements. Most probably they are not. In FHIR the mustSupport flag is used as an indicator that there are more requirements to be considered. Unfortunately, the associated requirements are hidden in natural language text. The requirements may be different for each of those elements/attributes. (Grahame's analysis has shown that the overall set of requirements is the same, but in different combinations.) The text also denotes when a resource/attribute is mandatory for a certain use case, e.g. only for the sender or recipient. But the detection and correct realization is then depending on the correct understanding of the implementation guide.
This page proposes a change in the process and the way the requirements are specified. The problem is that creating a proper hierarchy of dedicated profiles is too tedious so that they are not directly created. In addition, the maintenance process makes it difficult to track and identify the correct place where a specific requirement should be placed in the hierarchy.
Separating Editing and Usage (Validation, ..)
The target is to create a solution that supports editing only a very limited set of profiles, but in way that a hierarchy can be generated:
Within the new proposed process, the profiles are in principle defined as "abstract", they should not be used directly.They are created on a higher level so that a differentiation is not achieved immediately, but by generating a more detailed set afterwards. The idea is to define sets of requirements/obligations (aka "modules") that are then taken as input for a generation process that will generate profile hierarchies according to requirements per use-case-specific actors. Therefore, a mechanism must be provided that helps in creating that hierarchy.
The following requirements are taken from the introduction and should be addressed by this proposal:
- Edit single/simple profiles
- add tags/markups to mustSupport for further clarification
- enerate individual profiles (in a hierarchy) that can be used for specific validation etc.
- Specify activities as a hierarchy to be performed
- Aggregate requirements and make them machine readable
- Manage expectations about data content
We need to find a way that simple markups or tags can be used to introduce that there are some requirements for a certain element.
But the individual requirements may vary according to whom is using it.
The indication that there are some requirements can be best documented by introducing "modules", e.g. "basic patient demographics", "enhanced demographics", "insurance" etc. These "modules" collect and aggregate the elements which are relevant for that module. On the other hand "actors" will use the modules. The relationship to those modules is then used to introduce specific requirements in the sense of an activity and an expectation for the data. For example, a "simple patient creator" will only "send" for those elements/attributes, that are marked with that module. A "consumer" on the other side may be requested to "store" the information "exact" or in a "modified way". (A separation for different data expectations may be covered by different modules then.
The prvious drawing provides an example. When creating/writing profiles in combination with implementation guides, an IG writer has different use cases in mind. Or at least tries to consider the use of one item, a profile for one resource, to be used in different instantiations. Such an instantiation is in principle the application of certain requirements from different perspectives. For example, one would like to specify for an attribute that a sender must always provide the value, whereas a general recipient should only process it. In a derived use case, the same writer would like to add that the first consumer shall store it, whereas a second should also present it to the user in addition to store it.
Such a maintenance process seems to be much easier than separating the different views immediately into distinct profiles. The following details on this page elaborates a little bit further on the necessary details.
Adding constraints for development and implementation results in dedicated profiles. For HL7 product families these are message, segment, document, section, entry and resource profiles, sometimes also called templates.
This process is usually done on different aspects:
- profiles for key structures (segments, sections, resources, messages, documents, etc.) as far as they are specified within the standard
- implementation guides aggregating that together with additional information
For the process proposed here two more aspects must be realized:
- requirement collectors - "modules" - to mark responsibilities to simplify specifications
- actors to aggregate responsibilities with references to modules to verify implementations
Assigning to Items
There are two options to combine an item with a (set of ) requirement(s):
Option 1 lets an item point to an actor (or set of actors). The actor itself hides the requirements/obligations that are associated.
Option 2 lets an item point to an obligation set that itself is part of an actor.
Perhaps an example may help:
|Use Case||Demographic Consumption||Bracelet||Spiritual Leader|
|Activity||to be stored||to be printed||to be displayed||to be printed||sent/forward|
|.id||SHALL exactly||SHOULD equivalent||SHOULD equivalent||SHALL equivalent|
|.name||SHALL exactly||SHOULD equivalent||SHOULD||SHALL||SHOULD equivalent|
|.dob||SHALL exactly||SHOULD equivalent||SHOULD equivalent||SHALL equivalent|
Notes for the bracelet printer:
- the bracelet printer shall print a bracelet, but it has to print the family name exactly, whereas a modification for the given name is allowed. That opens the discussion to whether the modification is a requirement, or just allowed so that the exact printing of the name is possible as well, in order to separate that from a requirement where a modification must be performed.
- the bracelet printer shall select a current name. This requirement is currently not contained in the table above.
The interface requirement is the superset, i.e. the sender has to support all, whereas for a receiver it may depend on the role.
The example would be established following according to the previous two options:
Taking the two examples from above, assigning obligation sets to elements/items seem to be the more reasonable approach because it
- looks simpler - and nicer
- will be easier to maintain
- enforces less changes
Both examples do not consider the details for the bracelet printer. That comes next.
What is a good/reasonable example for actor hierarchies?
Can aggregations play the same role?
Target is to generate profile hierarchies.
Following some more detailed examples are presented that alter the requirements a little bit:
Example 2 tries to separate requirements/obligations for different actors. The point of interest is with separating the items so that the correct ones are addressed. The following example does not cover all the details from the above requirements table:
Example 3 tries to separate further that the bracelet printer actor should not use the name at birth, but one of the other two. This is done be introducing a grouping element:
In example 4 this separation is done by deriving a another profile (Patient2, name2) that constrains the use of name-at-birth (in red):
Options for Enhancements
FHIR R5 Resources
Currently, FHIR R5 provides the following elements including the links/references to each other:
Common to all Options
All following options assume/provide the following:
- The current situation from FHIR r5 is enhanced as far as possible.
- Obligation set is a resource that can be individually instantiated. There, it has an identifier for identification.
- The "code" attribute is outsourced into obligation details, thus providing the conformance verb (requirement level), activity and data expectation.
- To be considered: the obligation set can be included in the structure definition.
Option 1: Element Definition points to Obligation Sets
The obligation set is referenced from the element definition in a profile. Therefore, the profiles require an update if the associated obligations are changed.
Option 2: Link between Obligation Sets and Element Definition
A separate link allows for updating the association of obligations without changing the profiles or obligation sets.
Option 3: Obligation Set references Element Definition
The obligation set points to the element definition. This way the profiles do not receive an update.
Option 4: ??
Perhaps there are more/other options to consider. Proposals are welcome.
Functional and Data Requirements
As the bracelet printer use case from above demonstrates, functional requirements like to print something is tightly bound to the corresponding data, what is the data that I shall print? Therefore, both must be considered together in a specific use case.
Simplified Examples from IHE use cases
Following a set of (simplified) examples from IHE workflows should help to analyze further with regard to combine functional requirements with the corresponding data. The details demonstrate that the functional requirements may be bound to different data elements:
Patient Demographics Management (Query)
|Data Source||Data Manager||Data Consumer|
Order Entry Workflow
|Order Placer||Order Filler||Order Tracker||Order Results|
The current obligation extension is to be used within a profile. It combines the details into a single code be pre-coordinating the requirement level (SHALL, SHOULD, ..) with the activity (can-send, will-send ..).
The terms can-send (a sender has the capability but is not obliged to really send something) and will-send (sender will send if data is available) are mixing different kind of aspects. In principle they are stating the same, but under different conditions: The first documents a capability, whereas the second reflects the real behavior. In principle, that are two different type of profiles. Therefore, that should be represented by inheritance: What are the items (attributes) an application supports in general, and what are the ones that are counting in an implementation.
Requirements (or obligations) are defined by combining three elements that should be used in combination:
- conformance verbs
- data expectation
One aspect is the use of conformance verbs "SHALL", "SHOULD", "MAY" etc. These allow for more flexibility for implementation guides to simply give guidance for the strength of what is to be implemented. However, only "SHALL" (and "SHALL NOT") are something testable. A "SHOULD" can be tested in context-based scenarios (providing the context), where the system is provided the content to use for the "Should" to demonstrate that it can support the element as described in the IG, but it is not testable in context-free (or during production):
The use of those verbs may be confusing if applied for requirements and developments: "SHALL" designate a requirement that must be fulfilled by developers. It is used for constrainable profiles. What a developer has realized in the end, would better be expressed by "CAN", "HAVE" or "WILL". To simplify maintenance and documentation, and because those terms are in principle equivalent, only the term "SHALL" is used. The same applies in a similar way to the negation. A term like "HAVE NOT" also clearly indicates that during runtime no instance data will occur. Therefore, the cardinality for runtime is "0" (for implementable profiles).
In derived profiles the verbs can be constrained as following:
Following actions (obligations/requirements) can be defined. The list has been created based on experience, other proposals (Grahame's) and the EHR Functional Requirement specification:
From a high-level perspective they are separated into the following categories (level 1):
- alter, and
|1||SEND||send||populate with values (from somewhere)||positive||will-send|
|2||CR-UI||from UI||Take the data from UI, so that the user has to enter it.||in-ui|
|2||CR-S||from persistence layer||Take data from storage/persistence layer.|
|2||CR-C||constant||added as constant|
this value has no valid representation or meaning in the sending application, it is just added because it is required to be there
Data received is processed as needed for general message consumption, store permitted.
|2||DISPLAY||display/present (UI)||present the data on a display||display|
|2||STORE||store||store/persist the data somewhere||store|
|2||print the data (somewhere)|
consider the data in order to interpret other correctly
it is not requested to process this element other ways further
To UPDATE data by merging other data with the existing data in a controlled manner
|1||IGNORE||ignore||just ignore the data||negative|
probably for constants or other non-relevant information.
|2||PROHIBT||prohibit||it is not allowed to provide this data|
inherit the obligations to dependent elements in the hierarchic tree:
For example, inheriting "SHALL store" would mean that all subnodes/leafs would have this requirement without having to declare it explicitly.
|it must be discussed whether explicit inheritance obligations are necessary or not when referencing other requirement collectors by using the actor hierarchy.|
|2||INH-O||overrule||the processing rules inherited from above can/are overwritten||needs further investigation|
|2||INH-A||add||obligations to be added to the inherited ones.|
An essential result of the table above is positive or negative support of an element - beside no other requirements.
A starting point for the previous table was the Must Support replacement proposal [Historic Reference Purposes] created by Grahame and v2 IGs. Grahame's proposal should be enhanced with:
- conformance verbs, instead of pre-coordinated codes
- simplifies testing and profiling because the axes are separated and allows for adding precision
- dealing with extensions leading to define expectations about data (see below)
- level: resource, attribute
- type: data-absence, additions, replacements
Inheritance of requirements will be done by the actor hierarchy. More special actors inherit the requirements from above.
The expectations of data management/handling is translated into an appropriate code system:
data fits to expectations/specification
keep the information (unmodified)
that would possibly also include all unexpected details, and should also prohibit truncation.
|3||exactly||exactly what is specified, nothing else|
Use exact version of (stored) data rendered character for character as it is transmitted/stored.
Data received is preserved the way it was received character for character (it may be encrypted, or compressed)
allow for modifications of the data
|3||assocation||taken by association|
original data must be exactly reconstructed:
Display data in such a way that it matches exactly the data received, regardless of the architecture used to achieve that. Goal of this is to accurately display the text exactly as it was received, without defining the storage mechanism. Allowing for flexibility in the store option of ST-EX to ST-TR-R or ST-EX-A, use the text that was received, which does not necessarily have to be stored, but must be able to be recreated unaltered for display from the store mechanism used.
Data received is evaluated and if DETERMINED to be a match to existing data in the system is persisted by LINKING or via a pointer.
|3||equivalent||in an equivalent way|
Use of semantically equivalent version of stored data is rendered in locally acceptable format, without content being altered the displayed concept is semantically equivalent to the stored concept (synonym) for example a different format for a date.
Data received is preserved by reformatting to local format, without altering the content.
|3||translate||translate||Data received is preserved by 1:1 mapping/translation to an internal value that is semantically equivalent, that preserves the temporal aspect of the translation.|
|4||semantically||translate semantically||Two concepts are semantically equivalent if they can substitute for each other in the defined use case with no loss of information used to define the concept.|
|4||clinically||translate clinically||Two concepts are clinically equivalent if they can substitute for each other in the defined use case with no impact on clinical interpretation by a trained clinician. This may include further refinements based on the specific domain, e.g., for Lab use case, this would require interpretation that includes the impact of differences in normal ranges.|
|3||reference||Use referenced data based on stored pointer; stored data is displayed by linking to the corresponding stored value most often the case for data elements that are STORED EXACT by ASSOCIATION.|
|3||extends||additional values||extends the expected data with own information|
|3||truncated||cut off data||cut off remaining characters from the data|
|3||more-details||additional substructures||provides the data with more granular details, e.g. house number for an address line|
data is missing/not available
|aka null-flavor/absent reason|
|3||constant||added as a constant||this value has no valid representation or meaning in the sending application, it is just added because it is required to be there|
|1||unexpected||unexpected values||depends on standard|
|replaces the expected data by something else|
Therefore, the way "unexpected" data should be managed/allowed must be a separate element/attribute in the data structure, and not mixed with the obligation itself. That could become some kind of metadata to extensions that help to clarify their use.
These options should be managed either generally, e.g. on FHIR Resource Level (for all substructures), or per attribute (just this one).
How to use these requirements?
They are used as triplet:
Constraints are added by specializing the codes in the appropriate hierarchy.
Testable requirements (= "SHALL") are then generated into profiles. The include-references can be used to establish a hierarchy and to generate a differential.
Following some examples for declared obligations:
|SHALL CR-UI||shall take the data from a UI||SHALL CR-UI exactly|
|SHALL NOT SEND missing||resource/segment||prevent any kind of DAR|
|SHOULD NOT MODIFY||guidance to not change the data||SHALL NOT ALTER|
|SHOULD MODIFY||attribute||recommend to change the value in the application|
|SHOULD PROCESS||SHOULD USE|
|SHOULD USE||SHALL USE|
|SHALL ST-EX exactly order-processor|
|SHALL ST-EQ order-tracker|
|SHOULD NOT SEND extends||sender should not add any other additional information|
FHIR Obligation Codes
The FHIR Obligation Extension provides a value set for obligation codes:
|Level||Code||Display||Comment and comparison with the above proposal|
|1||ModifierCodes||ModifierCodes||is represented by a separate codesystem|
|2||can-send||Conformant Applications SHALL/SHOULD/MAY be able to correctly populate this element||the information, that a system is capable to send something but will not is useless, and equal to not having the capability|
|3||will-send||Conformant Applications SHALL/SHOULD/MAY be capable of sending this element and, if the element has a value and is allowed to be shared, include it when sending the resource||elements that are not allowed to be shared should be expressed in a separate profile where they are marked as empty/not present.|
|2||use-reason||Conformant Applications SHALL/SHOULD/MAY provide an element with a DataAbsentReason or a NullFlavor (or equivalent) if a value is not known and the element is mandatory||to be handled as "data expectation", i.e. in which way the data structure is allowed (or will be) enhanced|
|2||in-narrative||Conformant Applications SHALL/SHOULD/MAY ensure that this data element is represented in any human readable representation in a resource||to copy the information into the narrative is a special functional requirement|
|2||in-ui||Conformant Applications SHALL/SHOULD/MAY ensure that users can enter a value for this element during data input||"from UI"|
|2||in-store||Conformant Applications SHALL/SHOULD/MAY ensure that the value for this element is stored in a persistent data store||"from persistence layer"|
|2||must-explain||Documentation applicable to Conformant Applications SHALL/SHOULD/MAY explain how this element is handled||functional requirement needed|
|1||ExchangerObligations||ExchangerObligations||that refers to data expectations:|
|2||unaltered||Conformant Applications SHALL/SHOULD/MAY ensure that this element does not change between receiving and transfer||that does not imply that the element is not altered (in between)|
|2||may-alter||Conformant Applications MAY choose not to alter this element value||in which way are alterations allowed?|
|2||no-error||Conformant Applications SHALL/SHOULD/MAY accept resources containing any valid value for the element without error|
That should always be the case, otherwise the IG is not specific and detailed enough.
A problem arises from value sets with different coverage from different actors.
|2||handle||Conformant Applications SHALL/SHOULD/MAY handle the meaning of this element correctly||specific activities|
|3||display||Conformant Applications SHALL/SHOULD/MAY display the value of this element when presenting the data from the resource to a human user|
|3||share||Conformant Applications SHALL/SHOULD/MAY retain the value of this element when the information from the resource is shared with other applications|
|3||process||Conformant Applications SHALL/SHOULD/MAY consider the value of this element when processing the resource as specified by the IG|
|3||store||Conformant Applications SHALL/SHOULD/MAY store the value of this element in a persistent data store|
|3||Conformant Applications SHALL/SHOULD/MAY print the value of this element somewhere|
|3||ignore||Conformant Applications SHALL/SHOULD/MAY ignore the value of this element somewhere|
|3||preserve||Conformant Applications SHALL/SHOULD/MAY keep the value of this element exactly|
that refers to data expectations that alterations are not allowed.
On non-leaf nodes that implies exact knowledge about the structures and possible extensions providing more details than specified. Currently this spec is silent on this aspect.
This seems to be an error in the specification!
However, modifications require more details about what is allowed to do.
|1||AggregateConcepts||AggregateConcepts||Seems to be a pre-coordination of concepts with unclear meaning.|
|2||can-populate||A Conformant Application MAY choose to populate this element or not||same as "can-send"|
|2||can-ignore||A Conformant Application MAY ignore this element||on receiver side unknown elements are alwqays ignored unless they are necessary for a specific workflow.|
|2||v2-re||V2 RE||represents the v2.x concept for mustSupport with a minimum cardinality of "0"|
|2||ihe-r2||IHE R2||same from IHE|
|2||std||Standard Obligations||that should always apply, i.e. requirements are inherited from higher level elements and profiles.|
How can we realize the aforementioned concepts within the different product families?
Realization for FHIR
In FHIR, the proposal can be added in form of extensions to the must-support attribute, or by referencing a set of actors with their obligations. That would require:
- 3 simple extensions
- 1 complex extension, combining the other 3
(Another option would be to enhance the basic FHIR structure accordingly.)
Realization for v2+
A realization in v2+ is very similar to FHIR because the same basic conformance constructs are used.
Validation (of Profiles)
Before the content of the specified profiles can be used for development, eg. for instance validation, the profiles must be "expanded" from this comprehensive definition and generated into a set of dedicated profiles.
The "actors" are the foundation and anchor to generate generate the profile. The hierarchy is extracted from the inclusion references. A name could be selected from the name of the actor.
Some examples should explain how these concepts work together:
|an application must be capable to provide a certain element, and it shall always provide a valid value according to the original data specification; it must be able to demonstrate that||SHALL send exactly||1|
equivalent to V3 mandatory;
R in v2
|an application must be capable to provide a certain element, and it shall provide a valid value according to the original data specification when meaningful data is available, e.g. data is entered into the system (system must allow for entering this kind of data)||SHALL send exactly||0|
vendor must provide capability, user may not enter data;
RE in v2
|an application should be capable to provide a certain element, and it should always provide a valid value according to the original data specification when it has been implemented||SHOULD send exactly||1||it is not a testable requirement|
|an application should be capable to provide a certain element||SHOULD send exactly||0|
|an application must be capable to provide a certain element, and it should always provide a value; null-values/data-absent-reasons are allowed ; it must be able to demonstrate that||SHALL send missing||1||equivalent to V3 required|
|an application must be capable to provide a certain element, and it should always provide a value; other values than original are allowed; it must be able to demonstrate that||SHALL send unexpected||1||the sender can add any other value (in FHIR extension)|
|the receiver of data has to (must) store (including substructures) whatever the sender has send||SHALL store preserve||1|
|the receiver can store the data he receives in a way he likes||MAY store modify||-|
Requirements should be documented based on use cases, taking care of real issues that are relevant to realize this scenario.
From a testing perspective only requirements introduced as "SHALL" or "SHALL NOT" can be tested. A "SHOULD" or "SHOULD NOT" can be taken as "ideas" for an architect whether it makes sense to take it into account or not. In the end, a vendor/developer can decide.
Mapping to different standards?
The aforementioned conformance constructs appear in almost all data exchange standards and specifications. Unfortunately, the are not named equally, and even then the same term may have a different meaning:
|activity/obligation||some IGs||-||-||specified in IG|
|extensions||via Z-segments||via Z-segments||via namespace||extensions|
Open Topic: The table view does not directly allow for pre-coordinating the concepts like it is done with V3: "mandatory" = SHALL + no-null-value.
Mapping to v2+
V2+ can be used to renew and modify the optionality/usage indicator in the same way like with FHIR, given the enhancements are accepted. It could make use of the conformance verbs in combination with cardinality.
The translation from v2.x applies.
Mapping to v2.x
V2.x has "optionality" (in base standard)/"usage" (in profiles) that makes use of pre-coordinated terms. v2.x does not generically allow null values:
|0..||X||recommendation should be "SHOULD NOT"|
|0..||B||recommendation should be "SHOULD NOT"|
not "SHALL" because further use of such an element is not a violation,
therefore recommendation is should "SHOULD NOT"
The (optional) flags further specify certain reasons. In the above case, why there is a recommendation that it should not be supported: The standard does not forbid it, just set a recommendation.
Conditions have to be translated into the correct interpretation of what the condition should express. Support can be managed by declaring appropriate modules.
For generating v2+ when separating a core framework and a base standard profile, the latter is what v2.x represents, only ID/CNE elements are left in the core because all other are depending on use cases.
Mapping to V3/CDA
|optionality||=>||support||cardinality||null flavor (DAR)|
|not permitted (NP)||SHALL NOT||0..0||yes|
Cardinality is a valid conformance construct for V3/CDA already.
- Association with Actors, possibly taken from FHIR resources
- design strategy to reuse the real specifications across IGs
- Can we eliminate some activities because their aspect is managed by data exeptations?
FHIR Representation (Draft for a Proposal)
Following is the current draft as a starting point for discussions about FHIR resources and value sets: