Начиная разрабатывать расширения, не сразу задумываешься о том, а что с ними будет дальше. Вернее задумываешься, но не все последствия получается предугадать. И лишь основываясь на уже двухгодичном опыте разработки расширений, в частности для типовой отраслевой конфигурации, понимаешь, что уже лучше бы не делать, а что стоит заранее предусмотреть, чтобы в дальнейшем расширение не стало обузой для разработчика, вместо облегчения работы.
Мы сделали выводы из своих ошибок и в итоге появился ряд рекомендаций, которыми руководствуемся при разработке расширений:
- Не дробить расширения для одного и того же объекта конфигурации
- Изменения расширяемых форм делать программно, а не через редактор форм
- Минимизировать использование аннотации &Вместо (&ИзменениеИКонтроль?)
- Делать независимые друг от друга расширения
- Новые объекты конфигурации, предполагающие хранение данных, добавлять в основную конфигурацию
- Вести реестр расширений
Рассмотрим подробнее каждый пункт
1. Не дробить расширения для одного и того же объекта конфигурации.
Если изменения касаются, например, одной формы, то мы делаем одно расширение, а не несколько. Если в последствии появляются еще задачи на изменение этой же формы, мы дополняем существующее расширение, вместо создания нового. Особенно, если логика в расширениях зависимая друг от друга. Поменять последовательность исполнения расширений не самая тривиальная задача. Как говорят разработчики: расширения исполняются в последовательности их добавления в конфигурацию и поменять их местами можно только через удаление/добавление (а если расширения содержали хранимые данные, то сделать это может стать невозможно).
Как вариант, можно объединять расширения по функциональности, а не только по определенным объектам, хотя здесь может возникнуть "конфликт объединений" и решить, каким образом лучше объединять, возможно, стоит в самом начале доработок. Например, нужно добавить определенный (схожий) функционал к нескольким объектам, что лучше: добавлять его в каждое расширение, относящееся к определенному объекту, или же сделать одно расширение, но зато придется сослаться на эти объекты в этом одном расширении? Вопрос на самом деле довольно сложный и порой заставляет отступить от принципа "один объект - одно расширение", ради объединение функционала в одном месте.
2. Изменения расширяемых форм делать программно.
Функция "Обновить расширение формы": не стоит всегда надеяться на этот автоматический механизм, так как иногда он может не сработать и будет нестерпимо больно от того, что нужно переделывать всё с нуля.
Давайте возьмем самый банальный пример: сделать определенное поле на форме нередактируемым, т.е. установить ему свойство "ТолькоПросмотр".
Видела много примеров в сети, в том числе на Инфостарт, где предлагалось решить такую простую задачу через редактор форм. Т.е. выбрать элемент нужного поля в редакторе и в свойствах установить "галочку" только просмотр…
Действительно, не надо так! Давайте представим, что таких элементов на форме не один, а, допустим, пятнадцать, плюс Вы еще добавили несколько новых элементов, кнопок и групп, а также перераспределили часть элементов по группам. Делать это в редакторе форм в первый раз действительно удобно. Пощелкали нужные галки, поменяли некоторые свойства элементов, и вот быстрый результат!
А вдруг случается страшное ("Всё пропало, шеф!"): после очередного релиза автообновление формы не срабатывает (часть элементов с формы вообще исчезает, а новые не появляются, как было в нашем случае пару раз) и Вам нужно повторить установку всех этих галок и свойств, воссоздавая расширение с нуля (а Вы еще к тому же забыли записать, с какими элементами, что делали, и было это полгода назад…). (Например, у нас в типовой конфигурации есть такая сложная форма, расширение которой приходится переделывать при каждом обновлении)
Тогда первичная простота во второй раз может превратиться в затратную по времени процедуру и, возможно, это будет повторяться неоднократно.
Ну и самый плачевный случай - делали это может быть вообще не Вы, а тот, кто делал уже давно уволился. Тогда рекомендуется переделать расширение так, чтобы потом не было каждый раз мучительно больно при обновлении.
Так что же делать? Всё просто! Любые изменения, связанные с элементами формы делайте программно, вообще старайтесь не трогать редактор форм, как бы соблазнительно это не было. Либо альтернативный вариант решения: к каждому расширению прикладывать подробное описание: что и с каким элементом Вы сделали, какое свойство поменяли, какой элемент добавили и т.п.
Не рекомендуется делать так:
Рекомендуется: добавить процедуру с аннотацией &После для события формы "ПриОткрытии" примерно с таким кодом:
&НаКлиенте
Процедура АТБ_ПриОткрытииПосле(Отказ)
Элементы.Ответственный.ТолькоПросмотр = Истина;
// и все другие изменения элементов формы
КонецПроцедуры
В этом случае, если Вам придется воспроизводить расширение с нуля, достаточно будет просто перенести данный код в воспроизводимое расширение и всё.
В случае затруднений при программном изменении элементов форм можно воспользоваться бесплатным инструментарием декомпиляции формы, который публиковался здесь на Инфорстарте Евгенией Карук - Генерация кода управляемой формы (т.е. сначала делаем форму в редакторе, указанным инструментом декомпилируем ее и смотрим, как делаются элементы формы программно).
В каком случае можно смело отступить от этой рекомендации? Когда Ваше расширение является временным исправлением ошибки, которую разработчики поправят в следующем релизе типовой конфигурации.
3. Минимизировать использование аннотации &Вместо.
Старайтесь при любой возможности избегать использования аннотации &Вместо. Если логика позволяет, используем &Перед или &После.
Главная цель в этом случае - избежать проблем при изменении кода исходной процедуры в типовой конфигурации (ведь аннотацией &Вместо мы перехватываем исполнение процедуры полностью на расширение, заменяя исходную).
Однако бывают ситуации, когда нужно поменять несколько строк кода именно внутри процедуры и никак аннотациями &Перед и &После сделать этого не получается.
Из этой ситуации теперь есть выход. В платформе 8.3.15 появилась замечательная новая аннотация &ИзменениеИКонтроль, в какой-то степени она решит многие проблемы, связанные с тем, что Вам нужно подправить лишь пару строк в заимствованной функции/процедуре модуля, но Вы не хотели бы перехватывать его полностью, с риском в дальнейшем постоянно отслеживать изменения данного модуля (хотя даже при использовании &ИзменениеИКонтроль риски остаются).
Пример использования директивы &ИзменениеИКонтроль (только с версии платформы 8.3.15)
Например, раньше (т.е. сейчас, пока не обновили платформу) нам приходилось писать так:
Теперь можно написать так.
При этом в дальнейшем платформа сама отследит изменения кода расширяемой процедуры и оповестит в случае его изменения, что позволит Вам проанализировать свои дополнения.
4. Делать независимые друг от друга расширения.
Можно ли из одного расширения вызвать функцию в другом расширении? Можно, но может не нужно?
Ведь действительно удобно: сделать одно расширение с некоторым набором общих процедур и функций, которые можно использовать во всех остальных расширениях.
Скажу честно, мы так сделали, и оно действительно работает, работает не плохо, но…
Есть риск "зависимости". Что-то измените в таком шаред-расширении и могут "полететь" все остальные… Но если Вы держите это под своим контролем, то в принципе использовать такой механизм вполне возможно.
5. Новые объекты конфигурации, предполагающие хранение данных, добавлять в основную конфигурацию.
Разработчики 1С сделали многое, чтобы сделать хранение данных в объектах, добавленных в расширении, более безопасным. Но мы пока не рискуем с данными, имеющими критическую важность. Т.е. новые справочники, документы и регистры стараемся добавлять в основную конфигурацию, т.к. они не сильно мешают дальнейшему обновлению типовой конфигурации.
Можно вынести в хранение в расширении, например настроек, логов - т.е. того, что при случае не сильно жалко потерять.
Вообще вести документирование по любому изменению, связанному с типовой конфигурацией - это обязательно (иначе каждое обновление будет превращаться в головную боль).
Рекомендуется также и ведение реестра всех созданных расширений с описанием функционального назначения расширения, а также перечислением процедур и функций, которые оно заимствует из конфигурации, особенно следует выделять те, что используются с аннотацией &Вместо, т.к. на них нужно будет обращаться особое внимание при обновлении.
В нашем случае ведем реестр в общей записной книге OneNote. Пример фрагмента таблицы такого реестра (в некоторых названиях добавлены пробелы, т.к. иначе таблица здесь не поместится в ширину страницы):
На каждом элементе есть ссылка на другую OneNote-страницу с ТЗ (с полным описанием задачи, для чего делалось расширение, какие доработки в него вносились со временем, а также ссылка на GIT-хранилище).
Естественно, каждый сам для себя решает, в каком виде ему удобнее представлять такие сведения, главное, чтобы потом их смогли понять не только Вы, но и те, кто будет после Вас.
В итоге немного о том "Почему именно расширения?":
1) Отвечая на вопрос: "Зачем столько мучений, ведь можно просто внести изменения в конфигурацию?" - зачастую это безвыходная ситуация, когда Вам запретили изменять типовую конфигурацию, а что-то добавить очень хочется.
2) Легко распространять. Если Вы что-то изменили в конфигурации, сразу появляется проблема передачи этого изменения клиенту (отправлять целую конфигурацию для дальнейшего сравнения и объединения не всегда удобно, можно конечно сделать через выгрузку файлов и частичную их загрузку, но тоже не самый простой (для клиента) путь), а вот передача клиенту легких в установке расширений для типовых конфигураций, не требующих от пользователя изменения конфигурации, может стать выходом (но есть, конечно, риски при обновлении).
3) Удобство при работе с Git (см. Git-репозитории при небольших проектах)
В конце хотелось бы задать вопрос сообществу: Используете ли Вы расширения в своей работе?
1) Если да, то с какими трудностями Вы сталкивались (а может не сталкивались)?
2) Если не используете, то почему?
Другие статьи на эту тему: