Снизить количество ошибок, выявляемых на этапе разработки, и исключить практику написания кода в режиме отладки за счет максимально возможной типизации кода для статического анализатора в 1C:EDT.
Кроме того, типизация кода позволит активнее применять различные средства автоматической обработки кода (автоформатирование, рефакторинг, автоперевод кода и так далее).
Следует использовать следующие возможности:
1. Динамический расчет типов, выполняемый в 1С:EDT на основе контекста 1С:Предприятия и метаданных конфигурации.
2. Статическое указание типов в документирующих/типизирующих комментариях, ссылки на функции-конструкторы и ссылки на входящие параметры.
3. Включение "строгой типизации" для модулей.
## Включение строгой типизации
При использовании дополнительного расширения "1С:Стандарты разработки" для 1С:EDT рекомендуется для модуля включить строгую типизацию, которая будет контролировать, что все типы были созданы правильно, во всех местах используется жесткие ссылки на объекты-создатели, что нет смены типа у переменной.
Контроль типизации будет выполняться для всего модуля, включая не экспортные методы. Контролируется наличие типов всех переменных, используемых вызовов общих модулей, при обращении к полям/свойствам объектов контролируется их наличие и их типы.
Для этого необходимо в заголовке модуля указать аннотацию до первого семантического объекта (области, процедуры, переменной):
Далее 1C:EDT будет отображать ошибки, если с объектами и их типами что-то не корректное.
#### Применение строгой типизации
* Для всех новых конфигураций, не имеющих большого наследия нетипизированного кода, для всех модулей следует включать строгую типизацию.
* Для существующих модулей рекомендуется сначала выполнить адаптацию кода и после включить строгую типизацию.
## Использование контекстного помощника ввода
1. Для того, чтобы код был максимально типизирован изначально - при написании кода следует использовать контент-ассист (или контекстный помощник ввода) Ctrl+Space, который подсказывает все известные свойства объекта.
2. При этом, если помощник ввода не подсказывает нужные свойства - следует сначала уточнить типы (исправить типы) для текущего объекта и продолжить набор текста по известным свойствам.
3. Использование типизации кода снижает потребность написания кода в режиме отладки с целью определения типов переменных, т.к. типы переменных подсказывает среда разработки.
4. Для проверки, того, что объект имеет статический или динамический тип - необходимо выделить нужный объект и нажать `F2` для отображения описания объекта - перед именем объекта должен отображаться его тип.
## Инициализация локальных переменных
- Запрещается инициализация переменных через `Перем` т.к. такая переменная инициализируется с типом `Неопределенно` и дальнейшая смена типа значения может быть не видна для статического анализатора
- Запрещается инициализировать переменные внутри циклов или условий и последующим использованием их вне циклов/условий - т.к. 1С:Предприятие создает все локальные переменные сразу при входе в процедуру - то статическому анализатору невозможно отследить, где была создана переменная и с каким типом
- Уточнение типа локальной переменной, инициализированной, например, функцией возвращающей более общий тип, возможно через указание типа в строке:
НЕПРАВИЛЬНО:
```bsl
// Создает новый объект Номенклатуры по переданному типу
Текущей функциональностью 1C:EDT является запись типа в одну строку в комментарии - что исключает местное описание сложных объектов данных (ТЗ, Структура, массив из структур) - для них необходимо использовать ссылки на функции конструкторы этих объектов.
ПРАВИЛЬНО:
```bsl
МойОбъект = Параметры.МойОбъект; // см. НовыйОбъектДанных
```
Допускается применение типизатора созданного через `Новый ОписаниеТипов(...)` для формирования переменных с необходимым типом начального пустого значения.
ПРАВИЛЬНО:
```bsl
Типизатор = Новый ОписаниеТипов("СправочникСсылка.Номенклатура,СправочникСсылка.НоменклатураПоставщика");
Переменные модуля объекта, формы, конфигурации, включая глобальные переменные (экспортные), следует объявлять со статическим указанием типа в комментарии. Также следует инициализировать переменную модуля начальным/пустым значением в коде модуля (после всех процедур и функций). Для модуля формы допускается инициализация начального/пустого значения в обработчиках событий `ПриСозданииНаСервере` для серверных переменных и в обработчике `ПриОткрытии` для клиентских переменных.
Исключением могут быть не экспортные переменные модуля, используемые только внутри общих механизмов и не имеющие обращений внутри текущего модуля объекта или формы.
НЕПРАВИЛЬНО:
```bsl
#Область ОписаниеПеременных
&НаКлиенте
Перем КэшированныеЗначения; //используется механизмом обработки изменения реквизитов ТЧ
&НаКлиенте
Перем ТекущиеДанныеИдентификатор; //используется для передачи текущей строки в обработчик ожидания
&НаКлиенте
Перем ПараметрыДляЗаписи Экспорт;
#КонецОбласти
```
ПРАВИЛЬНО:
```bsl
#Область ОписаниеПеременных
//используется механизмом обработки изменения реквизитов ТЧ
&НаКлиенте
Перем КэшированныеЗначения; // см. ОбработкаТабличнойЧастиКлиентСервер.ПолучитьСтруктуруКэшируемыеЗначения
//используется для передачи текущей строки в обработчик ожидания
&НаКлиенте
Перем ТекущиеДанныеИдентификатор; // Число -
&НаКлиенте
Перем ПараметрыДляЗаписи Экспорт; // Структура -
#КонецОбласти
....
ТекущиеДанныеИдентификатор = -1;
ПараметрыДляЗаписи = Новый Структура;
```
## Сокращение типа локальной переменной или параметра
- Можно безопасно сократить (или фактически установить для статического анализатора) тип локальной переменной метода, входящего параметра или перменной модуля (объекта, формы) метода через проверку типа:
```bsl
Если ТипЗнч(МояПеременная) = Тип("СправочникОбъект.Товары") Тогда
МояПеременная.Артикул = "";
МояПеременная.Записать();
```
при этом внутри условия переменная будет указанного в проверке типа, как в рантайме, так и для статического анализатора. Условие проверки должно быть простым.
## Инициализация ключей структуры
- Значения ключей структуры (как в конструкторе, так и при добавлении в структуру) должны быть инициализированы сразу с пустым значением того типа, который будет использоваться в последствии. Динамическая типизация не позволяет рассчитать смену типа свойства структуры и, если не указывать пустое значение нужного типа, свойство будет инициализировано с типом Неопределенно.
- Смена типа значения ключа структуры - не допускается.
- При добавлении ключа в существующую структуру следует писать код "прозрачно" для статического анализатора, таким образом чтобы вставка ключа и его использование были в одной области видимости.
- Допускается использовать безопасный доступ к полю структуры в случае, когда структура чужая по отношению к текущему коду и описать поля и их типы нет возможности. Если необходимо безопасно проверить наличие ключа, если ключ опционален. Такой код является кандидатом для рефакторинга.
```bsl
Процедура Обработка()
Если Структура.Свойство("МоеСвойство") И ЗначениеЗаполнено(Структура.МоеСвойство) Тогда
МоеСвойство = Структура.МоеСвойство; // СправочникСсылка.Номенклатура - явное указание типа для неизвестного поля структуры
...
```
Функциональность будет реализована в 1C:EDT будущих версий.
- Ограничение на получение значение ключа через метод "Свойство" не следует использовать: выглядит неплохо, но не анализируемая типизация
НЕПРАВИЛЬНО:
```bsl
Процедура Обработка()
Перем МояПеременная;
Если Структура.Свойство("МоеСвойство", МояПеременная) И МояПеременная = "Полученное значение" Тогда
...
```
ПРАВИЛЬНО:
```bsl
Процедура Обработка()
МояПеременная = "";
Если Структура.Свойство("МоеСвойство", МояПеременная) И МояПеременная = "Полученное значение" Тогда
...
```
## Описание массивов
- В общем случае - запрещено создавать массив `Новый Массив;` без указания типа его значений, если далее в коде текущего модуля происходит обращение к элементам массива.
НЕПРАВИЛЬНО:
```bsl
СписокСсылок = Новый Массив;
СписокСсылок.Добавить(Ссылка);
...
Для каждого Ссылка из СписокСсылок Цикл
Объект = Ссылка.ПолучитьОбъект();
...
```
ПРАВИЛЬНО:
```bsl
СписокСсылок = Новый Массив; // Массив из СправочникСсылка.Номенклатура -
СписокСсылок.Добавить(Ссылка);
...
Для каждого Ссылка из СписокСсылок Цикл
Объект = Ссылка.ПолучитьОбъект();
...
```
ПРАВИЛЬНО:
```bsl
СписокСсылок = НовыйСписокНоменклатуры();
СписокСсылок.Добавить(Ссылка);
...
Для каждого Ссылка из СписокСсылок Цикл
Объект = Ссылка.ПолучитьОбъект();
...
// Возвращаемое значение:
// Массив из СправочникСсылка.Номенклатура
Функция НовыйСписокНоменклатуры()
Возврат Новый Массив;
КонецФункции
```
- Не рекомендуется использовать в качестве значений объекты разных типов: строки с числами, простые типы со ссылочными, объекты БД и структуры и т.д.
- Если значение массива сложное, рекомендуется использовать функцию-конструктор для инициализации пустого массива или массива с данными
- Если в функции создается массив и наполняется значениями, допустимо описывать возвращаемое значение типов элементов массива в описании функции, если в самой функции не происходит обращения к элементам массива.
- В документирующих комментариях следует указывать тип элементов массива для параметров и возвращаемых значений.
## Описание таблицы значений, дерева значений
- Следует при описании объекта `ТаблицаЗначений`, `ДеревоЗначений` всегда описывать все колонки и их типы.
- В общем случае запрещается использовать описание типа `ТаблицаЗначений` в качестве входящего параметра экспортного метода, с описанием колонок. Правильно использовать ссылку на функцию-конструктор создающий эту таблицу.
- Исключением могут быть методы обрабатывающие произвольные таблицы, место создания которых неизвестно, но код метода рассчитывает на наличие определенных колонок. Все колонки, на которые расчитывает код, с их типами должны быть указаны в документирующем описании.
- Исключением являются методы обрабатывающие таблицу значений с неопределенным набором колонок, например "копирование таблицы в структуру", при этом код не обращается к колонкам напрямую `СтрокаТЗ.Номенклатура = ...` а использует для обращения список колонок, сформированный в рантайме `СтрокаТЗ[ИмяКолонки] = ...`.
## Описание строки таблицы или дерева значений
Следует использовать один из двух вариантов:
- прямое указание колонок, на которые рассчитывает код в данной процедуре
- Соответствие - это фактически сложный тип с фиксированным набором колонок (ключ и значение) или аналогичен массиву из структур с 2 колонками. При этом описание типов у ключа и значения есть по умолчанию - `Произвольный`, и необходимо создавать функцию конструктор которая инициализирует соответствие и описывает типы ключа и значения.
- Следует избегать комбинации [различных типов в ключе и в значении соответствия](#ограничения-составных-типов).
ПРАВИЛЬНО:
```bsl
// Возвращаемое значение:
// Соответствие из КлючИЗначение:
// * Ключ - Строка
// * Значение - Массив из ДокументОбъект
Функция НовоеСоответствие()
...
```
## Ссылка на Табличную часть объекта
ПРАВИЛЬНО:
```bsl
// Параметры:
// Объект - См. Справочник.Товары.ЕдиницыИзмерения
Процедура ОбработкаОбъекта(Объект)
```
## Ссылка на Строку Табличной части объекта
> Такая ссылка еще не поддерживается в 1C:EDT!
ПРАВИЛЬНО:
```bsl
// Параметры:
// Объект - СтрокаТабличнойЧасти: См. Справочник.Товары.ЕдиницыИзмерения
Процедура ОбработкаОбъекта(Объект)
```
## Ссылка на тип реквизита объекта или реквизита Табличной части объекта
ПРАВИЛЬНО:
```bsl
// Параметры:
// Реквизит1 - См. Справочник.Товары.Артикул
Процедура ОбработкаОбъекта(Реквизит1)
```
ПРАВИЛЬНО:
```bsl
// Параметры:
// РеквизитТЧ - См. Справочник.Товары.ЕдиницыИзмерения.Единица
Процедура ОбработкаОбъекта(РеквизитТЧ)
```
## Ссылка на Форму
Ссылка на форму казывается по полному имени формы
ПРАВИЛЬНО:
```bsl
/ Параметры:
// Форма - См. Справочник.Товары.Форма.ФормаЭлемента
Процедура ОбработкаОбъекта(Форма)
```
## Ссылка на Элемент Формы, Реквизит формы
Ссылка тип реквизита формы
ПРАВИЛЬНО:
```bsl
/ Параметры:
// Объект - См. Справочник.Товары.Форма.ФормаЭлемента.Объект
Процедура ОбработкаОбъекта(Объект)
```
Ссылка тип элемента формы
ПРАВИЛЬНО:
```bsl
/ Параметры:
// Список - См. Справочник.Товары.Форма.ФормаСписка.Элементы.Список
Процедура ОбработкаОбъекта(Список)
```
## Ссылка на Текущие данные динамического списка формы
Использование ссылки на тип текущих данных динамического списка на форме не поддерживается в документирующих комментариях.
В место этого следует передавать сам элемент формы и далее обрабатывать `ТекущиеДанные`
ПРАВИЛЬНО:
```bsl
// Параметры:
// Список - См. Справочник.Товары.Форма.ФормаСписка.Элементы.Список
Процедура ОбработкаОбъекта(Список)
ЗначениеАртикула = Список.ТекущиеДанные.Артикул;
...
```
## Ссылка на Строку таблицы значений формы
> Такая ссылка еще не поддерживается в 1C:EDT!
ПРАВИЛЬНО:
```bsl
// Параметры:
// СтрокаТЗ - ДанныеФормыЭлементКоллекции: См. Справочник.Товары.Форма.ФормаСписка.Элементы.ТЗ
В этом случае будет выполнено сопоставление имен параметров текущего метода с именами параметров метода "интерфейса".
## Функции-конструкторы сложных объектов данных
Для сложных типов, создаваемых на основе абстрактных платформенных типов (`Структура`, `Соответствие`, `ТаблицаЗначений`, `ДеревоЗначений` и др.), следует использовать функцию-конструктор данных.
Наименование функции следует выбирать как `Новый`/`Новая`/`Новое` (`New`) и наименование объекта данных.
ПРАВИЛЬНО:
```bsl
// Возвращаемое значение:
// ТаблицаЗначений:
// * Номенклатура - СправочникСсылка.Номенклатура
Функция НоваяТаблицаОтобраннойНоменклатуры()
....
КонецФункции
```
- Конструктор данных может так же выполнять функцию заполнения данных т.е. предоставлять новый объект с заполненными данными. Например, функция выполняет запрос к БД и возвращает таблицу значений с колонками и данными.
### Указание ссылки на функцию-конструктор данных
При описании параметра метода следует указывать ссылку на функцию-констроктор данных без указания исходного базового типа данных (структура, таблица значений и т.д.).
НЕПРАВИЛЬНО 1:
```bsl
// Заполняет список команд печати.
//
// Параметры:
// КомандыПечати - ТаблицаЗначений - состав полей см. в функции УправлениеПечатью.СоздатьКоллекциюКомандПечати.
При обработке более общих типов объектов в общих модулях может потребоваться получить заранее известный комплексный тип (`Структура`, `ТаблицаЗначений`, `ДеревоЗначений`), при этом, функции-конструктора таких данных может не существовать, например когда данные создаются объектом метаданных, формой, СКД и так далее. Для таких случаев следует использовать функцию-получатель, описывающую тип возвращаемого значения со всеми необходимыми свойствами/полями объекта.
Для клиентских процедур не рекомендуется использовать конструкторы из модулей с контекстом 'Сервер', но без контекста 'Вызов сервера'.
НЕПРАВИЛЬНО:
```bsl
// Параметры:
/// Форма - ФормаКлиентскогоПриложения - форма, для элементов которых производится заполнение
// Параметры - Структура - дополнительные параметры дерева.
## Ограничение на использование в документирующих описаниях Массивов, ТЗ, Структур
Для параметров экспортных методов рекомендуется указывать ссылку на функцию-конструктор таких объектов.
Не рекомендуется указывать в качестве параметров не экспортных методов сложные типы на основе `Массивов`, `Таблиц Значений`, `Структур` и т.д., если объект является цельным, созданным в текущем модуле и контекст передачи объекта ограничен текущим модулем. В этом случае 1C:EDT не выполняет динамическую типизацию таких параметров, а использует указанные статические типы в описании метода.
Допускается описание таких типов во входящих параметрах, если описывается часть объекта или программный интерфейс объекта, например несколько колонок `ТЧ.Товары` для которых выполняется расчет, при этом не существует одной единой функции-конструктора на которую можно сослаться в описании.
## Описание программных интерфейсов для реализации в прикладных объектах
Существует понятие "описания программного интерфейса объекта" и его реализация в прикладных объектах конфигурации. С применением библиотечного подхода к разработке конфигураций, библиотека может описывать некий программный интерфейс который должен быть реализован в прикладном объекте, для того чтобы библиотечный механизм имел достук к объкту.
Например, механизм "Свойства" из библиотеки БСП описывает интерфейс объекта: Наличие табличной части `ДополнительныеРеквизиты`, содержит колонки `Свойство`, `Значение`, `ТекстоваяСтрока` с определенными типами. Далее общий механизм библиотеки может обращаться к объекту например, при записи `УправлениеСвойствами.ПередЗаписьюНаСервере(ЭтотОбъект, ТекущийОбъект);` объекта из формы.
Следует описывать интерфейс входящего объекта для той части объекта, которая требуется для работы механизма. При этом, следует учитывать что механизм расширений свойств в документирующих коментариях поддерживается для тех типов, у которых возможны пользовательские совойства. Например: элементы коллекции вместо самих коллекций - тип `ТабличнаяЧасть` не имеет пользовательских свойств, а тип `СтрокаТабличнойЧасти` может иметь; тип `ДанныеФормыКоллекция` не имеет пользовательских свойств, а тип `ДанныеФормыЭлементКоллекции` может иметь.
НЕПРАВИЛЬНО:
```bsl
// Параметры:
// Форма - ФормаКлиентскогоПриложения - уже настроена в процедуре ПриСозданииНаСервере:
// * Элементы - ВсеЭлементыФормы:
// ** ДополнительныеРеквизиты - ГруппаФормы
// * Свойства_ИспользоватьСвойства - Булево
// * Свойства_ИспользоватьДопРеквизиты - Булево
// ....
//
// Объект - Неопределено - взять объект из реквизита формы "Объект".
// - СправочникОбъект, ДокументОбъект, ДанныеФормыСтруктура - (по типу объекта) где:
## Описание используемых реквизитов и элементов форм для общего кода по работе с формами
- Допускается описание части формы, общие для нескольких форм или реализация некого интерфейса для общего механизма конфигурации. Например, части одного общего механизма подключенные к множеству объектов конфигурации (дополнительные реквизиты, контактная информация и т.д.).
ПРАВИЛЬНО:
```bsl
// Параметры:
// Форма - ФормаКлиентскогоПриложения:
// * Объект - ДанныеФормыСтруктура, СправочникОбъект, ДокументОбъект - основной реквизит формы
// * Элементы - ВсеЭлементыФормы:
// ** Товары - ТаблицаФормы - элемент таблицы товаров
- Если используется конкретная форма, следует в документирующих комментариях модулей (общих, менеджеров) указывать полную ссылку на форму.
```bsl
// Параметры:
// Форма - см. Справочник.Номенклатура.Форма.ФормаЭлемента
Процедура ПриСозданииНаСервере(Форма)
Ссылка = Форма.Объект.Ссылка;
Форма.Элементы.Артикул.Видимость = Истина;
....
```
- Для функций общих модулей, расчитывающих на дополнительные свойства и методы расширения типа `ФормаКлиентскогоПриложения` следует использовать соответствующие типы расширений управляемой формы: `РасширениеУправляемойФормыДляОбъектов`, `РасширениеУправляемойФормыДляДокумента`, `РасширениеУправляемойФормыДляДинамическогоСписка` и так далее.
```bsl
// Параметры:
// Форма - РасширениеУправляемойФормыДляОбъектов -
Процедура ОбработкаЗакрытия(Форма) Экспорт
....
Форма.Записать();
....
```
## Получение и открытие формы
- При использовании методов `ПолучитьФорму()` и `ОткрытьФорму()` с присвоением возвращаемого значения формы после открытия - следует указывать строковый литерал с полным именем формы первым параметром.
- Не следует выносить строковый литерал в отдельную переменную т.к. в этом случае переменная форма будет содержать общий тип `ФормаКлиентскогоПриложения` а не конкретный тип формы справочника номенклатуры, и весь контекст формы не будет доступен. В 1C:EDT на текущий момент поддерживается полная типизация только для полных имен форм, ссылки на основные формы для объекта метаданного `ФормаОбъекта`, `ФормаСписка` и т.д. возвращают общий тип `ФормаКлиентскогоПриложения`, полная типизация может быть поддержана в будущих версиях.
Форма = ПолучитьФорму("Справочник.Номенклатура.Форма.ФормаЭлемента");
Форма = Справочники.Номенклатура.ПолучитьФорму("ФормаЭлемента");
```
## Экспортные процедуры и функции
- Все параметры методов и возвращаемые значения функций должны содержать описания типов, при этом пояснения к параметрам следует описывать в соответствии со стандартом [?]
- Локальные процедуры и функции не обязаны содержать описаний типов в документирующих комментариях и могут быть полностью расчетными, если код написан прозрачно для статического анализатора.
## Разрыв прямого контекста выполнения кода
- В случае разрыва прямого вызова методов в рамках одного модуля (когда из одного метода напрямую вызывается другой метод) - следует описывать типы входящих параметров для не экспортных методов.
## Использование временного хранилища и других контейнеров
- Поместить во временное хранилище и после получить из него - можно все что угодно, поэтому необходимо выделять функцию возвращающую тип помещенный во временное хранилище использовать на нее ссылку при получении:
```bsl
Данные = ПолучитьИзВременногоХранилища(Адрес); // см. НовыйОбъектДанных
```
- Аналогичный подход следует использовать при помещении пользовательского объекта внутрь другого объекта-контейнера, например `ДполнительныеПараметры` у объектов, или `Параметры` формы, пользовательские параметры элементов `СКД`, `ДополнительныеПараметры` у обработчиков оповещения и так далее.
## Использование строковых литералов в качестве имен
Не следует обращаться к элементу именованной коллекции, например `ВсеЭлементыФормы` и другие, через строковый индекс с именем элемента. Вместо этого следует обращаться напрямую к элементу так как в этом случае статический анализатор может контролировать наличие элемента, его тип.
НЕПРАВИЛЬНО:
```bsl
Элементы["Наименование"].Видимость = Ложь;
```
ПРАВИЛЬНО:
```bsl
Элементы.Наименование.Видимость = Ложь;
```
Исключением может быть:
* обращение к элементам и свойствам создаваемым программно и в момент статического анализа их еще не существует. При этом следует указывать тип локальной переменной полученного значения и уже потом обращаться к ее свойства:
НЕПРАВИЛЬНО:
```bsl
Элементы["Наименование"].Видимость = Ложь;
Элементы["Наименование"].Доступность = Истина;
```
ПРАВИЛЬНО:
```bsl
Элемент = Элементы["Наименование"]; // ПолеФормы -
Элемент.Видимость = Ложь;
Элемент.Доступность = Истина;
```
* наличие таких элементов в коллекции может быть опциональным, при этом выполняется проверка наличия элемента. Например: исходный объект с неопределенными свойствами создается где-то вне и передается в текущую функцию входящим параметром.
## Ограничение на использование реквизитов формы с типом "Произвольный"
Реквизит формы с типом `Произвольный` в коде следует рассматривать как "черный ящик". Статический анализатор не отслеживает изменение типа реквизита формы, поэтому весь обслуживающий этот реквизит код должен использовать проверку типа значения.
В общем случае не следует использовать реквизит с типом `Произвольный` на форме, т.к. при этом разработчик самостоятельно несет ответственность за инициализацию значения в этом реквизите, за то, что все типы данных хранимые в реквизите могут быть сериализованы/десериализованы при передаче с клиента на сервер и обратно. Так же значение реквизита будет передаваться между клиентом и сервером всегда т.к. Платформа не контролирует модификацию значений например внутри структуры помещенной в произвольный реквизит.
Реквизит с типом `Произвольный` следует заменять на честные реквизиты формы с определенными типами. Исключением может быть хранимые данные общих механизмов библиотек, которые через программный интерфейс инициализируют и обрабатывают хранимое в этом реквизите значение.
Если заменить реквизит с типом `Произвольный` нет возможности, следует использовать функцию-конструктор для ициализаци значения и дальнейших ссылок на типы. При этом не следует напрямую обращаться к реквизиту - для получения значения следует использовать функцию-получатель.
ПРАВИЛЬНО:
```bsl
// Возвращаемое значение:
// Структура:
// * Ссылка - СправочникСсылка.Номенклатура - ссылка на текущую номенклутру
// ...
Функция НовыйСложныйОбъектДанных()
Данные = Новый Структура;
Данные.Вставить("Ссылка", ...);
...
Возврат Данные;
КонецФункции
// Возвращаемое значение:
// см. НовыйСложныйОбъектДанных
Функция РеквизитПроизвольный()
Возврат РеквизитПроизвольный;
КонецФункции
...
// Инициализация реквизита через функцию-конструктор
// Обращение к значению в реквизите с произвольным типом
Ссылка = РеквизитПроизвольный().Ссылка;
```
## Использование параметров формы
- Запрещается использовать параметр с типом "Произвольный" для передачи структуры параметров для инициализации формы.
- В редакторе формы на вкладке "Параметры" следует описывать все параметры, на которые опирается форма при открытии, включая необязательные.
## Выборка и выгрузка из результата запроса
При типизации выборки/выгрузки из результата запроса следует использовать возможности:
1. Статическое описание всех полей выборки (полей таблицы значений выгрузки) в возвращаемом значении [функции-получателе данных](#функции-получатели-сложных-объектов-данных). Может применяться для функций, динамически формирующих текст запроса и выборку, а так же все экспортные функции, возвращающие выборку.
2. Динамическая типизация полей выборк на основе текста запроса. В будущих версиях 1C:EDT может быть реализована возможность обращаться к полям запроса, при условии что текст запроса и выборка (результат запроса) находятся в одной процедуре, текст запроса не содержит ошибок (открыавется "Конструктором запросов"), выборка/выгрузка из результата запроса не передается в другой модуль для обработки.
НЕПРАВИЛЬНО:
```bsl
Запрос = Новый Запрос;
Запрос.Текст =
ТексЗапросаОстатков()
+ ТекстЗапросаРезервов();
РезультаЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Ссылка = Выборка.Ссылка.ПолучитьОбъект();
...
```
ПРАВИЛЬНО:
```bsl
// Возвращаемое значение:
// ВыборкаРезультатаЗапроса:
// * Номенклатура - СправочникСсылка.Номенклатура
Функция ОстаткиДляОбработки()
Запрос = Новый Запрос;
Запрос.Текст =
ТексЗапросаОстатков()
+ ТекстЗапросаРезервов();
РезультаЗапроса = Запрос.Выполнить();
Возврат РезультатЗапроса.Выбрать();
КонецФункции;
...
Выборка = ОстаткиДляОбработки();
Пока Выборка.Следующий() Цикл
Ссылка = Выборка.Номенклатура.ПолучитьОбъект();
...
```
ПРАВИЛЬНО:
```bsl
Запрос = Новый Запрос;
Запрос.Текст = "
| ВЫБРАТЬ
| Номенклатура
|ИЗ
| РегистраНакопления.Остатки.Остатки
|
| ОБЪДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Номенклатура
|ИЗ
| РегистрНакопления.Резервы.Остатки
|";
РезультаЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Ссылка = Выборка.Номенклатура.ПолучитьОбъект();
...
```
## Передача пользовательского объекта данных в другой модуль
Объекты данных созданные пользовательским кодом и использованные вне текущего модуля - должны быть описаны функцией возвращающей значение.
Использование типа созданного в текущем модуле, но не предназначенного для создания в другом модуле - следует использовать не экспортную функцию-конструктор, при этом существует 2 варианта:
1. Экспортная функция, которая возвращает это значение вместе с данными (функция-получатель) - в ней нужно в возвращаемом значении указать функцию-конструктор
2. Реализация какого-либо интерфейса из переопределяемого модуля - в этом случае, можно использовать ссылку на параметр
## Описание типов макетов СКД и Табличного документа
- В случае получения макета через универсальную процедуру - следует указывать в строке тип макета.
## Ограничение на создание пользовательских объектов-копий (Структуры, ТЗ) из платформенных объектов
- Существуют процедуры которые создают ТЗ или структуру аналогичную какому-нибудь объект метаданных, далее выполняется копирование значений для каждого свойства
- Не рекомендуется, т.к. Необходимо будет описать весь объект самостоятельно
- В исключительных случаях (каких?) можно сделать функцию-конструктор описывающую смешанный тип `Структура + СправочникОбъект.Номенклатура` чтобы не описывать весь тип. При этом можно добавить в описание дополнительные колонки, которые вводятся для технических целей (помощь при копировании, передача дополнительной информации с объектом).
- Следует учитывать ограничение на описание строк ТЧ объектов метаданных.
## Ограничения составных типов
- В общем случае неправильно делать составные типы, которые мало похожи между собой. Например:
- Строка и СправочникОбъект
- Число и Массив
- Коллекции (массив, ТЗ, Соответствие, ТЧ, Структура) и простые типы (строка, число, ссылка)
- ДеревоЗначений и ТаблицаЗначений
- Наличие таких смешанных типов - однозначный повод для рефакторинга кода.