При работе с типовыми конфигурациями 1С часто возникает необходимость доработать стандартные алгоритмы или печатные формы. Однако, когда логика процедуры сконцентрирована в одном большом блоке кода, как, например, при печати накладной реализации в 1С:Управление торговлей 11 (УТ11), внедрение изменений становится нетривиальной задачей. Разработчики сталкиваются с вопросом, можно ли надеяться на то, что 1С пересмотрит подход к написанию процедур, разбивая их на более мелкие блоки с "заглушками" для расширений, или же стоит ожидать доработки самого механизма расширений, позволяющего точечно привязываться к меткам внутри процедур.
Давайте подробно рассмотрим, какие подходы существуют для решения этой проблемы и какие инструменты предоставляет платформа 1С для модификации типовых алгоритмов.
Как мы уже выяснили из исходного сообщения, одной из главных проблем является то, что вся логика, например, печати накладной, может быть реализована в одной единственной процедуре. Это значительно затрудняет использование расширений для точечных изменений. Если нам нужно добавить всего пару строк кода или изменить небольшую часть алгоритма, нам придется либо полностью скопировать всю процедуру в расширение, либо использовать менее гибкие методы.
Разработчики 1С не всегда проектируют типовые модули с расчетом на легкое наследование и модификацию, что приводит к так называемой "проблеме хрупкого базового класса" (fragile base class problem). Это означает, что даже небольшое изменение в типовой конфигурации может привести к некорректной работе наших доработок.
Платформа 1С предлагает несколько механизмов для работы с расширениями, каждый из которых имеет свои особенности, преимущества и недостатки.
&Перед, &После, &Вместо и ПродолжитьВызов
Эти аннотации позволяют нам выполнить наш код до, после или вместо оригинального метода типовой конфигурации. Рассмотрим их подробнее:
&Перед: Метод расширения выполняется перед оригинальным методом. Это полезно для предварительной подготовки данных, проверки условий или изменения входных параметров.&После: Метод расширения выполняется после оригинального метода. Мы можем использовать его для пост-обработки результатов, логирования или изменения выходных параметров.&Вместо: Метод расширения полностью замещает оригинальный метод. Это мощный инструмент, но он требует осторожности, так как полностью перекрывает типовой алгоритм. Если нам нужно вызвать оригинальный метод внутри замещающего, мы можем использовать конструкцию ПродолжитьВызов().Преимущества: Позволяют гибко внедрять логику без изменения исходного кода конфигурации.
Недостатки: Могут возникнуть трудности с обновлением, если оригинальный метод сильно изменится. Использование &Вместо несколькими расширениями может привести к конфликтам, так как только одно из них будет применено (порядок определяется приоритетом расширений).
В типовых конфигурациях существуют общие модули, такие как МодификацияКонфигурацииПереопределяемый, которые специально предназначены для переопределения. В таких случаях, использовать &Вместо в расширении будет наиболее корректным и управляемым способом.
&ИзменениеИКонтроль
Этот механизм позволяет нам точечно изменять текст расширяемого модуля, заимствуя его целиком в расширение, а затем помечая фрагменты для вставки или удаления с помощью директив препроцессора.
Преимущества: Позволяет очень точно контролировать изменения внутри модуля, внедрять или удалять код в любом месте процедуры.
Недостатки: Платформа контролирует неизменность кода в основной конфигурации. При любом изменении оригинального модуля (даже в строках, не затронутых расширением), наше расширение перестает выполняться с ошибкой типа "ашипка. текст модуля для метода изменился", требуя ручного трехстороннего объединения. Это заставляет нас каждый раз уделять внимание изменившимся модулям, но может быть трудоемким при частых обновлениях.
На практике, некоторые разработчики сознательно переходят на использование &ИзменениеИКонтроль, находя его эффективным для экономии времени на обновлениях, несмотря на необходимость ручного контроля.
Для печатных форм обсуждение особенно активно, так как это частая точка доработок. Здесь существует принципиальный выбор между использованием внешних печатных форм (ВПФ) и размещением печатных форм в расширении.
ВПФ разрабатываются как отдельные файлы (.epf), которые подключаются к базе в пользовательском режиме. Они взаимодействуют с системой через стандартизированные интерфейсы БСП (Библиотека стандартных подсистем).
Преимущества:
Недостатки:
Когда применять: ВПФ идеально подходят для большинства кастомизаций печатных форм, особенно когда нам нужно полностью изменить макет, добавить новые поля или реализовать специфическую логику печати. Это стандартный и рекомендуемый способ для большинства случаев, если нам не требуются глубокие изменения в самом процессе формирования данных для печати.
Печатные формы могут быть добавлены или модифицированы непосредственно в расширении. Это означает, что они становятся частью конфигурации расширения.
Преимущества:
Недостатки:
Когда применять: Печатные формы в расширениях подходят для небольших "косметических" доработок типовых макетов (например, добавление телефона или адреса клиента), а также в случаях, когда требуется глубокая интеграция с уже модифицированными в расширении объектами или алгоритмами. Необходимо тщательно соблюдать стиль написания процедур, чтобы минимизировать риски при обновлениях.
Если нам необходимо внести изменения в середину большой процедуры, которая не разбита на подпроцедуры и не имеет удобных точек расширения, нам придется прибегнуть к более изощренным методам. Одним из таких методов является модификация результатов запросов через ТаблицаЗначений.
Предположим, у нас есть типовая процедура, которая формирует данные для отчета или печатной формы с помощью сложного запроса, оперирующего временными таблицами (Менеджер Временных Таблиц – МВТ). Если нам нужно добавить новую колонку, изменить значения или отфильтровать данные, но мы не можем напрямую изменить текст запроса, мы можем использовать следующий подход:
ТаблицаЗначений.
Для этого мы используем метод ПолучитьДанные().Выгрузить() от менеджера временных таблиц.
ТЗ = Запрос.МенеджерВременныхТаблиц.Таблицы["Какаятовременнаятаблица"].ПолучитьДанные().Выгрузить();
Здесь "Какаятовременнаятаблица" - это имя временной таблицы, которая была создана ранее в запросе.
ТаблицаЗначений.
Теперь, когда данные находятся в оперативной памяти в виде ТаблицаЗначений, мы можем выполнять с ними любые действия:
ТЗ.Колонки.Добавить("НоваяКолонка");
Для Каждого СтрокаТЗ из ТЗ Цикл
СтрокаТЗ.НоваяКолонка = СтрокаТЗ.Колонка1 * СтрокаТЗ.Колонка2;
// ... тут какая-то дополнительная логика по модификации ТЗ
КонецЦикла;
ТаблицаЗначений обратно во временную таблицу.
После всех необходимых изменений мы формируем новый запрос, который уничтожает старую временную таблицу (если она больше не нужна) и создает новую, используя нашу модифицированную ТаблицаЗначений как источник данных.
МассивПолейВыборки = Новый Массив;
Для Каждого Колонка Из ТЗ.Колонки Цикл
МассивПолейВыборки.Добавить(Колонка.Имя);
КонецЦикла;
ТекстПолейВыборки = СтрСоединить(МассивПолейВыборки, ",");
ТекстЗапроса = "
|УНИЧТОЖИТЬ Какаятовременнаятаблица // Уничтожаем старую ВТ, если нужно
|;
|ВЫБРАТЬ
| " + ТекстПолейВыборки + "
|ПОМЕСТИТЬ Какаятовременнаятаблица // Создаем новую ВТ с обновленными данными
|ИЗ
| &Таблица КАК Таблица";
Запрос.Текст = ТекстЗапроса;
Запрос.УстановитьПараметр("Таблица", ТЗ); // Передаем нашу модифицированную ТЗ как параметр
Запрос.Выполнить();
Теперь последующие части типового алгоритма будут работать уже с нашей модифицированной временной таблицей, содержащей все необходимые доработки.
Нюансы и рекомендации:
ТаблицаЗначений и обратно может быть затратной по памяти и времени. Используйте этот метод обдуманно, только когда другие варианты (например, прямое изменение запроса через расширение, если возможно) недоступны или слишком сложны. Однако, в некоторых случаях, это единственный рабочий способ.Выборка против Выгрузить(): Платформа 1С часто рекомендует использовать выборку запроса вместо полной выгрузки в ТаблицаЗначений для обработки больших объемов данных, чтобы избежать пикового потребления памяти. Однако, для модификации данных и последующего возвращения их в запрос, Выгрузить() в ТЗ может быть более практичным, особенно если нам нужно динамически добавлять колонки или выполнять сложную логику, которую сложно реализовать непосредственно в запросе.В случае, когда никакие механизмы расширений или ВПФ не позволяют реализовать требуемую функциональность из-за глубоких и фундаментальных изменений в архитектуре типового решения, некоторые разработчики прибегают к снятию конфигурации с поддержки. Это позволяет вносить любые изменения напрямую в код конфигурации.
Преимущества: Полная свобода действий, возможность изменить абсолютно любой аспект конфигурации.
Недостатки: Полностью теряется возможность автоматического обновления конфигурации. Каждое новое обновление потребует ручного объединения, что является крайне трудоемким и рискованным процессом. Этот метод рекомендуется использовать только в крайних случаях, при очень серьезных и необратимых изменениях, которые невозможно реализовать иными способами, и при наличии ресурсов для последующего сопровождения.
Мы выяснили, что не всегда можем рассчитывать на идеальное разбиение процедур в типовых решениях 1С для упрощения работы расширений. Однако, у нас есть арсенал методов, которые позволяют эффективно работать с существующей архитектурой:
&Перед, &После, &Вместо или &ИзменениеИКонтроль, осознавая их ограничения и риски.ХХХ_Переопределяемый. Они специально предусмотрены для расширения функциональности.ТаблицаЗначений, могут быть спасением в сложных ситуациях, когда нужно вклиниться в середину алгоритма.В конечном итоге, хотя 1С и не всегда предоставляет идеальную структуру процедур для легкого расширения, глубокое понимание доступных механизмов и умение применять различные подходы позволяют нам эффективно решать большинство задач по адаптации типовых конфигураций под нужды бизнеса.