При работе с современными конфигурациями на платформе 1С:Предприятие 8.3 программисты всё чаще сталкиваются с кодом, который на первый взгляд кажется необычным или даже ошибочным. Речь идет о механизме расширений и специальных директивах компилятора, которые позволяют изменять логику типовых решений, не снимая их с поддержки. В этой статье мы подробно разберем, как устроены аннотации перехвата методов, зачем нужны кавычки в именах процедур и какие «секретные» инструкции препроцессора существуют в системе.
Рассмотрим ситуацию, когда нам необходимо добавить свою логику в типовую процедуру, например, ПередЗаписью. Вместо того чтобы править основную конфигурацию, мы создаем расширение и используем специальные аннотации. Проанализируем основные виды «зацепок» (хуков), которые предоставляет платформа:
ПродолжитьВызов().Посмотрим на пример из практики, который часто вызывает вопросы у новичков:
&После("ПередЗаписью")
Процедура ДВ_ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Наша логика, которая сработает после типовой
Сообщить("Данные успешно проверены типовым кодом, выполняем доп. действия");
КонецПроцедуры
Здесь ДВ_ПередЗаписью — это произвольное имя нашей процедуры в расширении. Важно понимать, что связь с основной конфигурацией осуществляется именно через строку "ПередЗаписью" в кавычках. Это позволяет нам давать своим методам уникальные префиксы (например, ДВ_), чтобы избежать конфликтов с другими расширениями или будущими обновлениями типовой конфигурации.
Разберем вопрос, который часто возникает у разработчиков: зачем оборачивать имя целевого метода в кавычки? Проанализируем это с точки зрения работы компилятора. Если бы мы писали имя без кавычек, компилятор ожидал бы, что это имя функции или переменной, доступной в текущем контексте. Однако в момент написания кода в расширении метод ПередЗаписью основной конфигурации «физически» не находится в модуле расширения.
Использование строкового литерала "ИмяМетода" сообщает платформе: «Найди метод с таким именем в расширяемом объекте и приклей к нему мой код». Это также задел на будущее развитие платформы: возможно, в параметрах аннотации появятся дополнительные атрибуты управления (например, приоритет выполнения), которые будут передаваться через запятую после имени.
Хотя в обсуждениях часто упоминают только базовую тройку директив, самым мощным инструментом является &ИзменениеИКонтроль. Проанализируем, как она работает. Представьте, что типовая процедура состоит из 100 строк, а вам нужно изменить только 5-ю и 90-ю строки. Использовать &Вместо опасно, так как при обновлении вы можете пропустить важные изменения в остальных 98 строках.
Директива &ИзменениеИКонтроль позволяет скопировать код целиком и разметить его специальными тегами:
&ИзменениеИКонтроль("СформироватьОтчет")
Процедура Расш1_СформироватьОтчет()
//&Удалено
// СтарыйКод();
//&Вставлено
НовыйУлучшенныйКод();
КонецПроцедуры
Если при обновлении 1С обнаружит, что оригинальный код в секции &Удалено изменился в новой версии поставщика, система выдаст ошибку при синтаксическом контроле. Это заставляет программиста перепроверить логику, что значительно повышает надежность системы.
Выясним, что происходит, если в базе установлено несколько расширений, влияющих на один и тот же метод. Порядок выполнения будет следующим:
&Перед из всех расширений (согласно их приоритету в списке расширений).&Вместо. Если их несколько, они выстраиваются в стек («матрешку»). Последнее расширение вызывает предпоследнее через ПродолжитьВызов().&Вместо был вызван ПродолжитьВызов()).&После в порядке, обратном приоритету расширений.Нужно быть крайне осторожными с директивой &Вместо. Как отмечают опытные разработчики, если вы «грешите» её использованием, трудоемкость обновлений возрастает. &После — гораздо более безопасный и «этичный» способ расширения функционала.
В истории развития платформы 8.3 были периоды (особенно в бета-версиях), когда вместо современных аннотаций предлагались инструкции препроцессора, такие как #Вставить, #КонецВставить, #Удалить и #КонецУдалить. Рассмотрим, почему они практически исчезли. Эти инструкции физически «вырезали» или «вклеивали» куски текста в модуль во время компиляции.
Хотя сейчас они считаются устаревшими и заменены механизмом &ИзменениеИКонтроль, в старом коде или специфических разработках их всё еще можно встретить. Современная платформа переименовала или трансформировала их в более строгие аннотации, чтобы избежать хаоса при обновлении.
Кроме модулей, свои «директивы» есть и в языке запросов, особенно когда речь идет о системе прав доступа (RLS). Посмотрим на такие конструкции, как #ИмяТекущегоПраваДоступа или #Параметр(). Это элементы внутреннего макроязыка 1С, который используется для динамической подстановки условий в SQL-запросы в зависимости от прав пользователя. Программисту редко приходится писать их вручную, обычно они генерируются шаблонами ограничений доступа, но знать об их существовании необходимо для отладки сложных прав.
Проанализировав возможности расширений, мы можем сформулировать несколько правил эффективной разработки:
&Перед и &После. Это минимизирует риски при обновлении конфигурации.&ИзменениеИКонтроль, если нужно точечно изменить логику внутри длинного алгоритма.&Вместо без вызова ПродолжитьВызов(), если только вашей целью не является полное отключение типового функционала.МойПроект_ПередЗаписью).Понимание того, как работают эти «незнакомые» директивы, превращает магию в мощный инструмент. Расширения позволяют сохранять типовую конфигурацию в чистоте, что значительно упрощает жизнь как разработчику, так и владельцу бизнеса при сопровождении системы.