Перейти к основному содержимому

Правила Строгой Типизации Документации

Назначение

Документ фиксирует стандарт полной типизации для API, entities, replicas, events, consumers, search documents, ClickHouse facts, JSONB document models и frontend view models. Он дополняет Правила написания документации и обязателен для новых и изменяемых файлов.

Принцип Полной Типизации

Документация является контрактом для разработки, тестирования, интеграций и сопровождения. Каждый внешний и внутренний контракт описывается строго типизированно, явно и воспроизводимо.

  • Запрещены абстрактные типы object, json, jsonb, payload, metadata, settings, data, attributes, parameters, context, если рядом нет полной таблицы полей этой модели.
  • Любая request/response model, view model, command, query, event payload, aggregate snapshot, replica, search document, ClickHouse fact и JSONB document model имеет имя модели и таблицу полей.
  • Nested object описывается отдельной именованной моделью в том же файле или отдельным файлом models/<feature-group>/<model>.md.
  • Коллекция описывает тип элемента, максимальный размер или paging/partition rule, порядок сортировки и правила усечения.
  • Enum описывает все допустимые значения, смысл каждого значения, fallback для неизвестного значения и совместимость при добавлении новых значений.
  • Decimal, money, rates, time, identifiers и reference values описываются доменными типами, а не строкой без правил.
  • Если модель хранится в PostgreSQL jsonb, Elasticsearch document, ClickHouse table или Kafka event, ее схема документируется с версией, правилами совместимости, ограничениями размера и security notes.
  • Документация не должна оставлять "договоримся при реализации": nullable behavior, masks, permission checks и observability описываются до разработки.

Справочные Идентификаторы

Центральный справочник платформы — сервис handbook (pin.handbook, ACL-реплика Talent Handbook, ADR-0063): source of truth для стран, регионов, городов, валют и языков. В доменных моделях и API контрактах используются stable identifiers справочника — id источника Talent Handbook, не Guid: CountryId, CurrencyId, LanguageIdshort; RegionId, CityIdlong (коллекции — CountryIds, CurrencyIds, RegionIds и т.п. с теми же типами элементов).

  • CurrencyCode, LanguageCode, CountryCode не используются как основной доменный ключ в новых документах.
  • ISO-коды (IsoCode2/IsoCode3 стран и языков, IsoCode ISO-4217 валют) — атрибуты записей справочника handbook, а не доменные ключи контрактов. Вне handbook код справочника может появляться только внутри snapshot-модели или в adapter-specific модели внешнего провайдера.
  • События и snapshots, которым нужен человекочитаемый или исторический контекст, включают snapshot-модели справочника: CurrencySnapshot, CountrySnapshot, RegionSnapshot, CitySnapshot — единый дом моделей: handbook/domain/snapshots.md. Snapshot фиксируется на момент публикации; события с денежными суммами несут CurrencyId + CurrencySnapshot. Snapshot-модель языка не вводится: языки — реплика без текущих потребителей.
  • Любая фильтрация по валюте, стране, региону, городу или языку использует id справочника.
  • Lookup методы возвращают ResultEntry.Id как id справочника, а код помещают в явно описанное поле ответа или Description.
  • При миграции старого документа с xxxCode нужно заменить контракт на xxxId и указать compatibility note для consumers/readers.

Минимум Для Модели

Каждая модель содержит:

РазделЧто Описать
НазначениеГде и зачем используется модель.
ПоляИмя, тип, обязательность, описание, ограничения, источник значения.
ВалидацияMin/max, формат, допустимые состояния, cross-field rules.
Nullable behaviorКогда поле отсутствует, когда равно null, кто видит значение.
SecurityМаскирование, запрет secrets/PII, audit sensitivity.
СовместимостьВерсия, additive changes, fallback для unknown enum.

Структурированные Модели Вместо Плоских Полей

Плоские наборы полей, которые семантически образуют один объект, документируются одной вложенной моделью. Правило обязательно для трёх повторяющихся случаев.

Диапазоны — единое понятие, а не пара *Min/*Max

  • Пара границ одного значения описывается как единое понятие «диапазон» (нижняя и верхняя граница одного поля), а не двумя плоскими полями *Min/*Max или *From/*To.
  • Пример: цена лота — диапазон price (одно поле с нижней и верхней границей), а не пара priceMin + priceMax. Аналогично площадь area и этаж floor.
  • Для каждого диапазона фиксируются: включительность границ, смысл открытой границы (нет ограничения с этой стороны) и признак «диапазон не задан» (фильтр не применяется).
  • Диапазон дат описывается тем же понятием: либо с обязательными обеими границами, либо открытый по одной стороне.

Пара «id + name» — именованная ref-модель

  • Пара «идентификатор + отображаемое имя» одной сущности выносится во вложенную именованную ref-модель с ПОЛНЫМИ именами полей, а не в две плоские колонки корня.
  • Пример: developer: DeveloperRefModel { DeveloperId: Guid; DeveloperName: string } вместо плоских developerId: Guid + developerName: string.
  • Правило распространяется на все ссылки на сущности: project: ProjectRefModel, building: BuildingRefModel, layout: LayoutRefModel.
  • Полные имена полей внутри ref-модели (DeveloperId, а не Id) сохраняются намеренно — модель читается вне контекста родителя (в событиях, snapshot, view model).
  • Ref-модель может нести дополнительные stable-поля (Slug, IsoCode), но не тянет полный агрегат.

Группа связанных полей — под-модель

  • Набор полей, описывающих один аспект сущности, выносится в отдельную именованную под-модель, а не рассыпается по корню request/response.
  • Пример: характеристики планировки объекта — layout: PropertyObjectLayoutModel { RoomCount; TotalArea; LivingArea; KitchenArea; Floor; ... }, а не плоские roomCount + totalArea + livingArea + ... в корне.
  • Под-модель описывается по минимуму для модели: поля, валидация, nullable behavior, совместимость.

Запрещенные Упрощения

  • "Поле содержит произвольный JSON".
  • "Структура зависит от типа и будет уточнена при реализации".
  • "Metadata для UI".
  • "Payload provider-а сохраняется как есть".
  • "Список ids в JSONB".
  • "Currency code в контракте, потому что так проще для фронта".
  • "Плоские priceMin/priceMax или dateFrom/dateTo вместо единого понятия «диапазон»".
  • "Плоские developerId + developerName вместо DeveloperRefModel".

Если контракт действительно расширяемый, он описывается через typed union, versioned model или bounded list of typed entries с перечислением допустимых ключей.

Связанные Правила

Обратные ссылки

Автоссылки: где используется этот документ.