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

Как сохранять данные согласованными

Также доступно на 28 языках

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Svenska · Dansk · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

An old five-rung wooden ladder against a barn wall, its lowest rungs worn smooth from use and its top rungs barely touched.
Изображение создано с помощью ИИ

Модуль 9 из 10 главы Архитектура данных Salesforce, глава 3 курса Data Architect. Каждый модуль самостоятелен. Назад: Владение и жизненный цикл · Далее: Спроектируйте физическую модель Salesforce

Вопрос, на который отвечает этот модуль: как сохранять данные согласованными и сколько стоит каждый уровень?

Все хотят чистые данные. Я ни разу не приходил на встречу по требованиям, где кто-то сказал бы: «Чего мы на самом деле хотим, так это несогласованных данных». Разногласия начинаются позже: где мы применяем правила? На экране? Обязательное поле? Список выбора, правило проверки, правило дубликатов, flow, Apex? Все они помогают. Они не взаимозаменяемы, и у каждого уровня есть цена.

Мое общее правило — опускайте правило настолько низко, насколько это разумно. Если значение может быть только одним из пяти, не позволяйте людям вводить что угодно, чтобы потом чистить это автоматизацией. Если у двух записей никогда не должно быть общего идентификатора, не полагайтесь на то, что кто-то заметит это в отчете. Если правило должно выполняться независимо от того, пришла запись с экрана, через API, из интеграции, загрузки данных или от агента, не применяйте его только в интерфейсе. Чем ближе правило к данным, тем труднее его обойти. Я называю это лестницей согласованности.

Первое правило согласованности — то, что из модуля 6: выбирайте правильный тип. Дата — это Date, момент — Date/Time, деньги — Currency. Это согласованность еще до того, как кто-то написал правило.

Сделайте статус доставки текстовым полем, и вы получите Delivered, delivered, DELIVERED, Complete, Done и Dropped off, и кому-то придется разбираться, означают ли эти шесть одно и то же. Или определите словарь один раз: Delivered, одно значение, один смысл. Сделайте его ограниченным списком выбора, чтобы он отклонял все, чего нет в списке, даже через API, и глобальным набором значений, когда список используют несколько полей (подробности — в модуле 6).

Но не используйте список выбора только для того, чтобы люди не печатали. Это действительно значение или другая сущность? Девять распределительных центров, у каждого только название, могут выглядеть как список выбора; девять с адресами, руководителями, вместимостью и грузовиками — это записи. Правило должно укреплять модель, а не компенсировать плохую. А если это действительно контролируемый словарь, контролируйте его на уровне поля. Не допускайте хаоса, чтобы потом строить flow, превращающий AZ, Arizona, Ariz и Phoenix area в значение, которое вы хотели с самого начала.

Required и Unique привлекательны своей простотой: поставил галочку — проблема решена. Иногда. Если у каждого грузовика есть номер в автопарке с того дня, как его создали, и у двух грузовиков он никогда не совпадает, обе галочки выражают настоящие бизнес-правила. Это сильная согласованность.

Но как только платформа применяет правило, ей все равно, что у вашего процесса есть исключение во вторник после обеда. Я использую этот пример на занятиях годами. Объект существует уже какое-то время, записей в нем много. Кто-то добавляет поле и ставит Required. Тестирует создание записи: все прекрасно работает. Потом субботний вечер, развертывание, запускаются тесты, и старый тестовый класс создает объект без нового поля. Бум. Или кто-то редактирует старую запись, созданную до появления поля. Или интеграция присылает тот же пакет данных, что и пять лет подряд. Бум. «Но мы же не меняли это поле». Платформе все равно: вы изменили контракт того, что такое допустимая запись. Новое правило касается не только новых данных; оно меняет то, что вы можете делать со старыми.

Правила проверки (validation rules) позволяют сказать гораздо больше. Если статус — Delivered, фактическое время доставки должно быть заполнено. Если остановка — это установка, чек-лист должен быть выполнен, прежде чем остановку можно закрыть. Они срабатывают при сохранении записи, поэтому защищают запись, откуда бы ее ни сохранили: со страницы, через API, загрузкой данных, интеграцией или агентом. В этом и смысл. Если правило должно защищать запись, ставьте его там, где с ним встречается каждая запись данных.

И у них есть зубы. В этом их сила и их цена.

Вот где становится некрасиво. У вас миллион записей, и сегодня вы добавляете правило: время доставки не может быть раньше выезда по маршруту. Разумно. Но двадцать тысяч старых записей его нарушают — спасибо миграции семилетней давности. Пользователь открывает одну из них и меняет номер телефона. Сохранить. Правило срабатывает. «Я поменял номер телефона. Почему вы говорите мне о времени доставки из 2019 года?» Справедливый вопрос.

Поэтому правило проверки должно говорить не только что должно быть верно. Оно должно говорить и когда это проверять. Функции вроде ISNEW() и ISCHANGED() позволяют ограничить правило новыми записями или сохранениями, при которых действительно меняются нужные поля (Validation Rule Considerations (opens in a new tab)).

Но запись меняется не только тогда, когда ее редактирует человек, и многие причины вам неподвластны. Интеграция ночью обновляет статус. Flow проставляет дату. Руководитель переназначает территорию, и владелец меняется на десяти тысячах записей. Кто-то редактирует позицию доставки, roll-up на доставке пересчитывается, и это сохраняет доставку, так что правило проверки доставки срабатывает для пользователя, который ее даже не трогал (Roll-Up Summary Field (opens in a new tab) предупреждает, что ошибки проверки могут появиться на подчиненной или главной записи). Каждое из этих сохранений встречается с вашим новым правилом. Поэтому для каждого нового правила спрашивайте: должно ли это правило применяться к этому сохранению?

Вот варианты, и вы вплетаете их в правило:

  • Всегда, при каждом сохранении. Правильно, когда правило действительно касается записи, а старые данные его проходят. Но знайте, что значит «каждое сохранение»: пакетное задание, которое меняет только владельца, или любая мелкая правка любого поля записи тоже должны его пройти.
  • Только для новых записей, с ISNEW(). Правило проверяет запись один раз, при создании, и больше никогда. Прошлое остается как было, но и будущее тоже: последующая правка может заставить новую запись нарушить правило, и никто ее не остановит. Если это важно, сочетайте со следующим вариантом.
  • Только когда меняются поля, о которых оно, с ISCHANGED(). Правка номера телефона не будит правило о времени доставки.
  • Не для определенных источников записи. Пользовательское разрешение (custom permission), проверяемое в формуле как $Permission, пропускает интеграционного пользователя или миграцию данных, тогда как люди по-прежнему встречаются с правилом (How to Reference a Custom Permission in a Validation Rule (opens in a new tab)). Выдавайте его осознанно и немногим.
  • С определенной даты, сравнивая CreatedDate с днем, когда правило вступило в силу, когда «новое» означает «с тех пор, как мы начали это применять». В отличие от ISNEW(), такое правило продолжает проверять эти записи при каждом последующем сохранении, поэтому действует то же предупреждение: мелкое изменение, вроде пакетной смены владельца, может не пройти на записи, которая с тех пор разошлась с правилом.

Добавляете правило к уже существующим записям? Продумайте последствия, прежде чем его включать. Каждая существующая запись теперь должна проходить его при следующем сохранении, а это сохранение может прийти оттуда, откуда вы не ждали: ночная интеграция, пакетная смена владельца, roll-up, массовое обновление из представления списка. Что из этого на него наткнется и что будет с этим заданием, когда одна запись не пройдет? В разделе Прежде чем включать — последовательность, которой я пользуюсь.

Не переписывайте историю в угоду правилу

Заголовок раздела «Не переписывайте историю в угоду правилу »

А как же двадцать тысяч старых записей? Если данные неверны и вы знаете правильные значения, исправьте их. Но я видел и другое «исправление»: никто не знает исторической правды, просто нужно, чтобы записи проходили, поэтому их обновляют значениями, которые удовлетворяют сегодняшнему правилу. Мне это не нравится. Обновление старых записей ради соответствия меняет LastModifiedDate и уничтожает ключевую историческую информацию, а выдумывание значений означает делать вид, что мы знаем о прошлом то, чего не знаем. Дайте правилу обход для записей, созданных до него, вместо того чтобы переписывать историю. Это может быть некрасиво, но это честно.

Проверка в интерфейсе — не проверка данных

Заголовок раздела «Проверка в интерфейсе — не проверка данных »

Сделайте поле обязательным в макете страницы, и пользователи не смогут сохранить без него. Потом ночная интеграция вставляет 50 000 записей. Она пользовалась вашей страницей? Нет. Как и массовая загрузка, клиент API или агент. Требование в интерфейсе защищает этот экран, а не данные. Проверку полей в динамических формах (dynamic forms) можно обойти так же. Поэтому спрашивайте: через какие двери могут войти эти данные? Lightning, портал, мобильное приложение, интеграция, API, массовая загрузка, Flow, Apex, агент. Чем больше дверей, тем меньше я доверяю правилу, которое охраняет только одну из них.

Теперь мы переходим от согласованности внутри записи к согласованности между записями. Acme Corporation, ACME Corp, Acme Inc.: четыре клиента или один? Никакое правило поля на это не ответит. Правила сопоставления (matching rules) определяют, как сравниваются записи; правила дубликатов (duplicate rules) решают, что происходит, когда найден вероятный дубликат: разрешить с предупреждением, заблокировать или сообщить. На объект может быть до пяти активных правил дубликатов и до трех правил сопоставления в каждом, а ключи сопоставления (match keys) сужают каждое сравнение до 100 наиболее вероятных дубликатов (Things to Know About Duplicate Rules (opens in a new tab)).

Их цена — трение. Если на каждую организацию, которую создает менеджер, выскакивает Possible duplicate found, иногда это ровно то, что нужно, а иногда люди учатся прощелкивать, не читая. Законные записи могут быть похожи, а интеграции может требоваться иное поведение, чем человеку. И предупреждение — собственное, от Salesforce: его оповещение и список возможных дубликатов могут не вписаться в построенный вами пользовательский экран, а когда сохранение без интерфейса (headless) — интеграция, загрузка данных, агент, — показать его вообще негде. Поэтому решите, как дубликат проявляется на каждом пути: предупреждение для человека, заблокированное сохранение и ошибка для API или вариант Report и наборы дублирующихся записей, чтобы кто-то разобрал их позже. Хорошая архитектура — это не максимальное применение правил; это правильное применение.

И проверьте, какие двери правило дубликатов на самом деле охраняет (Things to Know About Duplicate Rules (opens in a new tab)). Через API и инструменты импорта предупреждения никто не видит: правило, настроенное на оповещение, просто блокирует сохранение. Некоторые пути полностью обходят правила: Quick Create, кнопка Undelete, ручное слияние, записи, добавленные через Lightning Sync или Einstein Activity Capture. А записи, сохраненные в один и тот же момент, не сравниваются друг с другом, только с записями, которые уже есть в Salesforce. Загрузите файл, где один и тот же клиент встречается дважды, и обе строки могут пройти. Правило дубликатов — хорошая сеть. Но не замок на двери.

Знать к экзамену. Правила дубликатов не сравнивают друг с другом записи, сохраненные в один и тот же момент, только с записями, которые уже есть в Salesforce. Через API и инструменты импорта оповещения нет: дубликат, пойманный правилом, просто не сохраняется. А сохранение и все, что оно запускает, выполняются как одна транзакция: если какая-то часть не удалась, откатывается все.

Одна граница. Правила дубликатов поддерживают чистоту одного org. Задачу идентификации на уровне предприятия они не решают. Если в Salesforce есть Acme Corporation, в ERP — ACME-10382, а в биллинге — клиент 77193, правило дубликатов не скажет вам, что это одна и та же компания. Это мастер-данные, глава 6.

Некоторые правила слишком сложны для нижних ступеней: им нужны связанные записи, другая система, зависимые записи, многошаговый процесс. Это Flow, Apex, иногда логика интеграции. (Не Workflow Rules и не Process Builder; их поддержка прекращена.) Автоматизация мощная и более дорогая: больше движущихся частей, больше тестирования, больше обработки ошибок, больше способов, которыми одна автоматизация может споткнуться о другую. А код приносит свои ошибки. Если это может обеспечить тип поля, я не пишу Apex. Если правило проверки выражает это ясно, я не строю flow только потому, что Flow есть под рукой. Не решайте проблему поля движком процессов.

Все или ничего: когда записи меняются вместе

Заголовок раздела «Все или ничего: когда записи меняются вместе »

До сих пор каждая ступень защищала одно сохранение. Но записи меняются вместе: доставка и ее позиции, заказ и его строки, flow, который обновляет три объекта. Здесь платформа дает сильную гарантию. Сохранение и все, что оно запускает, — триггеры, flow, вызываемые ими классы — выполняются как одна транзакция: если какая-то часть не удалась, все откатывается и ничего не фиксируется (Apex Transactions (opens in a new tab)). Половины доставки у вас не будет.

Массовая работа — исключение, которое вы выбираете сами. Загрузка данных или метод Apex Database может разрешить частичный успех: хорошие записи сохраняются, плохие возвращаются со своими ошибками, и кто-то должен с ними разобраться (DML Statements vs. Database Class Methods (opens in a new tab)). Для загрузки миллиона строк это часто правильно, но тогда согласованность — это процесс: кто читает файл ошибок и что происходит с записями, которые не прошли?

А еще есть время. Два сохранения в один и тот же момент могут оба пройти проверку, которую каждое по отдельности не прошло бы. Flow, который ищет существующий заказ, а потом создает его, может пропустить два, а мы только что видели, что правила дубликатов не сравнивают записи, сохраненные одновременно. Поле, помеченное как Unique, или External ID платформа проверяет при каждом сохранении, поэтому выиграет только одно из них. Это еще одна причина опускать уникальность до уровня поля. Блокировки, конкуренция и повторные попытки — отдельная тема; глава 11, Транзакции, параллелизм и надежность, разбирает ее глубоко.

Опускайте правило вниз — пока оно там уместно

Заголовок раздела «Опускайте правило вниз — пока оно там уместно »

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

Лестница согласованности Лестница согласованности в виде матрицы, с нижней ступени, против четырех тестов: каждый путь записи, сложные условия, между записями и легко ли с этим жить. Ступень 1, тип поля и список выбора: действует на каждом пути, UI, API, загрузке и агенте, и с этим легко жить, но говорит только то, что может сказать поле; самая сильная. Ступень 2, Required и Unique: каждый путь, а Unique работает между записями, но действует всегда, без исключений; грубая. Ступень 3, правило проверки: каждый путь и сложные условия, с учетом записи и ее родителей, но его нужно ограничить для старых записей; ограничьте. Ступень 4, правило дубликатов: нечеткое сопоставление между записями, но оно пропускает слияние и восстановление и добавляет трение, без предупреждения через API; страховочная сеть. Ступень 5, автоматизация во Flow или Apex: все, если срабатывает по записи, но тесты, ошибки и поддержка на вас; последнее средство. И для контраста обязательность в макете страницы: защищает только этот экран; не данные. Внизу: опускайте правило на самую низкую ступень, которая верно его выражает. КАЖДЫЙ ПУТЬ ЗАПИСИ СЛОЖНЫЕ УСЛОВИЯ МЕЖДУ ЗАПИСЯМИ ЛЕГКО ЖИТЬ ЭТО Тип поля и список выбора ступень 1: словарь UI, API, загрузка, агент только то, что может сказать поле САМАЯ СИЛЬНАЯ Required и Unique ступень 2: поле всегда, без исключений Unique: побеждает один ГРУБАЯ Правило проверки ступень 3: формула запись и ее родители ограничьте: старые записи ОГРАНИЧЬТЕ Правило дубликатов ступень 4: сопоставление пропускает слияние, восстановление нечеткое сопоставление трение, нет UI в API СТРАХОВОЧНАЯ СЕТЬ Автоматизация ступень 5: Flow, Apex если по записи тесты, ошибки, поддержка ПОСЛЕДНЕЕ СРЕДСТВО Обязательное в макете страницы для контраста: экран только этот экран НЕ ДАННЫЕ Опускайте правило на самую низкую ступень, которая верно его выражает. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Вот компромисс, который я хочу, чтобы вы увидели. Типы полей и контролируемые значения просты и сильны, но только для того, что может выразить поле. Required и Unique — тупые инструменты: включили — и каждая запись данных должна им удовлетворять. Правила проверки выражают более сложные условия, но могут блокировать правки старых записей и преподнести сюрприз при развертывании. Правила дубликатов защищают между записями, но добавляют трения для пользователей и интеграций. Автоматизация справляется с чем угодно, но заставляет вас владеть оркестрацией, ошибками, тестами и производительностью. Бесплатного уровня нет. Выбирайте уровень для каждого правила, зная, как оно отказывает.

Добавление правила в существующий org — это внедрение, а не галочка. Сколько записей нарушают его сегодня и почему? Они действительно неверны? Можем ли мы узнать правильное значение? Верно ли правило исторически или только с этого момента? Какие интеграции, тесты и автоматизации на него наткнутся? Хорошая последовательность: измерить, очистить то, что точно неверно, ограничить охват правила, добавить осознанный обход для законной истории, протестировать каждый путь записи и только потом применять. Измерение и очистка — отдельные дисциплины: профилирование, стандартизация, мониторинг, стюардство, — и их разбирает глава 5, Качество данных и управление ими. Гораздо лучше, чем поставить галочку в пятницу и узнать о последствиях в субботу вечером.

За пределами экзамена: что меняет ИИ. Агент может создавать записи быстрее любого человека — и плохие записи так же быстро. «Пользователи знают, что так делать нельзя» — не защита, когда пользователь — агент. Ставьте важные правила на уровне данных, где с ними встречается каждый, кто пишет, чтобы агенту не приходилось помнить неписаные правила компании.

Возьмите доставку. Ее статус берется из одного словаря: список выбора, ограниченный. Номер заказа розничного партнера должен быть уникальным в пределах партнера, поэтому это External ID, помеченный как уникальный, по которому делается upsert манифеста. Фактическое время доставки обязательно, как только статус становится Delivered: правило проверки, ограниченное этим изменением. Остановку с установкой нельзя закрыть, пока не выполнен ее чек-лист и не сделаны нужные фотографии (для посудомоечной машины — линия подачи воды, слив и уровень): правило проверки или автоматизация, если нужно проверять фотографии, хранящиеся вне платформы. Один и тот же заказ, пришедший дважды из повторно отправленного манифеста, ловит External ID; два разных заказа, которые похожи друг на друга, — это вопрос сопоставления.

Заметьте, я не сказал «положите все во flow». Каждое правило стоит на своей ступени. Для каждого правила спрашивайте: какой самый низкий уровень правильно обеспечивает это для каждого важного пути записи?

  • На какой ступени место каждому правилу: тип поля, контролируемый словарь, Required или Unique, правило проверки, правило дубликатов или автоматизация.
  • Какие пути записи нужно защитить: интерфейс, портал, мобильное приложение, интеграции, массовые загрузки, API, автоматизацию и агентов.
  • Применяется ли новое правило к историческим записям или ограничено новыми и измененными данными с обходом для прошлого.
  • Можно ли исправить существующие плохие данные на основе фактов, а не переписать их, чтобы они проходили.
  • Сколько трения, сложности и поддержки стоит правило.

Чистые данные не появляются оттого, что людей просят вводить хорошие данные. Они появляются из архитектуры, которая делает правильное легким, неправильное — трудным, а важные правила — трудными для обхода. Далее мы соберем главу воедино на срезе Steve Trucking.