Видео:
Для тех кому лень читать всю статью, предлагаю посмотреть видео, в котором изложены все приведенные в данной статье принципы:
Ну а всем остальным, добро пожаловать под кат.
Правила и приемы доработки типовых конфигураций 1С для облегчения их дальнейшей поддержки и обновления
Итак, когда мы делаем некоторый проект (под словом «Мы» я понимаю всех людей, которые заняты в автоматизации бизнес-процессов), то надеемся, что потом он плавно перетечет в поддержку. Как правило, если все выполнено хорошо и заказчик доволен, так и происходит.
Поддержку характеризует очень специфический набор задач – это могут быть задачи на консультацию из разряда «откуда здесь взялись такие числа» или на исправление каких-то непонятных ошибок и т.д. Но, так как практически все проекты заключаются в адаптации какого-то типового решения под нужды заказчика, то конфигурацию при поддержке приходится периодически обновлять на новые релизы:
- Если соблюдать некоторые правила разработки, то, потратив совсем незначительные трудозатраты на этапе проекта, в будущем можно будет сэкономить на поддержке и обновлении конфигураций.
- И наоборот, если на этапе проекта были какие-то ошибки, поспешность, неправильное оформление кода, то потом это может вылиться в настоящий ад поддержки и обновления.
Приходилось ли кому-нибудь обновлять конфигурацию, переписанную без всяких опознавательных знаков? Понимаете ли вы, какая это боль – сравнивать старую конфигурацию поставщика с новой конфигурацией, вручную разобрать каждый случай «дважды измененных» при сравнении с текущей конфигурацией и т.д. Это все довольно проблематично.
9 простых правил оформления модификаций в типовых конфигурациях
Итак, 9 простых правил оформления модификаций, которые позволят вам значительно облегчить процесс обновления. Я не утверждаю, что вы должны делать так и никак по-другому, я просто хочу с вами поделиться тем, как это делаем мы, какие правила работают в нашей компании. А брать их или не брать к себе в команду – это уже решать вам.
1. Концепция минимизации «разрушений» типовой конфигурации
Первое – это даже не правило, это некая концепция минимизации «разрушений» типовой конфигурации.
Ее суть в том, что всегда следует выбирать те способы решения задач, которые обеспечат более простое обновление конфигурации в будущем, даже если такое решение несколько сложнее в реализации. Понятно, что это должно делаться без фанатизма, в разумных рамках, но разработчик всегда должен помнить о том, что конфигурация остается на поддержке, и анализировать, насколько его код усложнит обновление конфигурации в будущем, выбирая наиболее подходящее решение.
2. Комментирование изменений кода
Второе правило заключается в том, что любое изменение кода обязательно должно быть прокомментировано.
У нас в компании мы используем следующую схему:
- В начале изменения находится открывающий комментарий (начинается со знаков //++)
- В конце – закрывающий комментарий (начинается со знаков //--)
- А те изменения, который выполнил разработчик, находятся в середине.
Это – обязательное правило для любых изменений.
У открывающего и закрывающего комментария указывается метка изменения. Она содержит в себе следующие составляющие:
- Префикс проекта – по умолчанию мы используем ФТО
- Доменное имя разработчика. Оно формируется очень удобно: компания большая, распределенная, и если ты разработчика не знаешь, но его надо о нем что-то спросить, можно взять его ник из этой метки, поставить справа @fto.com.ru и отправить ему письмо, чтобы таким образом с ним связаться.
- Дальше идет дата изменений. Когда изменения идут в рамках нескольких задач, эти связки комментариев могут быть вложенными одна в другую, и не всегда понятно, к какому открывающему блоку относится этот закрывающий комментарий, поэтому мы ориентируемся на дату. Кроме этого, по дате сразу видно, когда была сделана модификация: три года назад, полгода назад или вчера.
- Затем идет номер задачи, который ставится только в открывающем комментарии. Почему только там? Чтобы при глобальном поиске по номеру задачи в выборку попадало только начало изменений кода, от которого дальше уже можно вниз смотреть, иначе будет двоиться. Например, при передаче задачи на code-review очень удобно искать именно по метке.
Примеры
Вот так выглядит вставка кода:
Вот так выглядит удаление кода – мы не удаляем код полностью, мы комментируем код. За счет этого всегда видно, что было закомментировано, и в случае чего можно быстро вернуться назад.
Вот так выглядит изменение кода: сначала комментируется весь код поставщика, а потом уже добавляется свой код.
Отдельное правило работает для добавления процедур, функций и глобальных переменных модулей. В этом случае закрывающий комментарий ставится на той же строке, что и ключевое слово КонецПроцедуры. Зачем это сделано? Для того чтобы было удобно переносить модификации с помощью «попроцедурного сравнения».
Здесь на картинке видно, что используя «попроцедурное сравнение» можно просто выделить эту процедуру при объединении, и она вся полностью (вместе с метками) перенесется. Или наоборот, можно снять напротив нее галочку, чтобы не переносить.
А если закрывающий комментарий будет на следующей строке, то он будет отнесен к следующей процедуре и его уже просто так без дополнительных затрат перенести не получится.
3. Добавление объектов верхнего уровня
Следующее правило – это добавление в конфигурацию объектов верхнего уровня (справочников, документов, регистров и т.д.).
Это правило заключается в том, что имена объектов обязательно должны начинаться с префикса. Для чего?
- Во-первых, это визуально выделяет добавленный элемент в конфигурации и в коде сразу видно, что это – наш добавленный объект.
- Во-вторых, достигается уникальность имени, потому что поставщик может добавить свой объект с тем же именем. И если мы будем использовать свой префикс, то это гарантирует, что наше имя будет уникально.
Синонимы объектов должны начинаться с префикса в круглых скобках. Это позволяет выделить наш добавленный объект в интерфейсе.
Конечно же, это очень спорное правило, и его применение нужно согласовывать с заказчиком. Наших клиентов такая схема устроила, поэтому она у нас прижилась и попала в правила. Но тут решать только вам и клиенту – надо так делать или не надо.
Ну и последнее правило: комментарии ко всем добавленным объектам должны содержать специальную метку с именем разработчика и номером задачи. Эта метка аналогична открывающему комментарию из модуля, только без специальных символов – с ее помощью я всегда могу понять, кто, когда и по какой задаче добавил этот объект.
Итак, подытожим:
- Имена задаются с префиксом,
- Синонимы – с префиксом в круглых скобках
- И комментарий обязательно должен содержать специальную метку.
4. Добавление подчиненных объектов
Под добавлением подчиненных объектов я подразумеваю добавление реквизитов, макетов, форм и т.д. в объекты конфигурации.
Здесь нужно сразу выделить две ситуации, куда мы добавляем подчиненный объект:
- В типовой объект конфигурации
- Или в какой-то объект, который был добавлен ранее в рамках проекта.
Рассмотрим каждую из этих ситуаций отдельно.
Для добавления подчиненных объектов в типовые объекты конфигурации действуют следующие правила.
- Имена должны начинаться точно так же с префикса. За счет этого мы добиваемся уникальности имени и визуально тоже всегда понятно, что это – наш объект.
- Синоним заполняется без префикса, потому что здесь уже нет необходимости выделять наши объекты, наши реквизиты.
- Ну и наконец, комментарий точно так же содержит специальную метку, чтобы было понятно, кто, когда и зачем.
Итак, давайте подытожим, как происходит добавление подчиненных объектов в типовые объекты конфигурации:
- Имена задаются с префиксом,
- Синонимы по общим правилам
- И комментарии содержат специальную метку.
А если мы добавляем подчиненные объекты в те объекты, которые были ранее добавлены в рамках проекта и уже содержат в своем имени префикс, то:
- Их имена не должны содержать префикса, потому что и так понятно, что объект уже уникален, и как-то еще специально его выделять нет необходимости.
- Синонимы таких подчиненных объектов также задаются без префикса, потому что никакого специального выделения не надо.
- А комментарий содержит специальную метку только в том случае, когда этот подчиненный объект добавлен в рамках другой задачи. Потому что если у меня в задаче написано, что нужно добавить документ, у которого есть такие-то реквизиты, мне для каждого реквизита ставить такую метку не надо. Но если задача совсем другая – я обязательно ставлю метку, чтобы было понятно, зачем я это сделал.
А теперь подытожим, как добавляются подчиненные объекты в объекты, добавленные в рамках проекта:
- Имена без префикса.
- Синонимы без префикса.
- И комментарии должны содержать специальную метку только тогда, когда они добавлены в рамках другой задачи.
Если это правило объединить для обоих случаев и «разложить по полочкам», то получится следующая табличка:
- Новые объекты:
- Имя начинается с префикса.
- Синонимы – с префиксом в круглых скобках.
- Комментарий содержит метку.
- Подчиненные объекты, которые мы добавляем в типовые объекты:
- Имена начинаются с префикса,
- Синоним по общим правилам
- В комментарий ставим метку.
- А если мы добавляем подчиненные объекты в объекты, добавленные в рамках проекта, то
- Для них никаких специальных правил не действует,
- Но если задача другая, то в комментарий точно так же ставим метку.
5. Добавление предопределенных элементов
Следующее правило – добавление предопределенных элементов.
Здесь точно так же можно выделить две ситуации:
- Когда мы добавляем предопределенный элемент в типовой объект конфигурации (в справочник, в план видов характеристик)
- И когда мы добавляем предопределенный элемент в объект, добавленный в рамках проекта.
Если мы добавляем предопределенный элемент в типовой объект конфигурации,
- Его имя точно так же должно начинаться с префикса. Тем самым мы гарантируем уникальность его имени и сможем сразу визуально определить наш добавленный элемент.
- Код и наименование будут формироваться по общим правилам,
- Но метку тут, к сожалению, поставить некуда. Поэтому найти этот добавленный предопределенный элемент глобальным поиском по задаче не получится.
А если мы добавляем предопределенные элементы в объекты, добавленные в рамках проекта, то
- Его имя не будет содержать префикса, так как нет необходимости его как-то выделять.
Итак, если провести аналогию с предыдущей таблицей, то:
- Предопределенные элементы для типовых объектов добавляются с префиксом,
- А все остальные – по общим правилам, никаких специальных добавлять префиксов не надо.
6. Использование общих модулей и их строгая структура
Следующее правило касается использования общих модулей и организации для них строгой структуры.
Во-первых, для различных неоднократно используемых процедур, функций, обработчиков подписок и регламентных заданий следует добавлять собственные модули, оставляя типовые модули неизменными. И если разработчик захочет разместить какую-то экспортную процедуру в типовом модуле, то так делать не надо, надо создать свой модуль.
Во-вторых, обратите внимание, что общие модули добавляются по правилам добавления объектов верхнего уровня (имя и синоним с префиксом, метка в комментарии и т.д.)
В-третьих, имена модулей должны быть аналогичны соответствующим типовым модулям.
Не нужно изобретать велосипед: называем так же, как принято в типовых конфигурациях – для каждой функциональности свой модуль, соответствующий общепринятым в 1С обозначениям. Например:
- ФТО_ОбщегоНазначенияКлиент,
- ФТО_ОбщегоНазначенияСервер,
- ФТО_ОбщегоНазначениеГлобальный,
- ФТО_РегламентныеЗаданияСервер
- И т.д.
А какие-то большие отдельные задачи можно (и, наверное, нужно) выносить в отдельные общие модули.
7. Использование подписок и их строгая структура
Следующее правило – это использование подписок и их строгая структура. В чем его суть?
Подписки следует использовать для обработки различных событий, связанных с типовыми объектами, таких как:
- Перед записью
- При записи
- И т.д.
- Можно конечно взять и отредактировать модуль типового объекта, вставив свой код в соответствующую процедуру. Но это – плохой способ.
- Лучше вместо этого добавить подписку на обработку этого события.
Подписка добавляется согласно следующим обговоренным правилам:
- Для всех однотипных событий в системе добавляется только одна подписка. Например, если мне нужно для различных справочников в событии «Перед записью справочника» задействовать свой алгоритм, то для всех этих справочников я использую только одну добавленную подписку «Перед записью справочника».
- В источнике выделяются все объекты в рамках этого класса (например, все справочники)
- Для добавленной подписки создается отдельный модуль, который называется точно так же (просто для удобства).
- В основном обработчике события определяется условие, анализирующее вид объекта (вид справочника).
- И уже в зависимости от вида объекта выполняются те или иные действия.
Могу показать на примере. Предположим, есть такая задача: при проведении документа «Авансовый отчет» делать записи в добавленный ранее регистр накопления.
Сначала мы добавляем общий модуль ФТО_ДокументыОбработкаПроведения по всем правилам.
Далее мы добавляем подписку, в которой:
- В качестве источника указываем ДокументОбъект ( все документы);
- В качестве обработчика – наш добавленный выше модуль.
И уже в модуле, в самом обработчике мы определяем, что за документ к нам пришел и в зависимости от его вида вызываем ту или иную процедуру.
Подписка одна, а действия могут быть различными. Также можно управлять еще и очередностью вызова процедур.
В результате, порядок действий для создания подписки такой:
- Одна подписка,
- Один общий модуль
- И ничего другого уже не надо: модуль документа остается неизменным – в «дважды измененных» он уже не покажется.
8. Редактирование форм
Следующее правило – редактирование форм.
Здесь точно так же выделим два момента, две ситуации:
- Когда мы редактируем типовые формы;
- И когда мы редактируем формы, добавленные в рамках проекта.
Первая ситуация – это редактирование типовых форм, форм типовых объектов. Это самый спорный пункт правил. В свое время, еще во времена обычных форм, когда проекты в основном делались на УПП, у нас было много дискуссий по поводу того, что делать с формами. Какие были варианты?
- Прямое редактирование обычных форм заключается в том, что я просто меняю форму вручную. При этом варианте каждый раз, когда поставщик вносит в эту форму свои изменения, мне необходимо все свои правки переносить заново. Плохой способ.
- Другой способ – это создание копии формы. Это когда я делаю с типовой формы копию, назначаю ее основной и вношу в нее свои изменения. Но опять же, если эту форму меняет поставщик, мне нужно перенести его изменения в свой вариант вручную. Не самый лучший способ.
- Еще один вариант – это создание отдельной вкладки. Создаем на форме отдельную вкладку и на ней размещаем свои элементы. Понятно, что этот способ не гибкий, потому что иногда свой элемент нужно вставить куда-то именно в определенное место формы. Или нужно изменить свойства типовых элементов, обработчик им новый назначить и т.д. Поэтому это не гибкий способ – он тоже не очень хорошо работает.
- В результате мы выбрали способ полностью программного редактирования форм. Новым разработчикам, которые не сталкивались с этим способом, поначалу кажется, что программно редактировать форму очень сложно. Но на самом деле – нет. Из своей практики скажу, что надо просто набить руку. Кроме того, у нас давно написаны модули с экспортными процедурами по программному изменению форм, и все это делается довольно легко. Когда появились управляемые формы, мы эту практику программного изменения форм также полностью перенесли и на управляемые формы. Тем более, что редактировать управляемую форму программно стало вообще легко – с обычными формами не сравнить.
Давайте покажу на примере. В обработчике ПриСозданииНаСервере я добавляю вызов своей процедуры ДоработатьФормуПрограммно, где у меня происходит программное добавление элементов на форму.
В конфигурациях на базе БСП 2 (таких, как ERP, Бухгалтерия и т.д.) добавился обработчик СобытияФорм.ПриСозданииНаСервере(), который среди прочего, заходит еще и в переопределяемый модуль.
И вот в переопределяемом модуле можно добавить свой код – например, в процедуру ПриСозданииНаСервере(). Здесь я определяю имя формы, и в зависимости от него вызываю ту или иную процедуру, где добавляю элементы программно.
Кажется, что это сложно, что эта схема – громоздкая, но на деле, если все проекты делаются по таким правилам, то разработчик, получая задачу, уже сразу знает, куда ему смотреть, где что добавлять. Поэтому мне кажется, что это очень удобно.
Кроме того, в конфигурациях на базе БСП 2 переопределены еще и другие обработчики форм – такие как ПриЧтенииНаСервере(), ПередЗаписьюНаСервере() и т.д. И в этих обработчиках также можно активно использовать переопределение вызываемых процедур. Тем более что поставщиком переопределяемый модуль теоретически не меняется, и там можно без боязни конфликтов писать свой код.
Если мы редактируем форму, добавленную в рамках проекта, то тут ничего специально делать не надо, мы редактируем ее обычным способом, руками.
9. Принципы работы с ролями
И последнее правило – это принципы работы с ролями.
Принципы работы с ролями заключаются в следующем:
- Если возможно, то типовые роли следует всегда оставлять неименными. Нужно хорошо подумать, действительно ли необходимо изменить именно типовую роль или можно поступить как-то по-другому.
- Права на добавленные объекты конфигурации мы назначаем в новых, специально созданных ролях. Поэтому когда я добавляю в конфигурацию отчет, и для него нет подходящей заранее добавленной нами роли, я создаю отдельную роль. И потом уже эта роль добавляется в нужные профили. А типовые роли не меняются.
- И если есть изменения в RLS, то они оформляются по правилам редактирования модулей.
Например, если мне нужно поменять RLS, то я ставлю открывающий комментарий, комментирую старый код, потом дописываю свой и ставлю закрывающий комментарий. Всегда понятно: кто, зачем (в рамках какой задачи) и когда я менял.
Итак, я перечислил все девять простых правил оформления модификаций.
Дополнительные объекты и приемы, облегчающие жизнь
В заключение я расскажу о некоторых объектах и приемах, которые могут облегчить жизнь разработчику.
1. Самоидентификация тестовых баз
Первый прием – это самоидентификация тестовых баз.
Суть в том, что:
- есть некоторая константа, в которой хранится адрес рабочей продуктивной базы.
- При старте системы происходит проверка этого адреса: соответствует он адресу рабочей базы или не соответствует.
- И если не соответствует (база не рабочая), то происходит замена заголовка системы.
На скриншоте показано, как это выглядит. Это особенно полезно тогда, когда у разработчиков (или у консультантов) открыто много баз (рабочая, тестовая, разработческая и т. д.) и они могут нечаянно ошибиться и поменять данные в рабочей базе. А если заголовок изменен, то уже «на автомате» – глаза в левый верхний угол, смотришь, что это за база – ага, тестовая, можно менять.
Таким образом, мы делаем изменение данных в информационных базах более безопасным.
Кроме того, проверку значения этой константы полезно также применять при выполнении некоторых регламентных заданий. А именно:
- обмены данными,
- уведомления пользователей,
- какие-то рассылки,
- тяжелые регламентные задания.
- И т.д.
Когда разработчик создает такое регламентное задание, он обязательно должен сделать проверку – а рабочая ли это база или нет. Понятно, что по идее, на всех тестовых базах регламентные задания должны быть отключены в консоли кластера. Но всегда есть человеческий фактор, когда кто-то создал новую базу, загрузил в нее свежие данные, что-то поменял и в результате произошел какой-то критичный обмен с рабочими базами. А потом разборки – почему так произошло? Поэтому мы перед критичными регламентными заданиями всегда делаем проверку – рабочая это база или нет.
В конфигурациях на базе БСП 2 есть похожий механизм: если расположение информационной базы меняется, то задается вопрос – это копия базы или база была перемещена. В принципе, этого механизма может быть достаточно, но опять-таки, может вмешаться человеческий фактор, кто-то не поймет, что происходит и нажмет не на ту кнопку. Поэтому, на мой взгляд, константа надежнее.
2. Обработка инициализации
Следующий прием – обработка инициализации.
- Это добавляемая в конфигурацию обработка, которая в своем коде содержит свою текущую версию.
- Одновременно с этим в конфигурацию также добавляется некоторая константа, которая хранит текущую версию обработки инициализации.
- При старте системы производится проверка,
- И, если версия поменялась, выполняются необходимые обработчики и происходит установка нового значения константы.
Зачем это нужно? Часто при добавлении в конфигурацию новой функциональности необходимо произвести какие-то действия в самой базе данных: например, добавили предопределенный элемент справочника, и теперь нужно заполнить его реквизиты. Баз на проекте может быть очень много и заполнять эти данные вручную – это конечно, плохо. Правильнее:
- Увеличить версию обработки инициализации;
- Описать в коде порядок программного заполнения данных;
- И после этого новая версия обработки автоматически через хранилище попадет во все нужные базы, запустится там и выполнит все необходимые действия.
На схеме этот порядок работы показан так:
- Старт системы
- Сравнение версии константы с версией обработки.
- Если не совпадает, выполняются последовательно все необходимые обработчики,
- Устанавливается новое значение константы.
В результате везде, во всех базах данные обновлены.
3. Справочник предопределенных значений
Следующий прием – это справочник предопределенных значений.
Часто возникает необходимость обращаться из кода к существующим элементам справочника, которые не являются предопределенными. Понятно, что лучше создать предопределенный элемент, но так сложилось, что элемент не может быть предопределенным, а нему все равно обратиться.
Какие тут есть варианты реализации?
- Обратиться к элементу по наименованию. Понятно, что наименование поменялось – код перестал работать. Плохо.
- Обратиться по коду. Чуть лучше, но код тоже может поменяться. Не очень хорошо.
- Обратиться по внутреннему идентификатору. Тогда при переносе этот код тоже не будет работать. Вообще все эти три случая не будут работать, если мы переносим модификацию из одной базы в другую базу. Не очень хорошо.
- Предлагается завести справочник предопределенных значений.
Этот справочник содержит в себе только один реквизит с типом СправочникСсылка (ссылка на все справочники).
Если мне в рамках задачи нужно обратиться к какому-то элементу, я в этот справочник добавляю предопределенный элемент (например, Контрагент_Агроимпульс)
И потом уже в коде обработки инициализации либо руками я заполняю значение этого справочника нужным мне контрагентом.
Соответственно, после этого я смогу обратиться к этому контрагенту через справочник предопределенных значений. За счет этого достигается то, что:
- При переносе модификаций между разными базами весь мой код работает без какой-либо дополнительной доработки.
- Плюс, возможно, что сегодня этот контрагент – Агроимпульс, а завтра – это какая-то другая организация, но мне уже в конфигурации ничего модифицировать не нужно, я просто беру и меняю его значение в справочнике предопределенных значений.
4. Просмотр временных таблиц в отладчике
Ну и последний прием – это просмотр временных таблиц в отладчике.
- При отладке сложных запросов с временными таблицами нужна возможность просматривать содержимое этих временных таблиц.
- Для этих целей можно использовать специальную функцию для просмотра временных таблиц.
- Эту функцию удобно расположить в глобальном модуле.
- И назвать как-нибудь коротко, например ВТ()
В этом случае:
- Я ставлю точку останова в месте, где у меня есть запрос.
- В окне «Вычислить выражение» пишу ВТ(Запрос);
- Нажимаю «Рассчитать» и получаю структуру временных таблиц запроса, чтобы просмотреть, что там за данные.
Это очень удобная функция, мы ее постоянно используем. Особенно при расчете себестоимости, или в таких конфигурациях, как ЗУП. Я если честно, не понимаю, как другие без нее живут.
В последней версии платформы появился встроенный инструмент, который позволяет просматривать временные таблицы, но мне кажется, он не очень удобный. Использовать свою функцию гораздо лучше.
Заключение
Всем спасибо. У меня есть небольшой сайт, на этом сайте в подробном изложении выложены все эти правила и не только они – заходите, читайте, пишите мне на почту или в скайп.
Мне эта тема интересна, я готов по ней общаться. Мне правда важно, чтобы у вас тоже все получилось.
Ссылки:
Данная статья написана по итогам доклада, прочитанного на конференции INFOSTART EVENT 2016 DEVELOPER.