Understanding #FHIR Patterns

Apr 13, 2018

The FHIR R4 ballot is out (see announcement), and I’d like to draw attention to one part of FHIR that we’ve been working hard on during the preparation of R4: Patterns. Specific vs General

The background to patterns relates to generality vs specificity of the content models. When designing content models for exchange, designers have a choice:

(Sometimes this is called “Concrete” and “Abstract” but that has other meanings, so I’m going to stick with Specific / General)

Specific Designs:

  • For each actual exchange you want, you design a content model (schema) that has exactly the data items that you want for that exchange
  • This is really convenient for that exchange, because you only deal with exactly what the problem calls for
  • But as you deal with more and more related problems, you start from scratch each time, and spend more and more of your time writing transforms between the content models

General Designs:

  • You sum up all the related problems you have, and all the ones you can imagine, and design a big content model that handles all of them in a single structure
  • You get to reuse a lot of your work across different related problems
  • But each specific problem you work on, you get the tax of transforming to the general content model, and how do you prescribe these transforms?

This concept easily be illustrated using poetry: imagine that you are writing a scheme to describe a poem. It’s easy to imagine specific schemas for haikus and limericks, for instance – the rules for these are very well known. But there’s many other poetry forms that a much more fluid, and the schema becomes ever more flexible as you try to account for them (do poems even have to have words?). (h/t to Andrew Goodchild for introducing me to this example many years ago).

Choosing between Specific and General is a trade-off; there’s no great solution because you’re going to get transforms somewhere, and everyone (rightly) hates transforms. Also, it’s not a binary choice – you can (and should!) design somewhere along the spectrum, and where you land on the line is driven by a number of practical considerations.

In FHIR, we made a specific decision to be as specific as we can get away with. We debate the selection of use cases that get a common content model extensively, and have a number of consultation, community and management processes that deal specifically with this question. That still leaves us in the middle of the line somewhere, and we need to provide implementers with a language to deal with implementing more using a more specific or more general approach than FHIR. That’s necessary because implementers have their own constraints, and existing approaches that are already set in stone.

For supporting more specific approaches, we have profiling.

For supporting more general approaches, we have patterns.

FHIR Patterns

What we call patterns in FHIR (a name chosen somewhat arbitrarily) are a FHIR logical model that describes a more general pattern, and which the resources are required to conform to somewhat.

FHIR logical models are content models where the content modelling infrastructure developed for FHIR are used to describe a content model that is not a FHIR resource or data type.

Btw, note that the term “Logical Model” is really about the content being described is not – it’s not a FHIR resource or data type. In practice, we are using these for all sorts of things – domain analysis models, concrete schemas from other standards (v2, CDA, etc), or abstract design patterns. These are all different things, and lumping them under the general term “logical model” doesn’t really describe what’s going on here – we’re reviewing our use of language here.

FHIR patterns are logical models that describe a general design that other resources are required to follow to some degree. The most general pattern is the Five ‘W’s Attribution pattern (Who, What, When, Where, Why). This pattern describes a set of common attributes that resources might have:

This pattern says, for instance, that in general, resources might have identifiers, a version element, a status code, etc, and these are the recommended form for representing this attribution information in resources.

Resources can then define which elements they have, and how they map to the pattern – that is, how the resource is consistent with the pattern. Here’s an example for the DocumentReference resource:

The FHIR tooling then takes this information, and generates a large summary table that shows how the pattern is implemented in all the resources. Here’s the row for Document Reference:

This shows which pattern elements have a mapping into the resource for the Attribution pattern.

There are 3 other patterns:

  • Event: A pattern to be followed by resources that represent the performance of some activity, possibly in accordance with a request or service definition.
  • Request: A pattern to be followed by resources that represent a specific proposal, plan and/or order for some sort of action or service
  • Definition: A pattern to be followed by resources that represent a specific proposal, plan and/or order for some sort of action or service

Consistency?

An important fact – evident above – is that not all resources have these elements. Some literally contain elements based exactly on these element definitions, even using the same definitions, while others have some variation – sometimes the general concept is split into different elements capturing different aspects of the general case, or a simplified representation is chosen since it’s possible to be more specific for the use case in question. Or sometimes, the committee decides that there’s an obvious fixed value for one of the attributes, and documents that in the resource design, or sometimes committees decide that the element is not relevant for exchange in this use case (and that is a valid thing to do – there’s always the provenance resource to fall back on, where all of these elements can be represented).

It’s also possible that committees have failed to consider the use cases that these elements represent. That’s one of the points of defining these patterns – we can check whether resources conform to them, and require committees to account for the differences, to make sure that the use cases have been considered. This is work in progress – the patterns are following along behind the resources, and so it would be very appropriate to ballot around pattern consistency.

Note: alert readers with experience with HL7 v3 or openEHR will note that our approach here is different than in either of these, where pattern conformance is ruthlessly enforced, and we know that not everyone is happy about this. But it’s been a key philosophy of ours from the start, that the domain requirements are more important than the pattern consistency requirements.

We do have tooling that checks that when resource elements are mapped to pattern elements, they are actually consistent with the pattern element definitions and value domains, but at this time these are mostly only identified as QA issues for the committees to check. Over time, we expect some of these issues to turn into hard errors that must be resolved prior to publication.

Status Codes

One pattern element that has received particular focus is the status code element. Most (though not all) resources have a status element that describes the status of the resource. The possible status codes span the state of the resource as a record about a real world entity, and the state of the real world entity itself. Each resource defines its own status code, with a definition using language specific to the use cases that the resource addresses.

Every status code is also mapped to a code in the canonical status code system. Here’s the mapping for DocumentReference.docStatus:

So every status in a FHIR resource can be converted to a canonical status codes – this means that the resources have a common set of status codes. (Terminologists may think of this as a reference terminology with a set of interface terminologies.)

All of this infrastructure – the patterns, the element mappings, the code systems, and the concept mappings – is all published as conformance resources so that tools of all kinds can pick up the information and reason with it, whether that’s for design validation, resource validation, code generation, implementation guide publishing, etc.

Implementer Use of Patterns

While the patterns are defined to assist with design consistency, the intent is that they will also be useful to implementers: implementers that work with a more general design approach than FHIR – e.g. parts of the CIMI community (though CIMI is also very interested in very specific content models too) – can map to a pattern instead of individual resources. Then tooling could determine which of the mappings are reflected directly in particular resources, and which are unresolved (may need extensions?)

Such a mapping approach is somewhat degenerate, as described above – but that’s actually the point. One of the lessons of the V3 experience is that there is implicit degeneracy in the general à specific model transformation, and one of the big problems of V3 was that the degeneracy turned into under the cover issues for implementers. We believe that making the degeneracy explicit in the mappings is actually a value proposition.

So this is our intent: that implementers working with a more general design approach use patterns to map to the FHIR specification as part of their implementation guides. This is very much work in progress: there’s presently no clearly described way for an implementer to define their own pattern, or define mappings for the different resources for the pattern, or to publish this in an implementation guide, or to generate code from such mappings in the various relevant languages. Watch this space!