При написании сложного программного кода в среде 1С:Предприятие 8.3 разработчики часто сталкиваются с необходимостью визуально структурировать длинные алгоритмы. Одним из инструментов такой структуризации является использование директивы препроцессора #Область (или #Region). Однако в сообществе программистов не утихают споры: является ли размещение областей внутри тела процедуры признаком хорошего тона или же это сигнализирует о низком качестве кода? В этой статье мы подробно разберем стандарты разработки, проанализируем практические примеры и выясним, как правильно организовывать структуру программного модуля.
Для начала обратимся к официальной системе стандартов и методик разработки «1С». Согласно стандарту (пункт 8.1.3.4), тексты больших процедур и функций действительно разрешается разбивать на отдельные сворачиваемые области. Рассмотрим основные положения этого правила:
Проанализируем ситуацию: директива #Область не влияет на исполнение кода сервером или клиентом. Она предназначена исключительно для текстового редактора (Конфигуратора или 1C:EDT). При компиляции эти строки игнорируются, поэтому с точки зрения производительности системы разницы между кодом с областями и без них нет.
Разберем по шагам, почему опытные разработчики часто критикуют использование областей внутри методов. Рассмотрим пример кода, который предоставил автор темы:
&НаСервере
Процедура ВыгрузитьДанныеВЛюбимыйДомНаСервере()
// Блок инициализации справочников
ДокПриемник.Организация = Открытие.Справочники.Организации.FindByCode("00-000001");
// ... другие справочники
#Область СозданиеКонтрагента
Контрагент = Открытие.Справочники.Контрагенты.FindByCode(Объект.Контрагент.Код);
Если Контрагент.Пустая() Тогда
КонтрагентПриемник = Открытие.Справочники.Контрагенты.CreateItem();
Иначе
КонтрагентПриемник = Контрагент.GetObject();
КонецЕсли;
#КонецОбласти
КонецПроцедуры
В данном случае выделение блока #Область СозданиеКонтрагента — это попытка скрыть логически обособленный кусок кода. Правильным архитектурным решением здесь будет декомпозиция. Выясним причину: если вынести этот блок в отдельную функцию, мы получим возможность повторного использования кода и упростим отладку основного алгоритма.
Сравним с рекомендуемым подходом:
&НаСервере
Функция НайтиИлиСоздатьКонтрагентаВПриемнике(КодКонтрагента, Открытие)
Контрагент = Открытие.Справочники.Контрагенты.FindByCode(КодКонтрагента);
Если Контрагент.Пустая() Тогда
Возврат Открытие.Справочники.Контрагенты.CreateItem();
Иначе
Возврат Контрагент.GetObject();
КонецЕсли;
КонецФункции
&НаСервере
Процедура ВыгрузитьДанныеВЛюбимыйДомНаСервере()
// Вызов функционала через специализированный метод
КонтрагентПриемник = НайтиИлиСоздатьКонтрагентаВПриемнике(Объект.Контрагент.Код, Открытие);
// ... дальнейшая логика
КонецПроцедуры
Проанализировав ситуацию, мы видим, что код стал чище, а основная процедура ВыгрузитьДанныеВЛюбимыйДомНаСервере теперь содержит только высокоуровневую логику, не перегруженную деталями реализации создания объектов.
Тем не менее, существуют сценарии, где использование областей внутри методов считается допустимым и даже удобным. Разберем их подробнее:
#Область ТекстЗапроса позволяет свернуть его, чтобы он не мешал просмотру логики установки параметров Запрос.УстановитьПараметр().ПриСозданииНаСервере часто встречаются области типа #Область ПолучитьЗначенияФункциональныхОпций. Это делается для того, чтобы не раздувать стек вызовов мелкими процедурами, которые используются строго один раз в одном конкретном месте.Посмотрим на пример из типовой конфигурации:
#Область ПолучитьЗначенияФункциональныхОпций
Форма.ИспользоватьУпаковкиНоменклатуры = ПолучитьФункциональнуюОпцию("ИспользоватьУпаковкиНоменклатуры");
Форма.ИспользоватьХарактеристикиНоменклатуры = ПолучитьФункциональнуюОпцию("ИспользоватьХарактеристикиНоменклатуры");
#КонецОбласти
Здесь область оправдана, так как она группирует однотипные действия по настройке интерфейса формы, которые не требуют сложной логики и параметров.
Рассматривая пример автора, нельзя не упомянуть и другие критические моменты, которые важнее наличия областей:
Во-первых, использование методов FindByCode (НайтиПоКоду) и FindByDescription (НайтиПоНаименованию) с жестко прописанными строковыми значениями (хардкод) крайне нежелательно. Если в базе-приемнике изменится код организации или наименование склада, ваш код перестанет работать. Правильнее использовать предопределенные элементы, константы или настройки в специальном регистре сведений.
Во-вторых, работа через COMConnector накладывает свои ограничения (например, отсутствие поддержки кириллических имен методов в некоторых случаях), но это не оправдывает плохую структуру модуля.
Если вы все же решили использовать области внутри методов, следуйте этим правилам:
#Область ИнициализацияПараметров или #Область ЗаполнениеТабличнойЧасти.Подводя итог, можно сказать: использование #Область внутри процедур — это инструмент, а не запрещенный прием. Рассмотрим финальный вердикт:
Используйте области внутри методов только как временную меру для структуризации очень длинного «наследованного» кода (legacy code) или для визуального скрытия огромных статических данных (тексты запросов, шаблоны). Стремитесь к декомпозиции — выделению логических блоков в отдельные функции и процедуры. Это сделает ваш код профессиональным, читаемым и легким в поддержке, что гораздо важнее красивых «сворачивающихся» блоков в редакторе.