This wiki has undergone a migration to Confluence found Here
<meta name="googlebot" content="noindex">

FHIR Guide to Designing Resources

From HL7Wiki
Jump to navigation Jump to search

Introduction

This section provides guidance in the design of resources, profiles and extensions. It does not answer technical "how to" questions, but rather provides guidance for work groups and other authors in the design decisions they make. For technical instructions on how to define resources and the meaning of various resource and extension properties, refer to FHIR Guide to Authoring Resources.

Design guidance is provided in the form of questions with associated answers. In many cases, the guidance provided is non-binding advice. However, in some cases the answers reflect formally approved methodology which is expected to either be followed or have an exception granted and may be reviewed as part of QA processes. These are clearly marked as "Rule". All rules and many guidelines will also have additional content that provides information on *why* the rule or guideline is in place, referencing the principles and precepts associated with FHIR.

This page is subject to ongoing change as HL7 gains experience in FHIR development and implementation. Feel free to add new questions, guidance on existing questions, etc. This page is curated and managed by the Modelling and Methodology committee who has authority for formal approval the creation and modification of "Rules". If a change is desired to a rule, please add a comment rather than changing the rule directly. The guidelines used to evaluate methodology guidelines can be found in FHIR Methodology Process.

In some cases, methodology questions may also be of interest to implementers. These topics are marked with a "**" and may be migrated into the FHIR specification directly

Todo: Move more content across from Authoring FHIR Resources


Contents

Resource Guidance

Naming Rules & Guidelines

Rules

  • Names for operations, resources and resource elements must:
    • be lowerCamelCase for elements, UpperCamelCase for resources, be lowercase for operations
    • be U.S. English (spelled correctly!)
    • be expressed as a noun, with a preceding adjective where necessary to clarify the semantics and to make unique
    • not make use of trade-marked terms

Guidelines

Determination of names needs to take into account the “scope” of what the resource/element/operation will be used for. I.e. What are the boundaries?

Names should:
  • use the "most broadly recognized" industry term for the object that is unlikely to be mistaken for a different element.
  • assume no familiarity with other HL7 standards such as v2, v3 or CDA except within the broader context of what industry is familiar with overall
  • as much as possible without interfering with the intuitiveness of the name to implementers
  • express the full breadth of meaning of the concept
  • be sensitive to cross-national political considerations
  • use abbreviations only where extremely well understood by the entire target market.
    • Where used, treat the abbreviation as a “word” in terms of following the casing strategy. E.g. “targetUri for an element name”
  • use different names for different elements within the hierarchy unless the semantic is the same in different context.
    • E.g. using “.name” for “sponsor.name” and “contact.name” is ok if the meaning of “name” is consistent for both sponsor and name.
  • use names that distinguish from concepts that are not part of the resource (not considered core), but still exist in the resource space and might reasonably be confused.
  • be concise (differentiation of semantics through the name is only necessary with other elements in the resource. Full semantic description is in the definitions.)
    • This includes non-redundancy with the context. I.e. Don’t repeat part of the parent in the name of a child
  • be consistent with naming of similar elements in the same resource and other resources unless driven by common use of different terminology in industry.
    • E.g. “birthDate” and “dateOfDeath” would be bad
  • be sufficiently different from other names in the same space (other elements in same resource, other resources for a resource, other operations for an operation) to avoid confusion in verbal communication (“update” and “updates” is bad)
  • not include a suffix whose purpose is to identify the data type of the element (i.e. don’t end a name in “code” or “indicator”, etc. to identify what it is.
  • where a concept is known by multiple names in different places or contexts, use aliases to convey additional names
  • Names that lend themselves to being frequently abbreviated in committee use are likely too long and should be viewed with suspicion.
  • Use skmtglossary.org and a thesaurus to evaluate candidate names when unsure
  • If you’re having a really hard time coming up with a commonly recognized industry name for a thing, it may be a sign that the granularity of your “thing” isn’t aligned with industry needs.

Purpose is to give maximum insight for the unfamiliar developer to "what is this thing". Also used for searching. Name length impacts instance size and code readability, so there's a trade-off between semantic precision and ease-of-use.

Creating Resources

When should a new resource be created?

How should resources be named?

Creating resource elements

When does an element qualify for inclusion in core?

What if an element qualifies for core based on commonality, but is known to be bad practice?

In some cases, clinical systems will capture information in ways that is known to be flawed or not in keeping with best healthcare practices. In these circumstances, aligning with the 80% means perpetuating a business practice that is known to be problematic. In these circumstances, a Work Group may choose to instead support the more "current"/"best practice" approach to data representation. The primary considerations for making this call is whether it's a reasonable imposition to expect at least 80% of systems to support the new approach in a realistic adoption period (5-10 years). Factors affecting this include how easy or hard it is to migrate from old approach to new, how much added complexity is caused by the new approach and how much benefit to practice and patient care is provided by the change. If the work group agrees to make the change, they should note the exception to the 80% criteria and their justification in the Notes column. Serious consideration should also be given to an extension or set of extensions that support the "old" approach as well.

When faced with multiple alternative expressions mechanisms, which do we choose?

Where within the nesting structure should an element be added?

When do we create additional "levels" within a resource?

Are there design patterns for common semantic scenarios?

Yes. Refer to FHIR Design Patterns

Resource element content

How should resource elements be named?

What order should elements appear in?

Elements should be ordered roughly in terms of importance, with related concepts grouped together.

What if an element is known by different names in different contexts?

When should an element have a minimum cardinality of 1?

When should an element repeat?

When should the default UML layout be overridden?

Should the order of repeating elements matter?**

When should elements be marked as 'IsModifier'?

  • isModifier should only be declared on an element whose meaning would reasonably affect the meaning or interpretation of parent or peer elements.
  • It does *not* indicate any expectation that mustSupport is true for the element, nor should it be used a general purpose importance flag
  • When a element is flagged as "IsModifier" there must be some explanation of how or why it is flagged in the definition or comments, and if the minimum cardinality is 0, the implication of the element not being present must be explained

The flag draws attention to elements that influence the meaning of other elements so that implementers don't accidentally misinterpret data by ignoring them. Particularly important for extensions that might not be recognized.

What combinations of cardinality and 'Must Understand' are allowed?

Elements with mustUnderstand=Y should generally have a minimum cardinality of 1. If an element with mustUnderstand is omitted, it means that the parent element and all content within it can't necessarily be safely interpreted. No default value can be inferred. If it is possible for the value to be unknown, consider making minOccurs=1 and add an explicit coded value of "unknown" to make this explicit.

Default values are unsafe and interpretation can vary by context. Explicit values are safer

Resource element types

What are the criteria for selecting an appropriate data type?

General considerations

  • What level of discrete data do most systems capture for this element?
I.e. Don't select a complex data type if most systems only capture a string or simple date
  • When possible use an existing data type rather than creating your own custom structure within a resource to accomplish the same end. It's important to balance the careful tuning of elements to requirements with the ability to leverage commonly re-used structures.
  • If all properties of a data type aren't appropriate/relevant for a use-case, consider profiling the data type in a re-usable way and then referencing the data type with its profile.

Coded vs. non-coded

Codes should be used when computer systems are expected to make decisions on the basis of the data or when the information will be subject to statistical analysis. Examples include decision support, business rule validation, enhanced querying, etc. There is no value to using codes if the data is only for human consumption and there is no need to categorize by the element.

Choice of coding data type

There are 4 data types that support transmission of coded data: code, Choice, Coding and CodeableConcept. Each is intended for use in specific circumstances:

code should only be used when the following conditions are met:

  • The data element forms an essential part of interpreting the meaning of the resource, such that safe processing would be impossible without it. I.e. the element must be “mustUnderstand” or the element is a part of the FHIR infrastructure and has no clinical or business meaning
  • The element will be bound to a code list that is complete (non-extensible) and required (everyone must use it)
  • The element is intended for computing purposes, not human display
  • Ideally, the bound codes are human-friendly, expressed in English. I.e. The semantics are evident from looking at the code

This type allows for no translations, display names or original text so it is inappropriate for elements targeted to humans or elements that might need different codes in different implementation environments

Choice should be used when the set of codes bound to the element will vary from instance to instance. I.e. Even within a single Profile, the set of codes available will vary. This generally occurs with surveys and similar situations where the set of codes will vary from question to question.

Choice carries the value set with it. This overhead is only appropriate in circumstances where the value set can't be known from context.

CodeableConcept is the datatype for use in the vast majority of situations involving coded data. It supports multiple translations which allows common instances to be used in situations where different recipients might require different codes. It also allows for migration between code systems over time. Finally, it supports conveying a textual representation of the concept which is important for situations where no appropriate code exists or where the recipient doesn't recognize the code system or wishes to see the full detail of the original concept, not necessarily what was expressible by the selected code.

Coding is used in very limited circumstances, primarily in extensions where there's a need for finer control over the use of translations and text than is provided by the CodeableConcept. Work Groups considering using this type within a resource or within an HL7-defined extension are encouraged to discuss this with either the Vocabulary or Modelling and Methodology Work Groups.

Because this type doesn't support translations or text, it is likely to produce interoperability issues unless used very carefully

Choice of Identifier datatypes

There are 4 data types that can potentially be used to identify things: id, uri and its specializations (oid, sid and uuid), Identifier and HumanId. Each is intended for use in specific circumstances:

id is intended for use within the data types themselves and for "internal" identifiers to FHIR such as referencing another resource. An id is generally not globally unique so it is generally also only useful within a context. Direct use may be appropriate in extensions where a greater degree of control is needed than that offered by the standard data types. For example, specifying a "version" that is expected to be scoped by a companion Identifier element. Work Groups considering using this type within a resource or within an HL7-defined extension are encouraged to discuss this with the MnM Work Group.

uri is also generally intended for use within the data types, though it may appear as an element when communicating network addresses and the complexity of the Contact datatype is inappropriate (see below). Using URIs or one of the specializations for identifiers is only appropriate if a Work Group is 100% confident that all implementers currently and in the future will use a bare URI/OID/UUID/etc. for the identifier rather than the more typical "system + id" approach supported by the Identifier and HumanId types.

Identifier is intended for use in communicating identifiers not generally expected to be seen by humans or at least where the context of the identifier is implicit in the element. Examples might be order numbers, insurance identifiers, etc. The type, effective period, assigner and other metadata should either be irrelevant, implicit in the context or communicated via sibling data elements. In most circumstances, elements with a type of Identifier should have a maximum cardinality of 1. (If multiple repetitions are present, then the context information of the identifier is likely to be ambiguous, at least for human display purposes.)

HumanId is intended for identifiers expected to be displayed to humans where the information about the "kind" of identifier may vary. Frequently HumanId elements will be allowed to repeat.

The HumanId conveys the most information about the identifier and is therefore most amenable to human display.

Encoded data

There are 4 different mechanisms that can be used to convey binary and other encoded data such as images, embedded XML, PDF documents, etc.: Attachment, base64binary, uri and the Binary resource. Each is intended for use in specific circumstances:


Todo

Quantities

Range, integer, decimal, Quantity, Quantity profiles, Ratio

Timing

Schedule, Period, dateTime, date, instant

Contact

uri, Contact

Anything vs. string

Most common for HumanName and Address, but possible for others


When should multiple types be selected (i.e. a 'choice')?

When should an element reference a base data type vs. a profiled data type?

When should content be expressed inline rather than referencing another resource vs. both?

When should a resource have multiple elements rather than a single element with a choice of types?

When referencing resources, when should a list of allowed resources be enumerated and when should it be left open to Any?

Vocabulary

Every element that can have a code (types "code", "Coding", and "CodeableConcept") must have a "binding", which defines what codes can be used in the element. (There are a few special exceptions in the infrastructure itself)

How should bindings be named?

A binding name should be a title case word like "ProblemType". The binding name is not particularly meaningful - it's just a name that refers to the definition of the Binding. Within the specification itself, binding names must be unique, so it's a good idea to start the binding name with the resource name itself.

Binding names can be changed at any time without creating any implementation impact.

What information is supplied for a binding?

When you build a binding, you specify some or all of the following information on the bindings tab of the spreadsheet:

  • Definition: The meaning associated with this binding. Very often this is a clone of the element definition to which it is attached with minor grammatical corrections - but not always
  • Binding: How this binding is resolved to a set of codes. Possible values:
    • unbound - there is no particular codes associated with thie binding (this equates to a v3 concept domain)
    • special - this is bound to a set of codes that are internal to the specification (generally, this is only used in infrastructural resources)
    • reference - the set of codes is established simply by a general reference to some external web site (generally, this is used for "code" fields where the contents is anything defined by some external framework. A classic case is IANA media types. This should only be used after discussion with the FHIR core project team)
    • valueset - this is a reference to a value set. Preferably the value set is defined using a value set resource, and provided as part of the spec. it can be a simple external reference.
    • codelist - the specification provides a list of codes, and one of them should be used. The codes can either be defined as part of the specification, or defined elsewhere
  • Strength - what strength the binding has. Valid values:
    • required - implementers SHALL use this binding
    • preferred - implementers SHOULD use this binding
    • suggested - implementers MAY use this binding (i.e. it's an example)
  • Extensibility - whether the implementers can add their own codes for concepts not included in the binding. It has the following values:
    • complete - the implementers must use a code defined by the binding
    • extensible - the implementers can use other codes and/or just text for any concept not found in the binding
  • Management - how change to the codes will be handled going forward. Valid values for this depend on the type:
    • Binding = valueset
      • static - the list of codes is fixed as of publication
      • dynamic - the list of codes grows as new codes are defined and come into scope of the value set
    • Binding = codelist
      • fixed - the code list will never be changed (or, if it needs to change, it will be considered a breaking change). This is unusual - there are very few codes in this category, and mostly it would be safety reasons
      • alterable - future versions may add new codes, and implementers should have some arrangements for dealing with this eventuality
  • Reference - a url reference to the source of the definition. It's usage depends on type:
    • (codelist) - an internal reference starting with "#" that refers to another tab in the spreadsheet. The name should be all lowercase with "-" delimiting words. The tab name must be unique in the specification
    • (valueset) - either an absolute URL, or a relative URL which is just the name of a valueset resource (xml or json) found in the same directory as the spreadsheet. In the relative URL case, the value set will be picked up and published as part of the specification, and the relative name must be unique in the scope of the specification
    • (reference) - an absolute URL
  • Description - what the build tool shows when the reference is placed in the specification. if this is empty, the URL will be used instead.

Some of these fields can be combined in ways that don't make sense. The build tool generally only allows valid combinations. In addition, resource designers can rely on the build tool to enforce the name uniqueness constraints that are required.

Should I use a value set or a code list, or leave it unbound?

Firstly, note that a list of codes can incorporate codes defined in some other specification (often v2 or v3), or it can define it's own codes. A value set always refers to codes defined elsewhere.

You would define your own codes in one of two case:

  • the data type is "code" and the schema should enforce that only the codes allowed are used (irrespective of whether the codes are defined here or elsewhere)
  • you are defining a set of codes that can be used in resource, along with other codes. This would imply Coding/CodeableConcept as the type, with an extensible binding, or a preferred one. This is unusual and you should consult the core team prior to creating this kind of code list.

In other cases, if there is enough agreement on a set of codes, use a value set that defines the set of codes. When there is not enough consensus for that, you leave the binding unbound. Note that you can provide a suggested value set- and this is better.

How do I define a code list

You should only define a code list that has internally defined values if the codes are inherently related to the use of the resource itself. Typically, these are of type "code" and have names like "status", "state", "kind", and a very short list of codes (<10, usually <5) that are often involved in invariants, or discussed in the narrative. These codes are generally specific to FHIR, and not copied in and out of other representation formats. Longer codes lists, or concepts that are copied into and out of v2 messages, cda documents, dicom or xds etc, or that are exposed directly on the user interface should generally be incorporated from somewhere else, and if they don't already exist, some other place should be created (such as in the general vocab terminology through harmonization)

A code list is a tab on the spreadsheet with the following columns:

  • Id - an internal identifier that is never changed
  • System - a url that identifies the external system that defines the concept (usually a v2 table, a v3 code system, loinc, snomed)
  • Code - the code that is used in the instance (if a System is provided, the code must be valid in the referenced code system)
  • Parent - if the code is subsumed by another code (only 0..1 parent supported for now)
  • Display - a display name/print name to be used with the code. Display is optional, on the grounds that the codes are related to system workflow concepts, not direct user input, and the users would never be expected to see the code directly. i.e. if the display is missing, the code shouldn't be display directly to the users (display must be provided for externally referenced codes)
  • Definition - the formal definition for the code (required for all codes)
  • Comment - additional usage information.

Entries in the code list have either an Id (internally defined) or a System (externally defined). You cannot mix internally defined codes and externally defined codes in the same list (for now).

This list provides help for importing codes from other code systems:


When should a binding be 'required' (i.e. universal)?

  • If the data type is "code", the binding must be "required"
  • Value set bindings must not be marked as “required” for CodableConcept elements at the Resource level unless a context binding in the universal realm already exists in v3 terminology
  • To constrain to tighter vocabulary, profiles must be used
  • If a Concept Domain is context bound in the universal realm at HL7, the equivalently RIM-mapped FHIR elements should be bound to the same value set (within the constraints of backward compatibility rules, approval cycles, etc.)

We can’t make implementers non-conformant just because for jurisdictional policy or legacy reasons they’re unable to express data in a particular code system


What are the criteria for choosing Binding Strength?

Lloyd to do

When should content (negation, uncertainty, null values) be handled in terminology vs. distinct attributes?

Mostly, for internally defined code systems, null value issues don't apply, though the code 'unknown' may need to be defined sometimes.

For FHIR, there is no ubiquitous nullFlavor concept, so the code list/value set should include these concepts directly. Typically, these concepts are included by including the codes from the v3 NullFlavor code system etc.

Descriptive Content

What makes for a good Short Description?

A short description should:

  • Provide an alternate expression of the meaning of the element (i.e. not a repetition of the element name)
  • Should be short (<60 characters)
  • May be a phrase or an enumeration of allowed codes
    • enumerations should only be provided when
      • there is a single mandatory binding
      • the semantics of the codes are clearly expressed in the code itself
      • there are a small number of codes (no more than 5-6)
    • enumerations should match the spelling and case of the code and be delimited with " | "
    • if there are too many codes to reasonably express all of them within the length limit, use a representative set and put " +" at the end
  • Must be in U.S. English
  • Must start with upper-case unless an enumeration
  • Should use terminology the majority of implementers will find familiar

The purpose of a short description is to provide more information to the reader than is conveyed by the name of the model element while still being quick and easy to read. Starting with an upper-case helps the short description show up well in the XML

What are the criteria for a good Definition?

A good definition:

  • Provides additional clarity for the selected name
  • Can be easily consumed and understood by the reader. A guideline is that a definition does not exceed 1 paragraph in length though many definitions can be considered complete in a single sentence. Some difficult concepts may however require lengthy discussions but this is best left to comments and examples (see below)
  • Is unambiguous
  • Allows the reader to understand the definer's intent for the field
  • Should be grammatically correct. The definition should be composed of complete, grammatically correct sentences.
  • Is not reflexive
    • It should not rephrase the name in a statement, for example a definition for ConcernCode as "A Code value for the Concern" simply repeats the information conveyed in the name. At the very least, a definition provides synonyms for the concepts that comprise the name to allow the reader a better understanding of the definer's intent.

What goes into Definition vs. Requirements vs. Comments vs. Committee Notes?

The following contrasting sections attempt to explain and illustrate what is placed in each of the aforementioned sections:

Definition
A short concise (no more than 1 paragraph) description of the purpose of the described element. Every element will have a definition. (the WHAT)
Requirements
The reason(s) for including the element in the specification. A description of why the element is necessary (and under what conditions). May be documented using formal methodologies for business requirements or simple notes. Not all elements will have a requirements discussion. (the WHY and the WHEN)
Comments
The thought processes and design ideas/constraints that went into the creation/definition of the element. The area is also suitable for detailed discussion on the element including such topics as background and use. This section can also be used to augment the definition.
Committee Notes
There could be much overlap between Comments and Committee Notes. Essentially, Comments provide additional information about the element whereas Committee Notes document the process, decisions, and recommendations of the responsible Work Group. The Committee Notes are often formal in nature.

As a side note, the name of the element is the Who and the examples provide the How, thus answering all of the essential questions on the specification of an element.

Mappings

What mappings should be created?

How precise should a mapping be?

Invariants

What rules should be expressed as invariants?

What should the context be for an invariant?

Can invariants reference elements inside another resource or data type?

How should invariants be named?

Do I need to specify OCL or XPath?

What are the criteria for the English expression of an XPath?

When should an invariant be linked to specific elements?

Events

What events should be created for a resource?

When should an event have multiple request or response resources?

What should go into an even description?

When should an event have follow-ups?

What should go into event description vs. notes?

Search

What search parameters should be included in a resource?

How should search parameters be named?

  • Use element name
  • unless the element name is meaningless without scope (i.e. Resource.something.somethingelse.type) (in this case, consider just using the parent name)
  • unless that creates a duplicate search parameter
    • if it does - then pick one (or both) or use [parent]-[child]

What should go into a search description?

How should the type of a search parameter be determined?

When should a repeating parameter be handled as union vs. intersection?

Examples

How many examples should be created?

How realistic should examples be?

What should examples cover?

Additional documentation

What content should go into the introduction and notes section?

When should content be in the introduction and when in notes?

Where should content go that doesn't easily fit in either place?

Profile Guidance

Todo


Extension Guidance

Todo