При работе с типовыми конфигурациями 1С перед программистом часто встает дилемма: как внедрить необходимый функционал в существующий общий модуль, сохранив при этом возможность относительно безболезненного обновления системы. Платформа 8.3 предоставляет несколько механизмов для решения этой задачи. Разберем подробно каждый из них, проанализируем риски и выберем оптимальную стратегию в зависимости от ситуации.
Рассмотрим классический подход, когда конфигурация находится на поддержке с возможностью редактирования. Если нам необходимо изменить логику работы типовой процедуры, самым простым (но требующим аккуратности при обновлениях) способом является создание «врезки».
Проанализируем алгоритм действий: вместо того чтобы писать десятки строк кода внутри типовой процедуры, мы создаем свой собственный общий модуль (например, _МойОбщийМодуль) и вызываем его метод из типового кода. Выясним причину, почему это лучше: при сравнении и объединении конфигураций во время обновления вы увидите только одну добавленную строку, что сводит риск ошибки к минимуму.
Посмотрим на пример реализации:
// В типовом модуле конфигурации:
Процедура ТиповаяПроцедураОбработки(Параметр1, Параметр2)
// ... существующий типовой код ...
// Наша врезка:
_МойОбщийМодуль.ВыполнитьДополнительнуюОбработку(Параметр1, Параметр2);
// ... продолжение типового кода ...
КонецПроцедуры
Преимущества: Простота реализации и полный контроль над процессом выполнения кода. Вы точно знаете, в какой момент вызывается ваша логика.
Риски: При обновлении, если поставщик полностью перепишет данный модуль или удалит процедуру, вам придется вручную переносить вызов в новое место.
Разберем наиболее современный и рекомендуемый фирмой «1С» способ — использование механизма расширений. Для изменения кода в общем модуле лучше всего подходит аннотация &ИзменениеИКонтроль. В отличие от &Вместо, этот метод позволяет заменять не всю процедуру целиком, а только конкретные блоки кода, используя специальные теги.
Рассмотрим подробнее синтаксис использования этого механизма. Допустим, нам нужно вставить свой код в середину типового метода:
&ИзменениеИКонтроль("ПечатьДокумента")
Процедура Расш1_ПечатьДокумента(Параметры)
// Код, который мы не трогаем, остается без изменений
НаборДанных = ПолучитьДанныеДляПечати();
#Вставка
// Наша логика: проверяем дополнительные условия перед выводом на печать
Если _МойМодульСервер.НужноЗаблокироватьПечать(Параметры) Тогда
Возврат;
КонецЕсли;
#КонецВставки
СформироватьТабличныйДокумент(НаборДанных);
КонецПроцедуры
Выясним важный нюанс: механизм &ИзменениеИКонтроль проверяет соответствие типового кода в расширении и в основной конфигурации. Если вендор изменит код в области контроля, расширение не применится, и система выдаст ошибку при запуске. Это позволяет вовремя заметить конфликт логики и актуализировать доработку.
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), проанализируем возможность использования штатных «точек входа». Разработчики 1С специально оставляют модули с постфиксом ...Переопределяемый для нужд программистов на внедрении.
Разберем по шагам, как это работает:
ПрисоединенныеФайлыПереопределяемый или ОбщегоНазначенияПереопределяемый).ПриОпределенииОбъектовСКомандамиПечати).Важный момент: Эти модули практически никогда не обновляются поставщиком в плане внутреннего содержимого процедур. Они предназначены именно для вас, поэтому при обновлении ваши изменения в них гарантированно сохранятся.
Часто возникает задача изменить текст запроса, который формируется в общем модуле. Использовать здесь аннотацию &Вместо крайне опасно: если 1С изменит структуру таблиц или логику связей в основном коде, ваша подмена через &Вместо со старым текстом запроса приведет к непредсказуемым ошибкам или потере данных.
Проанализируем ситуацию: как безопасно добавить поле в запрос? Рассмотрим вариант использования &После для программной модификации текста запроса:
&После("ПолучитьТекстЗапросаДляОтчета")
Функция Расш1_ПолучитьТекстЗапросаДляОтчета(Результат)
// Результат — это уже сформированная строка запроса от 1С
// Мы можем динамически добавить в нее свои поля
ТекстДопПоля = ",
| ДополнительныеСведения.Значение КАК МоеСвойство";
Результат = СтрЗаменить(Результат, "ИЗ", ТекстДопПоля + " ИЗ");
Возврат Результат;
КонецФункции
Такой подход позволяет сохранить актуальность базового запроса от поставщика, при этом гибко внедряя свои изменения.
Выясним, какой метод выбрать в конкретной ситуации:
&ИзменениеИКонтроль.Рассмотрим также вопрос производительности. Помните, что каждое расширение немного увеличивает время инициализации сеанса. Старайтесь не плодить десятки расширений, а группировать доработки по смыслу. Также проверьте настройки Безопасного режима: по умолчанию расширения работают с ограничениями, и если ваш общий модуль должен обращаться к внешним ресурсам (файловой системе, COM-объектам), безопасный режим в свойствах расширения нужно отключить.
Таким образом, комбинируя современные механизмы платформы и принципы минимизации изменений в типовом коде, мы обеспечиваем высокую надежность системы и легкость ее дальнейшего сопровождения.