Почему технический долг в автоматизации отличается от обычного технического долга

В Salesforce накопить технический долг проще, чем в обычной среде разработки, поскольку платформа позволяет любому добавлять автоматизацию без прохождения упорядоченного процесса кодирования. Любой администратор, добавляющий Flow Before Save для решения точечной проблемы, любой триггер, который кто-то добавил два года назад и никто не помнит, зачем, и любое поле формулы, зависящее от уже несуществующего поля — все это накапливается в слое, который никто не видит целиком.

Фундаментальное различие между обычным техническим долгом и техническим долгом в автоматизациях Salesforce заключается в том, что последний почти всегда не имеет централизованной документации. Код хранится в репозитории с историей коммитов; Flow находится в настройках без объяснения причин его создания. Это делает этап идентификации экстремально сложным – не потому что проблема технически сложна, а потому что не у кого спросить.

Эта статья посвящена выявлению, измерению и сокращению этого долга. В ней не обсуждается вопрос о том, когда изначально выбирать Flow и когда Apex — этому посвящена статья Flow против Apex: как выбирать.

Три типа долга, которые ведут себя по-разному

Не весь технический долг одинаков, и однообразное отношение ко всем проблемам приводит к напрасной трате усилий. Целесообразно разделить долг на три категории:

Тип долгаТипичный примерЧто произойдет, если игнорироватьПриоритет устранения
Структурный долгНесколько триггеров на одном объекте без унифицированного фреймворкаНепредсказуемый порядок выполнения, скрытый сбойВысокий
Логический долгFlow с десятками ветвей решений, представляющий бизнес-правило, которое уже изменилосьОшибочные решения, выполняющиеся незаметноВысокий
Эксплуатационный долгПоля, Flow и константы без документации или использованияУвеличение времени разработки, страх вносить измененияСредний

Структурный и логический долг создают реальный операционный риск — они могут привести к неверным данным, поступающим клиентам или в финансовые отчеты. Эксплуатационный долг замедляет работу команды, но не обязательно нарушает процесс. Это разделение определяет порядок действий: сначала устраняется операционный риск, затем улучшается скорость разработки.

Как выявить долг до того, как он проявится на этапе производственной эксплуатации

Идентификация не должна начинаться с трудоемкого ручного обзора кода — это слишком дорого и неустойчиво. Она начинается с нескольких количественных показателей, которые можно получить в течение часа:

  • Количество активных Flows на каждом из ключевых объектов (Lead, Opportunity, Case и т. п.). При наличии более пяти-шести активных Flows на одном объекте порядок выполнения становится трудно предсказуемым.
  • Количество триггеров, не объединенных в единый фреймворк, для каждого объекта. Более одного триггера на объект уже является предупреждающим знаком, если только нет явного уровня маршрутизации.
  • Плотность SOQL-запросов внутри циклов, проявляющаяся в логах как приближение к лимитам Governor, даже если они фактически не превышены.
  • Необычное время выполнения Flow или Apex Batch, которое увеличивается со временем без пропорционального роста объемов бизнеса.
  • Поля и переменные, не имеющие идентифицированного использования в отчете Field Usage, которые остаются «на случай, если кому-то понадобятся».

Эти метрики не доказывают однозначную проблему, но они предоставляют сфокусированный список подозреваемых. Их сочетание с глубоким пониманием интеграций, от которых зависит автоматизация, подробно описано в Шаблоны интеграции Salesforce.

Рамочное решение: что обрабатывать в первую очередь

Не все элементы в списке подозреваемых требуют одинаковых инвестиций. Простая система приоритизации основана на двух осях — влиянии на бизнес и вероятности сбоя:

СитуацияБизнес-влияние в случае сбояВероятность сбоя в ближайшем будущемДействие
Автоматизация процесса заказа/выставления счетов с множеством недокументированных триггеровВысокоеВысокаяНемедленный рефакторинг, вне обычного графика
Сложный Flow на внутреннем обновлении статуса без внешнего воздействияНизкоеВысокаяДокументирование и упрощение в обычном темпе
Старый триггер, который работает стабильно, но его назначение неясноПотенциально высокоеНизкаяСначала документирование, немедленно не трогать
Неиспользуемые поля и осиротевшие константыНизкоеНизкаяПериодическая очистка на уровне релиза

Основное правило: не следует решать проблемы, исходя из того, что больше всего беспокоит разработчиков, а ориентироваться на то, что наиболее опасно для бизнеса. Старый и стабильный триггер, который никто не понимает, иногда является самым заманчивым объектом для устранения первым — и это именно тот случай, когда неосторожное вмешательство приводит к наибольшему ущербу.

Организационный сценарий: страховая компания с 14 Flows на Opportunity

Предположим, средняя страховая компания управляет B2B продажами через Salesforce уже шесть лет. За это время накопилось 14 активных Flows на объекте Opportunity: семь обрабатывают обновления этапов, три отправляют внутренние уведомления, два синхронизируют данные с внешним инструментом BI, и еще два являются остатками старого процесса, который был заменен два года назад, но никогда не был деактивирован.

Поводом для выявления проблемы стал конкретный сбой: сделка перешла в статус «Закрыто-Выиграно», но уведомление команде андеррайтеров не было отправлено, потому что другой Flow одновременно обновил то же поле и создал незапланированную последовательность выполнения. Команда провела два дня, пытаясь понять, почему — не потому что баг был сложным, а потому что никто не знал полного порядка выполнения всех 14 компонентов.

Решение не заключалось в «переписывании всего с нуля на Apex». Команда сначала отобразила все 14 Flows и классифицировала их согласно приведенной выше таблице: два старых Flows были отключены после проверки отсутствия активных зависимостей, три уведомления были объединены в один Flow с четкой логикой маршрутизации, а семь обновлений этапов были объединены под одним Record-Triggered Flow с явно заданным порядком выполнения. Результат: от 14 компонентов до 6, с документированным порядком выполнения, который любой новый разработчик может понять за четверть часа.

Риски в процессе сокращения

Сокращение технического долга — это действие, связанное со своими собственными рисками, а не только исправление существующего риска:

РискКак он выглядит на практикеМеры предотвращения
Изменение порядка выполнения нарушает скрытую зависимостьПроцесс, который работал, перестает работать после объединения FlowsПолное отображение зависимостей и регрессионное тестирование перед каждым объединением
Удаление "мертвого" компонента, который на самом деле все еще выполняется в редком сценарииОтказ, проявляющийся только в конце квартала или в сезонном крайнем сценарииПроверка журналов выполнения за полный год, а не только за последний месяц
Преобразование в Apex без владельца процесса, понимающего бизнес-правилоНовый код "технически правильный", но реализует старое правило, которое уже изменилосьПроверка бизнес-правила с владельцем процесса перед написанием кода, а не только по существующему коду
Рефакторинг, выполненный в одной песочнице и не синхронизированныйПроблема возвращается в производственной среде после следующего развертыванияУправление изменением через обычный процесс релиза, а не как "внеплановое" исправление

Общим риском для всех является одно и то же явление: команда уверена, что она «просто убирается» и поэтому пропускает тесты, которые она провела бы для новой функции. На уровне управления рефакторинг должен пройти тот же процесс приемки, что и обычная разработка — не меньше.

Показатели для постоянного мониторинга сокращения

Чтобы убедиться, что усилия действительно уменьшают долг, а не просто перемещают его, стоит отслеживать следующее:

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

Организации, которым трудно расставлять приоритеты между рефакторингом и текущей разработкой, используют услугу CRM-архитектуры для создания обязательного и измеримого плана работ.

Операционный чек-лист перед началом рефакторинга

  • ☐ Существует полная карта всех активных автоматизаций на соответствующем объекте.
  • ☐ Известен фактический порядок выполнения, а не только порядок создания.
  • ☐ Каждый компонент, предназначенный для удаления, проверен по журналам выполнения за полный год.
  • ☐ Владелец бизнес-процесса утвердил заново реализуемое правило.
  • ☐ Существует тестовая среда, имитирующая реальный объем данных.
  • ☐ Определены метрики «до и после» для количества компонентов и времени диагностики.
  • ☐ Процесс рефакторинга проходит через обычный релиз, а не через внеплановое развертывание.
  • ☐ В каждом спринте выделена постоянная емкость для непрерывного обслуживания, а не только для разового события.

Заключение

Технический долг в автоматизациях Salesforce накапливается незаметно, по одному компоненту за раз, поэтому и устранять его нужно незаметно — не в большом проекте по очистке, который останавливает разработку на месяц. Необходимые инструменты относительно просты: подсчет компонентов по объектам, отображение порядка выполнения и классификация по бизнес-влиянию относительно вероятности сбоя. Успех определяется непрерывностью — выделением постоянного ресурса для сокращения долга наряду с текущей разработкой, а не точечным устранением компонента, вызвавшего последний сбой. Организация, которая принимает такую практику измерения, достигает состояния, когда любой новый разработчик может за час понять, что происходит при сохранении записи — и это, в конечном итоге, самое практичное определение отсутствия технического долга.