Пиши код правильно — по стандарту. Часть 4. Бизнес-логика, открытие форм, запросы, библиотеки
В данной статье описываю кратко часть статей стандарта для использования в работе. Вы можете использовать эту информацию как шпаргалку, для быстрого напоминания отдельных пунктов стандарта, или если впервые знакомитесь со стандартами.
В четвертой части статьи освещаются вопросы, касающиеся бизнес-логики и форм.
Contents
- 1 Бизнес-логика
- 2 Единообразие пользовательского и программного интерфейсов
- 3 Открытие форм #std404
- 4 Размещение текста запросов
- 5 Оформление текстов запросов #std437
- 6 Типичные случаи программной модификации текста запроса
- 7 Псевдонимы источников данных в запросах #std758
- 8 Использование вложенных запросов
- 9 Дублирование кода и использование библиотек
Бизнес-логика
Частой ошибкой является размещение всего кода в форме без разделения на интерфейсный и бизнес-логики. Размещение кода бизнес-логики в модуле форм не позволяет использовать его при программной работе с объектом.
Под бизнес-логикой понимаем код, обеспечивающий бизнес-процессы. Т.е. какие есть данные об объектах бизнеса (товары, инструменты, автомобили и т.д.), как преобразуются, куда передаются и т.п.
Это приводит к тому, что при последующем изменении кода приходится декомпозировать код, выделять из него бизнес-логику, переписывать код модуля формы и только после этого приступать к задаче. Некоторые программисты решают эту задачу дублированием кода, что не рекомендуется, так как в дальнейшем сложнее поддерживать — при изменении бизнес-логики требуется не забыть исправить оба места размещения кода.
Пример декомпозиции задачи и соответствующие места размещения кода:

Единообразие пользовательского и программного интерфейсов
В случаях когда при выполнении каких-либо действий с полями на форме производятся какие-то дополнительные действия, например, заполнение других реквизитов на основании, данные действия должны также производиться при программном взаимодействии, особенно если выполняется заполнение расчетных, невидимых, скрытых реквизитов.
Часто в ТЗ заказчик при заполнении реквизитов описывает, как это должно производиться в форме. При этом те реквизиты, которые не видны, но влияют на поведение объекта, остаются неописанными. И в таком случае при программном заполнении реквизитов могут появляться ошибки либо несоответствия заполнения в форме и при программном заполнении. Это происходит из-за того, что предыдущие разработчики заложили важный для заполнения код в его форму и, соответственно, дозаполнения полей, служебных реквизитов не происходит, если заполняем не из формы.
Данных проблем можно было бы избежать если, например, в обработчике ПередЗаписью добавили простой код по заполнению.
Хороший пример единого поведения пользовательского и программного интерфейсов можно посмотреть в «Справочнике Пользователей» из состава «Библиотеки стандартных подсистем».

На скриншоте выделены зеленым квадратом поля, которые не являются реквизитами «Справочника Пользователей».
Создан программный интерфейс объекта и подробно описан в модуле объекта «Справочника Пользователей». Интерфейс создан на базе дополнительных свойств, весь код размещен в одном месте, и неважно, где мы пишем код, в модуле формы или в другом модуле, действуем всегда одинаково: правильно заполняем дополнительные свойства.
Открытие форм #std404
1. Для открытия форм следует применять метод глобального контекста ОткрытьФорму (при использовании версии платформы «1С:Предприятие 8.2» и более ранних версий также ОткрытьФормуМодально). Применение альтернативного способа с получением формы и ее последующим открытием с помощью метода ПолучитьФорму не рекомендуется.
Рекомендация обусловлена соображениями:
- повышения устойчивости кода, работающего с формой, за счет разделения программного интерфейса для работы с формой и деталей ее внутренней реализации,
- а также сохранения единой стилистики кода прикладных решений.
Кроме того, применение глобального метода ОткрытьФорму гарантирует выполнение инициализации формы на сервере в обработчике ПриСозданииНаСервере. Этот подход помогает сосредоточить весь код инициализации формы в одном месте и исключает «случайное» обращение к серверу, связанное с инициализацией формы, между строками кода
Форма = ПолучитьФорму(...)
и
Форма.ОткрытьФорму(...)
2. В случаях когда форма требует параметризации при открытии, все ее параметры следует указывать в наборе параметров формы. Таким образом, набор параметров формы декларативно описывает возможности формы по ее параметризации.
Параметры формы из этого набора могут быть указаны в вызывающем коде при открытии формы (ОткрытьФорму).
3. Не следует применять другие способы параметризации формы при открытии. Например, нужно избегать обращения к методам и свойствам формы после ее открытия.
Например, вместо
ФормаПутеводитель = Форма.ОткрытьФорму("ОбщаяФорма.ПутеводительПоСистеме");
ФормаПутеводитель.Элементы.ГруппаШаг.ТекущаяСтраница =
ФормаПутеводитель.Элементы.ГруппаШаг.Страницы.Приветствие;
следует по той же причине использовать параметры формы:
ОткрытьФорму("ОбщаяФорма.ПутеводительПоСистеме",
Новый Структура("РежимОткрытия", "Приветствие"));
4. Для получения результата работы формы, вместо непосредственного обращения к элементам и реквизитам формы:
ФормаВопроса = ПолучитьФорму("ОбщаяФорма.ФормаВопроса");
ФормаВопроса.ОткрытьМодально();
Если ФормаВопроса.БольшеНеПоказыватьНапоминание Тогда
// …
следует использовать процедуры-обработчики оповещений, которые будут вызваны при завершении работы пользователя с формой:
Оповещение = Новый ОписаниеОповещения("БольшеНеПоказыватьНапоминаниеЗавершение", ЭтотОбъект);
ОткрытьФорму("ОбщаяФорма.ФормаВопроса",,,,, Оповещение, РежимОткрытияОкнаФормы.БлокироватьВеcьИнтерфейс);
...
&НаКлиенте
Процедура БольшеНеПоказыватьНапоминаниеЗавершение (БольшеНеПоказыватьНапоминание, Параметры) Экспорт
Если БольшеНеПоказыватьНапоминание = Неопределено Тогда
Возврат;
КонецЕсли;
Если БольшеНеПоказыватьНапоминание Тогда
// …
КонецПроцедуры
При этом возвращаемое значение формы формируется в коде модуля формы с помощью метода формы «Закрыть».
Закрыть(Результат);
5. Другие ограничения:
Обработчик события формы ПриОткрытии не должен содержать код по открытию какой-либо другой формы, так как это может привести к нарушению порядка отображения окон. В этом случае рекомендуется использовать обработчик ожидания на короткий интервал или открывать другие формы интерактивно, например, по нажатию на кнопку.
Не рекомендуется выполнять программное открытие и закрытие формы в одном обработчике. Такие действия должны быть разнесены по времени. Например, закрытие формы можно выполнять в обработчике ожидания.
При использовании в конфигурации «Библиотека стандартных подсистем» и разработке форм (рабочих мест), предназначенных только для внешних пользователей, следует явно блокировать открытие таких форм в сеансах «обычных» пользователей. Для этого следует устанавливать параметр Отказ при создании формы на сервере с помощью функции ЭтоСеансВнешнегоПользователя общего модуля Пользователи или ПользователиКлиент:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Не ПользователиКлиентСервер.ЭтоСеансВнешнегоПользователя() Тогда
Отказ = Истина;
Возврат;
КонецЕсли;
…
КонецПроцедуры
6. Следующие виды форм должны быть всегда доступны пользователю в режиме «1С:Предприятия» из меню «Все функции» вне зависимости от того, размещены ли соответствующие объекты в командном интерфейсе приложения или нет:
- основная форма списка (для всех объектов),
- основная форма обработки,
- основная форма отчета.
Размещение текста запросов
Рекомендуется текст запроса (кроме коротких — 4 строки) выносить в отдельную функцию.
Размещение текста запроса в методе выполнения запроса приводит к значительному увеличению объема метода выполнения запроса. При этом если требуется проанализировать код, отдельно анализируется код выполнения запроса и обработки результатов запроса и отдельно анализируется сам текст запроса.
Оформление текстов запросов #std437
1. Все ключевые слова языка запросов пишутся заглавными буквами.
2. Рекомендуется указывать и необязательные конструкции запроса, прежде всего, явно назначать псевдонимы полям в целях повышения наглядности текста запроса и «устойчивости» использующего его кода. Например, если в алгоритме используется запрос с полем, объявленным как
Касса.Валюта
при изменении имени реквизита нужно будет также изменить и код, осуществляющий обращение по имени свойства «Валюта» к выборке из результата запроса. Если же поле будет объявлено как
Касса.Валюта КАК Валюта
то изменение имени реквизита приведет только к изменению текста запроса.
2а. Особенно внимательно следует относиться к автоматически присваиваемым псевдонимам для полей – реквизитам других полей, типа
... Касса.Валюта.Наименование...
В приведенном выше примере поле получит автоматический псевдоним ВалютаНаименование, а не Наименование.
2б. Следует обязательно указывать ключевое слово КАК перед псевдонимом поля источника.
3. Текст запроса должен быть структурирован: не следует писать запрос в одну строку, даже короткий. Текст запроса должен быть нагляден, поскольку это существенно улучшает его понимание другими разработчиками.
4. В запросы, сложные для понимания, в которых используются вложенные запросы, объединения или соединения, рекомендуется вставлять комментарии. Комментарии, например, могут объяснять для получения каких данных используется та или иная таблица в соединении или объединении.
При этом необходимо иметь в виду, что при использовании конструктора запросов все комментарии в запросе удаляются автоматически, без предупреждения.
5. При создании объекта Запрос рекомендуется указывать комментарии, для получения какой информации или каких иных целей будет использован данный запрос.
6.1 При программной «сборке» текста запроса рекомендуется комментировать все этапы его сборки.
6.2. Нужно стараться, чтобы каждая часть формируемого запроса могла быть открыта с помощью конструктора запросов:
— позволяет осуществить экспресс-проверку корректности синтаксиса запроса,
— упрощает разработку и сопровождение кода конфигурации, в том числе сторонними разработчиками.
Типичные случаи программной модификации текста запроса
1. Изменение имени поля выборки или таблицы
Неправильно:
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование ,
| Номенклатура. " + ИмяПоляКод + " КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Правильно:
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК Наименование,
| &ИмяПоляКод КАК КодАртикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяПоляКод", "Номенклатура." + ИмяПоляКод);
или аналогично для имени таблицы
ТекстЗапроса =
"ВЫБРАТЬ
| ТаблицаСправочника.Наименование КАК Наименование,
| ТаблицаСправочника.Код КАК Код
|ИЗ
| &ТаблицаСправочника КАК ТаблицаСправочника";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ТаблицаСправочника", "Справочник." + ИмяСправочника);
или еще один вариант для имени таблицы
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Наименование КАК НаименованиеТовара ,
| ЕСТЬNULL(ТаблицаОстатков.ВНаличииОстаток,0) КАК ОстатокТовара
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ #ТаблицаОстатков КАК ТаблицаОстатков
| ПО Номенклатура.Ссылка= ТаблицаОстатков.Номенклатура";
Если ИспользуетсяАдресноеХранение Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаОстатков", "РегистрНакопления.ТоварыВЯчейках.Остатки");
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "#ТаблицаОстатков", "РегистрНакопления.ТоварыНаСкладах.Остатки");
КонецЕсли;
2. Использование комментария для помещения во временную таблицу результата запроса
Неправильно:
ТекстЗапроса =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|// ПОМЕСТИТЬ втКонтрагенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
Если ВыгрузитьВоВременнуюТаблицу Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "// ПОМЕСТИТЬ", "ПОМЕСТИТЬ");
КонецЕсли;
Правильно:
ТекстЗапроса =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Ссылка
|ПОМЕСТИТЬ втКонтрагенты
|ИЗ
| Справочник.Контрагенты КАК Контрагенты";
Если Не ВыгрузитьВоВременнуюТаблицу Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПОМЕСТИТЬ втКонтрагенты", "");
КонецЕсли;
3. Конкатенация нескольких текстов запросов в пакет
Неправильно:
ТекстЗапроса = " ";
Если ИспользоватьУпаковки Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Упаковки КАК Упаковки;
|/////////////////////////////////////////////////////////////
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса +
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник. Номенклатура КАК Номенклатура";
Правильно
ТекстЗапроса = " ";
Если ИспользоватьУпаковки Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Упаковки КАК Упаковки";
ТекстЗапроса = ТекстЗапроса +
"
|;
|/////////////////////////////////////////////////////////////
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса +
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
Или
Разделитель =
"
|;
|/////////////////////////////////////////////////////////////
|";
ТекстыЗапросовПакета = Новый Массив;
ТекстЗапроса =
"ВЫБРАТЬ
| Упаковки.Ссылка КАК Ссылка
|ИЗ
| Справочник.Упаковки КАК Упаковки";
ТекстыЗапросовПакета.Добавить(ТекстЗапроса);
ТекстЗапроса =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура";
ТекстыЗапросовПакета.Добавить(ТекстЗапроса);
ТекстЗапроса = СтрСоединить(ТекстыЗапросовПакета, Разделитель);
Псевдонимы источников данных в запросах #std758
1. Псевдоним источника данных должен быть осмысленным, чтобы было понятным его назначение в данном контексте. Требования к псевдонимам источников схожи с требованиями к именам переменных в коде:
- псевдонимы следует образовывать от терминов предметной области таким образом, чтобы было понятно, как источник данных будет использоваться в запросе;
- псевдонимы следует образовывать путем удаления пробелов между словами. При этом каждое слово в имени пишется с прописной буквы (например, ТоварыНаСкладах). Предлоги и местоимения из одной буквы также пишутся прописными буквами;
- псевдонимы запрещается начинать с подчеркивания;
- псевдонимы не должны состоять из одного символа.
Неправильно:
ВЫБРАТЬ
Таблица1.Ссылка КАК Товар,
ЕстьNULL(Таблица2.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК Таблица1
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Таблица2
ПО Таблица1.Ссылка = Таблица2.Номенклатура
Правильно:
ВЫБРАТЬ
ВсяНоменклатура.Ссылка КАК Товар,
ЕстьNULL(ОстаткиНаСкладах.КоличествоОстаток, 0) КАК Остаток
ИЗ
Справочник.Номенклатура КАК ВсяНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ОстаткиНаСкладах
ПО ВсяНоменклатура.Ссылка = ОстаткиНаСкладах.Номенклатура
В частности не рекомендуется использовать имена классов объектов метаданных («Справочник», «Документ» и т.д.), т.к. обычно такой псевдоним не будет описывать назначение источника в конкретном запросе.
2. В ряде случаев при разработке универсальных механизмов, рассчитанных на работу с произвольными таблицами данных, или при написании универсальных запросов, когда вместо источника данных при исполнении кода подставляется имя конкретной таблицы, допустимо использование универсальных псевдонимов.
Пример:
"ВЫБРАТЬ
Таблица.Наименование КАК Наименование
Таблица.Код КАК Код
ИЗ
&Таблица КАК Таблица";
ТекстЗапроса = СтрЗаменить(ТекстЗапроса , "&Таблица", "Справочник." + ИмяСправочника);
Использование вложенных запросов
Не рекомендуется использовать вложенные запросы.
Причины:
— запросы со временными таблицами читаются легче;
— отмечается зачастую медленное выполнение запроса (см. Ограничения на соединения с вложенными запросами и виртуальными таблицами);
— сложнее проверять, что выдает вложенный запрос по сравнению с временными таблицами;
— сложнее редактировать в конструкторе запросов.
Дублирование кода и использование библиотек
1. Есть принцип, пришедший из общего программирования, — DRY (Don’t Repeat Yourself — «не повторяйся»). Согласно этому принципу, программный код не должен копироваться. Если код должен быть использован более чем в одной точке программы, он должен быть вынесен в отдельный метод, доступный из каждой точки.
Дублирование кода создает проблемы для поддержки конфигурации:
— при исправлении этого кода необходимо найти все точки использования;
— если код при дублировании немного исправлялся, например, изменены наименования используемых переменных, это добавляет сложности понять, тот ли это код и нужно ли его менять;
— повышение временных затрат на изменение кода;
— усложняется понимание структуры программы.
2. Для уменьшения необходимости многократного использования кода создаются библиотеки, обеспечивающие единообразное решение задач.
Например:
— библиотека стандартных подсистем,
— библиотека подключаемого оборудования,
— библиотеки для конкретных конфигураций,
— самописные библиотеки.
Самая часто используемая библиотека — это библиотека стандартных процедур. Для успешного программирования нужно изучить эту библиотеку.
Данная библиотека имеет множество версий. Описание версий доступно на сайте its.1c.ru. Например, здесь доступно описание версии 3.1.11.
Для изучения БСП необходимо открыть состав библиотеки. В составе описаны все подсистемы, входящие в текущую версию. При использовании каких-либо подсистем нужно не забыть ознакомиться с главой 3 «Настройка и использование подсистем при разработке конфигурации».
Узнать версию БСП, которая внедрена в конфигурации, можно в регистре сведений «Версии подсистем» в строке «СтандартныеПодсистемы».

Comments
So empty here ... leave a comment!