Почему технический долг в автоматизации отличается от обычного технического долга
В 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 накапливается незаметно, по одному компоненту за раз, поэтому и устранять его нужно незаметно — не в большом проекте по очистке, который останавливает разработку на месяц. Необходимые инструменты относительно просты: подсчет компонентов по объектам, отображение порядка выполнения и классификация по бизнес-влиянию относительно вероятности сбоя. Успех определяется непрерывностью — выделением постоянного ресурса для сокращения долга наряду с текущей разработкой, а не точечным устранением компонента, вызвавшего последний сбой. Организация, которая принимает такую практику измерения, достигает состояния, когда любой новый разработчик может за час понять, что происходит при сохранении записи — и это, в конечном итоге, самое практичное определение отсутствия технического долга.
