Почему в типовых конфигурациях запрещают авторегистрацию?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Почему типовые конфигурации запрещают авторегистрацию
Это один из классических вопросов архитектуры 1С-систем, и ответ на него показывает понимание проблем масштабируемости и консистентности данных. Давайте разберёмся в корне проблемы.
Проблема авторегистрации (Self-Registration)
Авторегистрация — это когда объект метаданных сам регистрирует свои изменения в регистре накопления:
// ПЛОХО — авторегистрация в модуле объекта
Процедура ПередПроведением(Отказ, РежимПроведения) Экспорт
// Объект сам пишет свои движения
Движение = Движения.РегистрНакопления.Добавить();
Движение.Счёт = ...;
// Объект сам о себе заботится
КонецПроцедуры
Это кажется удобным, но создаёт множество проблем.
Основные причины запрета
1. Нарушение принципа Single Responsibility
Документ должен отвечать за:
- Хранение своих реквизитов
- Валидацию своего состояния
- Успешное сохранение
Документ НЕ должен отвечать за:
- Как учитываются его данные
- Какие регистры обновлять
- Бизнес-логику учёта
В авторегистрации документ смешивает:
- Domain logic (свойства, валидация)
- Application logic (как отражать в учёте)
2. Нарушение инкапсуляции данных
Когда документ сам пишет в регистры, становится невозможно:
// Пример проблемы
Процедура ПересчитатьРегистр() Экспорт
// Нужно пересчитать движения документа
Документ = Документы.МойДокумент.ПолучитьОбъект(Ссылка);
// Но как это сделать?
// Если я просто измению реквизит и проведу — документ сам перепишет движения
// Но движения остались старые! Откуда они возьмутся?
КонецПроцедуры
Проблема: непонятна граница ответственности между документом и его движениями.
3. Сложность расширений и модификаций
Когда появляется расширение или нужно добавить новый регистр:
База конфига: Документ сам пишет в РегистрВыручка
Расширение: Нужно добавить РегистрЗатраты
Проблема: Где писать в РегистрЗатраты?
- В расширение документа? Но это значит раздваивать логику
- В обработчик? Но это добавляет зависимость
4. Проблемы с откатом и пересчётом
// Сценарий: нужно пересчитать все документы после сбоя
Процедура ПересчитатьВсе() Экспорт
// С авторегистрацией это становится адом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Ссылка
ИЗ Документ.МойДокумент
ГДЕ ...";
Для Каждого Строка Из Запрос.Выполнить().Выгрузить() Цикл
Док = Строка.Ссылка.ПолучитьОбъект();
// Нужно откатить старые движения
Движения.РегистрНакопления.Записать(Ложь); // Но как?
// Проводим заново
Док.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;
КонецПроцедуры
Без явной регистрации движений очень сложно контролировать этот процесс.
5. Отсутствие точки контроля (Audit Trail)
Если движения пишутся автоматически:
- Сложнее отследить, когда что изменилось
- Нет явного места, где можно добавить логирование
- Нельзя добавить бизнес-правила на уровне регистра
Правильный подход: Явная регистрация
Вместо авторегистрации используется паттерн "Publication":
// ===== ДОКУМЕНТ (Domain) =====
Процедура ПередПроведением(Отказ, РежимПроведения) Экспорт
// Документ только проверяет себя
ПроверитьКорректность();
КонецПроцедуры
// ===== ОБРАБОТЧИК (Application Layer) =====
Процедура ОбработатьПроведение(ДокументСсылка) Экспорт
Документ = ДокументСсылка.ПолучитьОбъект();
// Регистрируем движения явно
ОтметитьНаПроведение(Документ);
Документ.Записать(РежимЗаписиДокумента.Проведение);
// Записываем движения в регистры
РегистрацияДвижений(Документ);
КонецПроцедуры
Процедура РегистрацияДвижений(Документ) Экспорт
// Явно пишем в каждый регистр
Движения = Новый Массив;
// Выручка
Движение = Движения.Добавить();
Движение.Счёт = ...;
Движение.Сумма = Документ.СуммаВыручки;
// Затраты
Движение = Движения.Добавить();
Движение.Счёт = ...;
Движение.Сумма = Документ.СуммаЗатрат;
КонецПроцедуры
Преимущества явной регистрации
1. Clarity и Maintainability
Ясно видно в одном месте:
- Какие регистры обновляет документ
- В каком порядке они обновляются
- Какие проверки предшествуют обновлению
2. Extensibility
// Расширение может добавить свой регистр
Процедура РегистрацияДвижений_Расширение(Документ) Экспорт
// Пишет в РегистрЗатрат из расширения
Движение = Движения.РегистрЗатрат.Добавить();
Движение.Сумма = Документ.ДополнительнаяСумма;
КонецПроцедуры
3. Testability
// Легко тестировать регистрацию отдельно
Процедура Тест_РегистрацияДвижений() Экспорт
Документ = СоздатьТестовыйДокумент();
РегистрацияДвижений(Документ);
// Проверяем движения
ПроверитьДвижения(Документ);
КонецПроцедуры
4. Контроль над состоянием
Легко реализовать отката и пересчёты:
Процедура ОткатитьДокумент(ДокументСсылка) Экспорт
// Сначала удаляем старые движения
УдалитьДвижения(ДокументСсылка);
// Затем перепроводим документ
ПроводитьДокумент(ДокументСсылка);
КонецПроцедуры
Практический пример: Авторегистрация vs Явная
Авторегистрация (ПЛОХО):
// 100 строк логики в ПередПроведением документа
// Трудно расширять, трудно тестировать
// Невозможно переиспользовать логику регистрации
Явная регистрация (ХОРОШО):
// Документ чистый, 20 строк валидации
// Регистрация в отдельном сервисе, переиспользуемый код
// Легко расширить, добавить логирование, пересчёт
Практические рекомендации
- Не пишите логику регистрации в модули объектов — это приводит к техдолгу
- Используйте сервисы для явной регистрации движений
- Разделяйте ответственность — объект отвечает за себя, сервис за отражение в учёте
- Тестируйте регистрацию отдельно от проведения документа
- При расширениях добавляйте новых обработчиков, не модифицируя базовую логику
Заключение
Типовые конфигурации запрещают авторегистрацию, потому что это нарушает основные принципы архитектуры:
- Single Responsibility — объект не должен знать о своём отражении в учёте
- Extensibility — сложно расширять без нарушения целостности
- Maintainability — логика регистрации разбросана по разным местам
- Testability — трудно тестировать отдельно
Вместо этого используется паттерн явной регистрации через сервисы, что обеспечивает чистоту архитектуры, гибкость и надёжность системы. Это основополагающий принцип проектирования в профессиональных 1С-системах.