FHIR-моделирование структурно похоже на Domain-Driven Design (DDD) — software-engineering подход к моделированию сложных предметных областей. Параллель не случайна: оба моделируют medical/business reality и пришли к похожим primitives.
Эта страница — placeholder для исследования (status: draft). Зафиксирована по триггеру обсуждения fhir-basics § «Resource vs DataType».
Resource vs DataType ≈ Entity vs Value Object
| FHIR | DDD | Свойства |
|---|---|---|
| Resource (Patient, Observation, Composition) | Entity | имеет identity (URL/ID), lifecycle, версионируется, ссылается-на и ссылаемый |
| DataType (HumanName, CodeableConcept, Reference, Period) | Value Object | identity нет, определяется атрибутами, conceptually immutable, существует только внутри родителя |
Пример: Patient — Entity (Patient/123, история через _history, обновляется PUT’ом). Patient.name — Value Object типа HumanName (нельзя сослаться на name отдельно от patient’а; если имя поменялось — это новый HumanName внутри того же Patient).
Ключевая DDD-идея: Entity persists, Value Object replaces. То же в FHIR — Resource обновляется PUT’ом с тем же ID; DataType-поле просто пере-сериализуется внутри Resource без отдельной identity.
Ubiquitous Language ≈ coding systems + IG vocabulary
DDD требует, чтобы команда (developers + domain experts) использовала один словарь в коде, документации, разговорах — без переводов вида «у нас в коде это userId, а в бизнесе клиент». Буферы перевода создают непонимание и баги.
FHIR продвигает аналогичный принцип:
- Coding systems (loinc для лабораторных тестов, snomed для клинических концептов, RxNorm для лекарств) — терминология одинаково понимается всеми участниками индустрии.
- IG vocabulary (us-core, rucore, IPS) — каноническое значение «
Patient.identifierсsystem=http://hl7.org/fhir/sid/us-ssnэто SSN».
В практике BloodGPT: код, документация, обсуждения используют FHIR-словарь напрямую (Observation, DiagnosticReport, Composition.section) — не наш собственный slang.
Bounded Context ≈ FHIR profiling / IGs
DDD: каждая domain model живёт в bounded context — границе, где термины и правила консистентны. Между bounded contexts — explicit translation (anti-corruption layer).
FHIR: базовый стандарт намеренно нейтрален; конкретные регионы / use cases выпускают Implementation Guides (IGs) — US Core, RuCore, IPS, mCODE — где общие FHIR resources профилированы под локальные правила. См. fhir-profiling.
В BloodGPT мы пишем в vanilla R4 + опираемся на US Core conventions для интероперабельности (не строгий IG-conformance, а usage-pattern).
Anti-corruption layer ≈ интеграция с не-FHIR системами
DDD: когда наш bounded context взаимодействует с чужим (legacy DB, external API) — между нами и им стоит anti-corruption layer, переводящий чужие модели в наши термины.
В BloodGPT эту роль играют:
- recognition — превращает unstructured PDF/image в FHIR
- B2B HL7v2 input pipeline — переводит legacy HL7v2 в FHIR
- LOINC normalization — переводит lab-vendor-specific test codes в LOINC
Все эти слои нормализуют внешние представления в наш FHIR-моделируемый «bounded context».
Aggregate ≈ FHIR Composition / Bundle (частично)
DDD: aggregate — кластер entities + value objects с одним aggregate root, через который только и можно изменять что-то внутри. Гарантирует консистентность.
FHIR частично похоже:
- Composition — clinical document с фиксированной структурой sections, single author, atomic update. См. fhir-composition.
- Bundle type=document — sealing aggregate’а (Composition + referenced resources в одном «package»).
Граница не точная (FHIR разрешает Observations жить и без Composition), но pattern узнаваемый.
Что отличается
- DDD — методология, FHIR — стандарт. DDD говорит «как моделировать». FHIR говорит «вот конкретная модель».
- DDD не предписывает versioning / format / wire-protocol. FHIR предписывает (XML/JSON, HTTP REST, search syntax,
_history). - FHIR resources заранее определены (~150 типов в R4 core). DDD — каждая компания определяет свои aggregates.
- DDD bounded contexts могут быть любыми. FHIR profiling — внутри fixed resource shapes (нельзя добавить новый resource type, только slicing / extensions).
Что полезно знать
Если кто-то из команды знаком с DDD — FHIR-моделирование быстро ложится: Resource = Entity, DataType = Value Object, IG = Bounded Context. И обратно: знание FHIR помогает интуиции для DDD primitives при работе с не-FHIR domain’ами.
Открытые вопросы
- Aggregate-границы в нашей FHIR-store — где разумно говорить «Composition aggregate-root для AI-output»? Это поможет дисциплине write-paths (всегда через Composition vs прямой Observation update).
- Bounded context boundaries в BloodGPT — какие у нас есть? Recognition, enrichment, b2b-platform, b2c-portal — каждое своё? Или это всё один context?
Связано
- fhir-basics — FHIR primer (Resource vs DataType — там короткое введение, здесь — параллель с DDD)
- fhir-profiling — IGs как bounded contexts
- us-core — наш de-facto IG
- loinc, snomed — ubiquitous language в действии