Интегрировать две и более системы - это вам не легкая прогулка томным субботним вечером. Через эти системы могут проходить критически важные данные: платежи, логистика, уведомления, идентификация и многое другое. И именно на стыках между системами возникают ошибки, которые очень часто трудно воспроизвести и очень дорого исправлять.
Многие из этих ошибок происходят не на уровне кода, а гораздо раньше - в момент, когда аналитик формулирует требования. Непродуманная логика, отсутствие контракта, игнорирование сбоев - всё это закладывает возможную нестабильность в сам фундамент архитектуры.
Каждый случай уникален. Каждый случай достоин отдельной публикации. Но сейчас хочу поделиться с тобой, начинающий системный аналитик, одними из самых часто распространенных ошибок при проектировании, которые я находил на этапе ревью.
Не поверхностно, а с разбором боевых кейсов, с примерами и выводами, которые можно вполне себе использовать, как чек-лист. Чтож! Щас выскажусь!)
Отсутствие чёткого контракта: не договорённость, а недоговорённость
Передача данных без описанного и согласованного контракта приводит к расхождению в ожиданиях, ошибкам типизации и ошибкам. Формат обмена (например, JSON) не гарантирует согласованность типов, обязательности полей и значений по умолчанию.
Если не определена структура, типы, обязательность и допустимые значения, то вы не интегрируетесь, а играете в угадайку.
Почему это происходит:
Описание только в виде примеров JSON. Нет формальной спецификации (OpenAPI, JSON Schema), фиксирующей поля, типы, обязательность и структуру вложенности.
Типы данных не указаны явно. Например, поле amount используется как number, но в одном случае это float, в другом - string, в третьем - null.
Обязательные поля не размечены. В документации не указано, какие поля являются
required
, и какая логика применяется при их отсутствии.Контракт не синхронизирован с кодом. Актуальный формат запроса/ответа расходится с документацией. Спецификация не обновляется при изменениях.
Пример:
Система передаёт объект payment. В поле payment.amount иногда попадает значение null, потому что в редких случаях сумма рассчитывается позже. Получающая вторая система не ожидает null. У неё нет обработки такого случая, и валидация падает.
Если контракта нет, то вся интеграция будет держаться на удаче. Проще подкинуть монетку - результат будет аналогичный.
Отсутствие обработки ошибок и нестабильных сценариев
Интеграция без сценариев обработки ошибок считается надёжной только на этапе тестирования. В реальности сервисы могут быть временно недоступны, возвращать коды 4xx/5xx, отвечать с задержкой или не отвечать вовсе. Если такие ситуации не предусмотрены в требованиях, то система начинает работать непредсказуемо.
Почему это происходит:
Фокус аналитика на основном (успешном) сценарие.
Обработка ошибок воспринимается как «техническая деталь реализации».
Отсутствуют требования к логике retry, таймаутов.
Нет fallback-стратегии. Не предусмотрено переключение на альтернативный источник.
Пример:
Сервис расчёта бонусов обращается к справочнику контрагентов другого сервиса. Во время кратковременной деградации сервис недоступен. Сервис расчета бонусов блокируется при каждом обращении. Аналитик не описал сценарий временной недоступности, не задал предел ожидания и не предусмотрел поведение при ошибке.
Система должна уметь управлять нестабильностью. Если сценарий отказа не описан - это проектная ошибка и прямая вина аналитика, а не баг реализации.
Неопределённость семантики
Каждое передаваемое значение в интеграции должно иметь чётко определённую семантику и задокументированное поведение на стороне получателя. Если поле воспринимается как флаг, команда или индикатор состояния, оно должно сопровождаться описанием.
Отсутствие такой спецификации приводит к расхождению в трактовке. Система-источник и система-приёмник по-разному интерпретируют значение одного и того же поля. Это приводит к скрытым логическим ошибкам, которые могут быть не выявлены на этапе тестирования
Почему это происходит:
Семантика не описана в контракте. Например,
status: string
без указания допустимых значений.Нет сопоставления справочников между системами. В системе A
status = "completed"
, в системе B -status = "done"
, но соответствие не описано.
Пример:
Поле
status = "closed"
не описано в контракте. В одной системе это значит "неактивен, можно восстановить", в другой — "удалён безвозвратно". Отсутствие единой семантики превращает передачу данных в источник ошибок.
Каждое передаваемое поле в интеграции должно иметь фиксированное описание: допустимые значения, контекст использования, влияние на принимающую систему. Если семантика поля не определена в спецификации, его обработка становится неконтролируемой.
Отсутствие управления изменениями интерфейса
Без версионирования любое изменение может разрушить прод. Аналитик должен заранее определить правила, что считается breaking change, как вносится новая версия, как уведомляются потребители.
Почему это происходит:
Breaking changes вносятся без объявления. Удаление или переименование поля не сопровождается уведомлением потребителей.
Нет политики обратной совместимости. Не определено, какие изменения допускаются без смены версии, а какие требуют новой версии API.
Контракт изменяется напрямую. Спецификация обновляется «поверх» старой, не фиксируется история изменений.
Пример:
В начальной версии API поле цены передавалось как числовое значение. Позже структура была изменена: вместо числа стал использоваться вложенный объект с валютой и суммой. Обновление внесли без смены версии API.
Мобильное приложение, не готовое к новой структуре, не смогло корректно отобразить цену. Пользователи столкнулись с пустыми экранами и недоступностью части функциональности.
Любые изменения в структуре или логике API должны сопровождаться версионированием. Отсутствие версионирования делает поддержку и развитие API неконтролируемым процессом.
Отсутствие архитектурного решения по владению данными
В распределённых системах одни и те же данные часто находятся в разных системах. Если не определено, где находится источник истины и кто имеет право обновлять данные, то возникают конфликты.
Почему это происходит:
Атрибуты сущности хранятся и обновляются в нескольких системах. Например, email пользователя меняется и в CRM и в системе рассылок.
Нет правил разрешения конфликтов. В случае расхождения значений в разных системах не определено, какое значение приоритетное и по какому алгоритму выбирается.
Контроль целостности распределённых данных не входит в модель интеграции. Актуальность, согласованность и задержка синхронизации не рассматриваются как часть требований
Механизм синхронизации между системами не реализован. Изменения не логируются и не отслеживаются. Нет ни CDC, ни событийной модели, ни регламентной репликации.
Пример:
Атрибут
В любой интеграции должна быть зафиксирована роль master-системы: кто хранит, кто обновляет, кто синхронизирует. Без этого нет целостности данных.
Что в итоге
Интеграция - это не просто гонять данные между системами. Это точка пересечения архитектурных решений, контрактных обязательств, логики обработки данных и устойчивости процессов. Ошибки системного аналитика здесь не видны на этапе сбора требований, но проявляются на проде в виде несогласованностей, сбоев и логических конфликтов. Очень часто исправление этих огрехов обходится очень дорого.
Я веду свой ТГ канал #ЯЖАНАЛИТИК, в котором рассказываю о буднях системного аналитика, околоITшной жизни, описываю кейсы, лайфхаки, рабочие неудачи и все то , что тебе потребуется для работы. Простым и доступным языком. Без нудятины и духоты (ну может быть совсем чуть-чуть).