|
14 min de lecture
|

Liaisons sans limites

Résumé de l'article

Les liaisons supplémentaires — introduites dans FHIR R5 — permettent d'associer plusieurs contraintes terminologiques à un seul élément, chacune avec son propre objectif : exiger des codes précis pour les nouvelles données, suggérer un sous-ensemble de départ, fournir des indications pour l'interface utilisateur, ou appliquer des règles propres à une juridiction. Elles se superposent à la liaison principale sans jamais la remplacer.

Résumer cet article avec :
ChatGPTPerplexityClaudeGrok

Un élément, une liaison — et ses limites

Depuis FHIR DSTU2, chaque élément codé possède exactement une liaison — une règle qui associe l'élément à un ensemble de codes autorisés (un ValueSet) avec une force particulière. La force indique à quel point les codes doivent être respectés : required signifie que vous DEVEZ utiliser un code de cet ensemble ; extensible signifie d'en utiliser un s'il s'applique à votre concept, sinon vous pouvez utiliser d'autres codes ; preferred et example sont des suggestions progressivement plus souples. Pour des éléments simples comme Patient.gender (lié à AdministrativeGender avec la force required), ce modèle fonctionne parfaitement.

Mais à mesure que l'adoption de FHIR s'est élargie — à travers les juridictions, les domaines cliniques et les régimes réglementaires — le modèle à une seule liaison a atteint ses limites. Les auteurs de profils (les personnes qui rédigent des StructureDefinitions — des ensembles de contraintes superposées aux ressources FHIR de base) se heurtaient continuellement à des problèmes qu'un seul ValueSet ne pouvait pas exprimer.

La saga Extensible+Max

Le premier contournement fut le patron Extensible+Max. US Core avait besoin d'un moyen de dire : « utilisez les codes de ce petit ValueSet, mais si vous devez étendre, restez dans les limites de ce ValueSet plus large. » La solution fut l'extension maxValueSet, introduite dans STU3 et affinée dans R4.

Elle a immédiatement causé de la confusion. La spécification la décrivait comme « une liaison 'required' par-dessus la liaison extensible » — mais personne ne s'entendait sur ce que cela signifiait concrètement. La tension fondamentale, mise à nu dans un fil de 182 messages sur chat.fhir.org : Argonaut avait besoin de « utiliser ce code ou du texte libre » pour la conformité ONC — les hôpitaux avaient des problèmes de texte libre qui étaient « littéralement une chaîne de caractères dans le système local » (Jenni Syed). Mais aucune combinaison de forces de liaison ne pouvait exprimer cela. Josh Mandel a souligné que US Core Immunization liait vaccineCode à CVX avec à la fois extensible et max — vers le même ValueSet : « Du point de vue de l'interopérabilité, je ne comprends pas pourquoi choisir extensible et maximum est préférable au simple choix d'extensible. »

Par ailleurs, une extension minValueSet parallèle tentait d'établir un plancher pour les liaisons extensibles — si un code de cet ensemble s'applique, vous devez l'utiliser. Mais elle confondait les contraintes des émetteurs avec les obligations des récepteurs, et les validateurs ne pouvaient pas l'appliquer.

Ces deux extensions ne pouvaient exprimer que deux cas d'utilisation étroits, et même ceux-là étaient mal compris.

Le problème des « liaisons multiples souhaitées »

Au même moment, les auteurs d'IG réclamaient sans cesse des liaisons multiples sur un seul élément. Le moteur le plus fréquent était IPS (International Patient Summary), qui devait exprimer un choix de liaisons terminologiques sur un CodeableConcept — différents systèmes de codes pour différentes juridictions. Le seul outil disponible était le slicing — le mécanisme FHIR permettant de dire « cet élément répétable doit avoir des entrées correspondant à des patrons précis ». Appliqué à CodeableConcept.coding, le slicing permettait d'exiger un Coding de SNOMED et un autre de ICD-10. Mais il était complexe à rédiger, difficile à comprendre pour les développeurs, et verbeux dans le rendu des profils.

Comme Grahame Grieve l'a exprimé : « Il y a beaucoup de slicing dans les guides d'implémentation parce que les auteurs veulent dire 'l'un des codes doit provenir du ValueSet X.' C'est l'utilisation la plus courante du slicing, et vous devez le faire parce qu'une liaison s'applique à toutes les répétitions du code. Mais le slicing est difficile pour les développeurs. »

La proposition de Grahame (février 2022)

En février 2022, Grahame Grieve a proposé une nouvelle extension sur ElementDefinition.binding — les liaisons supplémentaires. L'idée centrale : la liaison principale demeure la liaison de conformité (ce que le validateur applique), mais il est possible d'y associer des liaisons supplémentaires ayant des objectifs différents :

Je voudrais définir une extension sur ElementDefinition.binding qui spécifie des liaisons supplémentaires. ElementDefinition.binding est la liaison de conformité : ce que le validateur applique — et il ne peut y en avoir qu'une. Mais en plus, les concepteurs pourront spécifier des liaisons supplémentaires.

Sa liste initiale d'objectifs — conformance, required, recommended, UI, starter, component, minimum, maximum — répondait à toutes les lacunes que la communauté avait tenté de contourner. La motivation :

Dans quelques endroits, nous utilisons extensible+max et nous voulons vraiment un ValueSet de base avec un ValueSet recommandé. Dans quelques endroits, nous utilisons extensible, et nous voulons vraiment un ValueSet de base assez large avec un required — c'est ce que la législation exige pour les nouveaux dossiers.

Rob Hausam a immédiatement vu la valeur pour IPS : « Je conviens que cela semble pouvoir remplacer le slicing sur CodeableConcept.coding... En supposant que tout cela soit vrai, quand pourrons-nous commencer à utiliser ceci dans IPS ? »

Lloyd McKenzie a exprimé des réserves : « En général, si les règles diffèrent selon les contextes, alors vous avez des profils différents. » Mais Grahame a répliqué : « Ce n'est pas rendre service aux utilisateurs que de multiplier les profils qui ne diffèrent que par le contexte d'utilisation et quelques liaisons. »

En avril 2022, l'IG Publisher disposait d'une prise en charge de rendu en version préliminaire, et Grahame a ajouté l'indicateur any — « si any = true, la liaison ne s'applique qu'à l'une des répétitions, et non à toutes. » En août 2022, IPS l'utilisait déjà. La fonctionnalité a été intégrée au scrutin R5 sous la forme de ElementDefinition.binding.additional, et livrée dans R5 (mars 2023) comme élément de première classe — plus comme extension.

Comment ça fonctionne : la sémantique d'abord

Avant d'explorer le catalogue d'objectifs, deux règles fondamentales.

Règle 1 : toutes les liaisons sont en ET. La liaison principale et chaque liaison supplémentaire s'appliquent simultanément. Lloyd McKenzie l'a dit clairement : « Toutes les liaisons s'appliquent toujours. Point final. » Cependant, toutes les liaisons ne mordent pas de la même façon :

  • Les liaisons avec un contexte usage sont ignorées si vous n'êtes pas dans ce contexte
  • Les objectifs d'orientation (starter, ui, component, preferred) n'ont aucune valeur de conformité
  • Les liaisons current ne s'appliquent qu'aux données saisies depuis la déclaration de conformité — pas aux données historiques
  • Les liaisons extensible ont la sortie standard : vous n'êtes pas tenu de vous conformer si aucun code du ValueSet ne s'applique à votre concept

Si vous voulez une sémantique OU (« envoyer un code du ValueSet A ou du ValueSet B »), combinez-les dans un seul ValueSet groupé. Les liaisons supplémentaires ne vous donneront pas le OU.

Pour un CodeableConcept — le type de données FHIR pouvant contenir plusieurs représentations de codes parallèles (Codings) pour le même concept — des liaisons required multiples peuvent signifier que vous avez besoin de plusieurs Codings, chacun satisfaisant une liaison. C'est ainsi que fonctionne « doit envoyer SNOMED ET ICD-10 » sans slicing.

Règle 2 : l'indicateur any modifie la sémantique de répétition. Par défaut, une liaison s'applique à toutes les répétitions d'un élément. Mettre any = true signifie que la liaison est satisfaite si une seule répétition correspond. C'est le mécanisme clé qui remplace les tranches de codage — et comme Lloyd McKenzie l'a noté : « utiliser le slicing pour des liaisons 'et' est désormais considéré comme un antipatron et déconseillé. »

Structure et objectifs

Une liaison supplémentaire ne remplace jamais la liaison principale — elle se superpose à celle-ci. Chacune possède :

PropriétéDescription
purposePourquoi cette liaison existe (voir les tableaux ci-dessous)
valueSetL'URL du ValueSet
documentationMarkdown expliquant l'utilisation dans le contexte
shortDocoUn court résumé en texte brut pour le rendu tabulaire
usageUsageContext délimitant par juridiction, domaine ou flux de travail
anySi true, satisfaite lorsqu'une seule répétition correspond (par défaut : toutes doivent correspondre)

Voici à quoi cela ressemble dans une StructureDefinition (notation simplifiée) :

binding:
  strength: extensible
  valueSet: http://hl7.org/fhir/ValueSet/observation-codes
  additional:
    - purpose: starter
      valueSet: http://example.org/ValueSet/common-lab-codes
      documentation: >
        A manageable subset of ~200 common laboratory codes
        for implementers getting started.
    - purpose: current
      valueSet: http://example.org/ValueSet/2026-lab-codes
      documentation: >
        Required for all new observations captured after 2026-01-01.
        Legacy data may use codes outside this set.

Les objectifs ont évolué depuis la proposition de Grahame en 2022 (certains ont été renommés, conformance a été supprimé). L'élément purpose a une liaison required — vous ne pouvez utiliser que les codes du ValueSet AdditionalBindingPurposeCodes, aucun objectif personnalisé n'est permis. Voici les codes R5 :

Objectifs de conformité

ObjectifSignification
requiredL'élément DOIT utiliser un code de ce ValueSet — dans le contexte d'utilisation spécifié
extensibleUtilisez les codes de ce ValueSet si applicable — dans le contexte d'utilisation spécifié
currentLes nouveaux dossiers DOIVENT utiliser ce ValueSet. Les données historiques ou provenant de sources externes peuvent utiliser d'autres codes

Objectifs d'orientation

ObjectifSignification
minimumToutes les applications conformes doivent accepter ces codes comme valides (obligation d'application, pas contrainte d'instance)
candidatePeut remplacer le ValueSet principal dans des situations documentées (p. ex., une juridiction définit un remplacement)
preferredCe ValueSet est préféré dans un contexte donné (la documentation doit expliquer pourquoi)
uiCodes suggérés pour la sélection dans l'interface utilisateur
starterUn sous-ensemble pratique pour commencer lorsque le ValueSet complet est trop volumineux
componentDocumente comment une partie du ValueSet principal est utilisée (p. ex., par système de codes)

R6 ajoute current-extensible (sémantique extensible pour les nouvelles données), best-practice (signalé en mode de validation des meilleures pratiques) et open (aucune restriction, à des fins de documentation).

L'objectif maximum existe dans R5 mais est déprécié dans R6. Il était initialement destiné à plafonner les liaisons extensibles, mais sa sémantique n'était pas claire (voir la saga Extensible+Max ci-dessus). Utilisez plutôt required avec un contexte d'utilisation.

À travers les versions FHIR

VersionFonctionnement des liaisons supplémentaires
R4 et antérieuresPas natif. Utilisez l'extension additional-binding du Tooling Extensions IG. L'IG Publisher les affiche ; le validateur les prend en charge. Les anciennes extensions maxValueSet et minValueSet fonctionnent encore, mais sont supplantées.
R5Natif comme ElementDefinition.binding.additional. Prise en charge complète par le validateur. Pas d'élément key — la contrainte des liaisons supplémentaires dans les profils dérivés est limitée.
R6Natif + élément key pour la contrainte à travers les couches de profils. Nouveaux objectifs : current-extensible, best-practice, open. maximum déprécié.

Pour les IG R4, les liaisons supplémentaires sont exprimées comme extension sur ElementDefinition.binding :

binding:
  strength: extensible
  valueSet: http://hl7.org/fhir/ValueSet/observation-codes
  extension:
    - url: http://hl7.org/fhir/tools/StructureDefinition/additional-binding
      extension:
        - url: purpose
          valueCode: current
        - url: valueSet
          valueCanonical: http://example.org/ValueSet/2026-codes
        - url: documentation
          valueMarkdown: Required for new records.

Dans R5+, la même chose s'exprime nativement — aucune enveloppe d'extension n'est nécessaire.

Scénarios

Conformité multijuridictionnelle

Un profil international nécessite des systèmes de codes différents selon les pays — SNOMED CT aux États-Unis, ICD-10-GM en Allemagne. Avant les liaisons supplémentaires, cela impliquait soit des profils distincts par juridiction, soit un slicing complexe. Vous pouvez maintenant l'exprimer dans un seul profil en utilisant required + any: true + usage :

binding:
  strength: extensible
  valueSet: http://hl7.org/fhir/ValueSet/condition-code
  additional:
    - purpose: required
      valueSet: http://example.org/ValueSet/us-snomed-conditions
      any: true
      usage:
        - code: { code: US, system: urn:iso:std:iso:3166 }
      documentation: US jurisdiction — at least one SNOMED CT coding required.
    - purpose: required
      valueSet: http://example.org/ValueSet/de-icd10gm-conditions
      any: true
      usage:
        - code: { code: DE, system: urn:iso:std:iso:3166 }
      documentation: German jurisdiction — at least one ICD-10-GM coding required.

Trois fonctionnalités travaillent ensemble ici : required rend la liaison applicable, any: true signifie « au moins un Coding doit correspondre » (pas tous — vous pouvez donc envoyer d'autres codings en parallèle), et usage délimite chaque liaison à sa juridiction. Un système américain ne voit que l'exigence SNOMED ; un système allemand ne voit que ICD-10-GM. La liaison extensible principale s'applique aux deux.

Migration de données historiques

Un problème courant : un pays passe à un nouveau standard de codification, mais les hôpitaux ont des décennies de données dans l'ancien format. Sans liaisons supplémentaires, vous devez choisir — soit la liaison est assez souple pour les données historiques (et vous perdez la conformité pour les nouvelles données), soit elle est stricte pour les nouvelles données (et les anciens dossiers échouent à la validation).

Les liaisons supplémentaires résolvent ce problème avec current + minimum :

binding:
  strength: extensible
  valueSet: http://hl7.org/fhir/ValueSet/condition-code
  additional:
    - purpose: current
      valueSet: http://example.org/ValueSet/icd-11-conditions
      documentation: >
        All new diagnoses captured after 2026-01-01 must use ICD-11.
    - purpose: minimum
      valueSet: http://example.org/ValueSet/icd-10-icd-11-conditions
      documentation: >
        Systems must accept both ICD-10 and ICD-11 codes.

La liaison principale reste large (condition-code — extensible). La liaison current dit : « dorénavant, utilisez ICD-11. » La liaison minimum dit : « mais chaque système conforme doit encore accepter ICD-10 dans les données entrantes. » Aucune ne remplace la liaison principale — elles ajoutent de la précision là où l'ancien modèle n'offrait qu'un seul levier.

Liaisons dépendantes de la catégorie (SDOH)

Il s'agit d'un patron réel tiré des profils US Core SDOH. Condition.code est lié à un ValueSet large, mais différentes catégories reçoivent des liaisons plus strictes — si la catégorie est food-insecurity, le code doit provenir du VS SDOH Food Insecurity Diagnoses ; si housing-instability, d'un autre VS. Chaque liaison supplémentaire utilise usage pour délimiter par valeur de catégorie :

# Condition.code
binding:
  strength: required
  valueSet: http://hl7.org/fhir/us/core/ValueSet/us-core-condition-code
  additional:
    - purpose: required
      valueSet: http://hl7.org/fhir/us/sdoh/ValueSet/food-insecurity-diagnoses
      usage:
        - code: { code: food-insecurity, system: http://hl7.org/fhir/us/sdoh/CodeSystem/sdoh-category }
      documentation: >
        When Condition.category = food-insecurity,
        code must come from this ValueSet.
    - purpose: required
      valueSet: http://hl7.org/fhir/us/sdoh/ValueSet/housing-instability-diagnoses
      usage:
        - code: { code: housing-instability, system: http://hl7.org/fhir/us/sdoh/CodeSystem/sdoh-category }
      documentation: >
        When Condition.category = housing-instability,
        code must come from this ValueSet.

Le contexte usage ici n'est pas une juridiction — c'est une catégorie clinique au sein de la même ressource. Le validateur vérifie : si la Condition a category = food-insecurity, alors la liaison supplémentaire pour la sécurité alimentaire s'applique et code doit provenir de ce ValueSet précis. Si la catégorie ne correspond pas, la liaison est ignorée. Comme Grahame l'a confirmé : « si votre catégorie est l'une des catégories désignées, alors le ValueSet pour cette catégorie s'applique. »

Indications d'interface pour les grands ValueSets

Toutes les liaisons supplémentaires ne concernent pas la conformité. Les objectifs ui et starter n'ont aucune valeur de validation — ils aident les développeurs à créer de meilleures interfaces. Un profil de signes vitaux peut avoir plus de 100 000 codes LOINC dans sa liaison extensible, mais l'interface utilisateur n'en a besoin que d'une poignée :

# Observation.code (vital signs)
binding:
  strength: extensible
  valueSet: http://hl7.org/fhir/ValueSet/observation-vitalsignresult
  additional:
    - purpose: starter
      valueSet: http://example.org/ValueSet/common-vitals
      documentation: >
        15 most common vital sign codes. Start here
        if you're building a new system.
    - purpose: ui
      valueSet: http://example.org/ValueSet/vitals-picker
      documentation: >
        Curated list optimized for dropdown selection.
        Not a conformance constraint.

L'objectif starter dit « commencez votre implémentation avec ces codes ». L'objectif ui dit « affichez ces codes dans un sélecteur ». Aucun des deux n'affecte la validation — un système peut envoyer tout code valide selon la liaison extensible principale. Mais ils résolvent un vrai problème : les développeurs qui se retrouvent devant un ValueSet de 100 000 codes sans savoir par où commencer.

Encore en évolution

Le mécanisme est mature, mais la communauté continue de résoudre des cas limites. Aussi récemment qu'à la fin de 2025, Eric Haas a écrit : « Nous avons discuté de ce sujet au WGM, et en tant que concepteur de profils, je suis toujours perplexe quant au fonctionnement prévu des liaisons supplémentaires. » Lui et Gay Dolin créent une matrice de cas d'utilisation explicites avec des exemples pour le FHIR Guidance IG. Les principaux aspects en cours d'affinement :

  • Liaisons conditionnelles — utiliser usage (UsageContext) pour délimiter les liaisons par juridiction ou flux de travail est puissant mais complexe en pratique (66 messages et en progression).
  • Comportement du validateur — la façon dont les violations sont signalées varie selon l'objectif : required produit des erreurs, les objectifs d'orientation comme starter et ui sont purement informatifs.

Références et discussions communautaires

Spécification :

Communauté (chat.fhir.org) :

Voir aussi : Catégories résiduelles en Terminology FHIR.

Partager cet article
Comments
Comments
Sign in
Loading comments...
Subscribe to our blog

Get the latest articles on FHIR, interoperability, and healthcare IT.