В процессе разработки конфигураций на платформе 1С:Предприятие часто возникает ситуация, когда после выполнения определенного кода или пользовательского действия объект (или форма) получает признак модифицированности. Быстро определить, изменение какого именно реквизита привело к установке данного флага, — важная задача при поиске багов и оптимизации алгоритмов. Разберем доступные методы решения этой задачи: от пошаговой отладки до программных способов сравнения состояний объекта.
Самым простым и надежным интерактивным методом при разработке является пошаговый замер состояния формы или объекта в отладчике. Проанализируем, как это реализовать на практике.
ЭтаФорма.Модифицированность или Модифицированность.Модифицированность изменит значение с Ложь на Истина, текущая выполнившаяся строка и будет являться причиной изменения данных.Если необходимо отловить момент изменения конкретного значения без ручного прохода каждой строки, используем точку останова с условием. В настройках точки останова можно задать выражение с проверкой изменения реквизита или флага модифицированности. Отладчик остановит выполнение ровно в тот момент, когда условие станет истинным.
Если объект уже существует в базе данных (имеет зафиксированную ссылку Объект.Ссылка), мы можем сравнить текущие значения реквизитов объекта в памяти со значениями, сохраненными в базе данных.
Рассмотрим вариант универсального обхода через метаданные объекта. Чтобы проверка была полной, проанализируем три категории данных: реквизиты, стандартные реквизиты и табличные части.
Функция ПолучитьСписокИзмененныхРеквизитов(Объект1С) Экспорт
Перем ИзмененныеРеквизиты;
ИзмененныеРеквизиты = Новый Массив;
Если Не ЗначениеЗаполнено(Объект1С.Ссылка) Тогда
Возврат ИзмененныеРеквизиты; // Новый объект, в БД данных нет
КонецЕсли;
МетаданныеОбъекта = Объект1С.Метаданные();
// 1. Проверяем обычные реквизиты
Для Каждого РеквизитИзМетаданных Из МетаданныеОбъекта.Реквизиты Цикл
ИмяРеквизита = РеквизитИзМетаданных.Имя;
Если Объект1С[ИмяРеквизита] <> Объект1С.Ссылка[ИмяРеквизита] Тогда
ИзмененныеРеквизиты.Добавить(ИмяРеквизита);
КонецЕсли;
КонецЦикла;
// 2. Проверяем стандартные реквизиты (Наименование, Код, Проведен и т.д.)
Для Каждого СтандартныйРеквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
ИмяРеквизита = СтандартныйРеквизит.Имя;
Попытка
Если Объект1С[ИмяРеквизита] <> Объект1С.Ссылка[ИмяРеквизита] Тогда
ИзмененныеРеквизиты.Добавить(ИмяРеквизита);
КонецЕсли;
Исключение
// Некоторые стандартные реквизиты могут быть недоступны для прямого чтения
КонецПопытки;
КонецЦикла;
Возврат ИзмененныеРеквизиты;
КонецФункции
Важное замечание по производительности: При первом прямом обращении к Объект1С.Ссылка.ИмяРеквизита платформа 1С считывает из базы данных целиком весь объект. Если требуется проверить только 1–2 конкретных поля, целесообразнее использовать запрос к базе данных с помощью Новый Запрос. Запрос прочитает исключительно необходимые поля, не загружая кэш лишними табличными частями.
В случаях, когда объект еще не записан в базу данных (новый объект) или требуется зафиксировать срез состояний до и после выполнения конкретной процедуры на клиенте/сервере, применяется метод сериализации в формат JSON.
Разберем данный алгоритм по шагам:
// Фиксация состояния ДО
ЗаписьJSON1 = Новый ЗаписьJSON;
ЗаписьJSON1.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON1, Объект);
СтрокаДо = ЗаписьJSON1.Закрыть();
// Выполнение исследуемого кода
ИзменитьДанныеОбъекта(Объект);
// Фиксация состояния ПОСЛЕ
ЗаписьJSON2 = Новый ЗаписьJSON;
ЗаписьJSON2.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON2, Объект);
СтрокаПосле = ЗаписьJSON2.Закрыть();
Если СтрокаДо <> СтрокаПосле Тогда
Сообщить("Данные объекта были изменены!");
КонецЕсли;
Важно понимать разницу между интерактивной модифицированностью формы и фактическим изменением данных объекта:
Модифицированность принадлежит самой форме. При интерактивном взаимодействии пользователей на клиенте или при присвоении значения реквизиту формы платформой автоматически взводится флаг модифицированности — даже если реквизиту было присвоено точно такое же значение, которое в нем находилось ранее.Модифицированность формы установился в Истина, можно сбросить его программно: ЭтаФорма.Модифицированность = Ложь;.Чтобы отслеживать изменения на клиенте без постоянных вызовов сервера, разработчики сохраняют начальное состояние реквизитов формы в структуру при открытии (в обработчике ПриОткрытии) и сравнивают значения при необходимости или в обработчиках событий ПриИзменении элементов формы.
Для системного контроля изменений в 1С предусмотрены готовые механизмы:
ИсторияДанных).ПередЗаписью) на сервере с помощью запроса к Источник.Ссылка можно точно определить список всех изменившихся полей перед зафиксированием данных в базе.