Что такое формальные параметры процедуры 1с. Описание процедур и функций. Передача параметров по значению

Заранее извиняюсь за пафосную аннотацию про "расстановку точек", но надо же как-то завлечь вас в статью)) Со своей стороны постараюсь, чтобы аннотация все же оправдывала ваши ожидания.

Вкратце о чем речь

Все это и так знают, но все же в начале напомню, как в 1С могут передаваться параметры метода. Передаваться они могут "по ссылке" и "по значению". В первом случае, мы передаем в метод то же самое значение, что и в точке вызова, а во втором - его копию.

По умолчанию в 1С аргументы передаются по ссылке, и изменение параметра внутри метода будет видно извне метода. Здесь дальнейшее понимание вопроса зависит от того, что именно вы понимаете под словом "изменение параметра". Так вот, имеется в виду повторное присваивание и ничего более. Причем, присваивание может быть неявным, например вызовом метода платформы, который возвращает что-то в выходном параметре.

Но если мы не хотим, чтобы наш параметр передавался по ссылке, то мы можем указать перед параметром ключевое слово Знач.

Процедура ПоЗначению(Знач Параметр) Параметр = 2; КонецПроцедуры Параметр = 1; ПоЗначению(Параметр); Сообщить(Параметр); // выведет 1

Все работает, как обещано - изменение (а правильнее сказать "замена") значения параметра не приводит к изменению значения вне метода.

Ну а в чем прикол-то?

Интересные моменты начинаются, когда мы начинаем передавать в качестве параметров не примитивные типы (строки, числа, даты и т.п.), а объекты. Вот тут-то и всплывают такие понятия, как "мелкая" и "глубокая" копия объекта, а также указатели (не в терминах C++, а как абстрактные дескрипторы (handles)).

При передаче объекта (например, ТаблицыЗначений) по ссылке, мы передаем само значение указателя (некий handle), который в памяти платформы "держит" объект. При передаче по значению платформа сделает копию этого указателя.

Иными словами, если, передавая объект по ссылке, в методе мы присвоим параметру значение "Массив", то в точке вызова получим массив. Повторное присваивание значения, переданного по ссылке, видно из места вызова.

Процедура ОбработатьЗначение(Параметр) Параметр = Новый Массив; КонецПроцедуры Таблица = Новый ТаблицаЗначений; ОбработатьЗначение(Таблица); Сообщить(ТипЗнч(Таблица)); // выведет Массив

Если же, мы передадим объект по значению, то в точке вызова наша ТаблицаЗначений не пропадет.

Содержимое объекта и его состояние

При передаче по значению копируется не весь объект, а только его указатель. Экземпляр объекта остается одним и тем же. Неважно, как вы передаете объект, по ссылке или по значению - очистка таблицы значений приведет к очистке именно таблицы. Эта очистка будет видна везде, т.к. объект был один-единственный и неважно, как именно он передавался в метод.

Процедура ОбработатьЗначение(Параметр) Параметр.Очистить(); КонецПроцедуры Таблица = Новый ТаблицаЗначений; Таблица.Добавить(); ОбработатьЗначение(Таблица); Сообщить(Таблица.Количество()); // выведет 0

При передаче объектов в методы платформа оперирует указателями (условными, не прямыми аналогами из C++). Если объект передается по ссылке, то ячейка памяти виртуальной машины 1С, в которой лежит данный объект, может быть перезаписана другим объектом. Если объект передается по значению, то указатель копируется и перезапись объекта не приводит к перезаписи ячейки памяти с исходным объектом.

В то же время любое изменение состояния объекта (очистка, добавление свойств и т.п.) изменяет сам объект, и вообще никак не связано с тем, как и куда объект передавался. Изменилось состояние экземпляра объекта, на него может быть куча "по-ссылок" и "по-значений", но экземпляр всегда один и тот же. Передавая объект в метод, мы не создаем копию всего объекта.

И это верно всегда, за исключением...

Клиент-серверное взаимодействие

В платформе очень прозрачно реализованы серверные вызовы. Мы просто вызываем метод, а под капотом платформа сериализует (превращает в строку) все параметры метода, передает на сервер, а потом возвращает выходные параметры обратно на клиента, где они десериализуются и живут, как будто ни на какой сервер не ездили.

Как известно, не все объекты платформы являются сериализуемыми. Именно отсюда растет ограничение, что не все объекты можно передать в серверный метод с клиента. Если передать несериализуемый объект, то платформа начнет ругаться нехорошими словами.

  • Явное объявление намерений программиста. Глядя на сигнатуру метода, можно четко сказать, какие параметры входные, а какие выходные. Такой код легче читать и сопровождать
  • Для того, чтобы изменение на сервере параметра "по ссылке" было видно в точке вызова на клиенте, п араметры, передаваемые на сервер по ссылке, платформа обязательно будет сама возвращать на клиента, чтобы обеспечить поведение, описанное в начале статьи. Если параметр не нужно возвращать, то будет перерасход трафика. Для оптимизации обмена данными параметры, значения которых нам не нужны на выходе, нужно помечать словом Знач.

Здесь примечателен второй пункт. Для оптимизации трафика платформа не будет возвращать значение параметра на клиент, если параметр помечен словом Знач. Все это замечательно, но приводит к интересному эффекту.

Как я уже говорил, при передаче объекта на сервер происходит сериализация, т.е. выполняется "глубокая" копия объекта. А при наличии слова Знач объект не поедет с сервера обратно на клиента. Складываем эти два факта и получаем следующее:

&НаСервере Процедура ПоСсылке(Параметр) Параметр.Очистить(); КонецПроцедуры &НаСервере Процедура ПоЗначению(Знач Параметр) Параметр.Очистить(); КонецПроцедуры &НаКлиенте Процедура ПоЗначениюКлиент(Знач Параметр) Параметр.Очистить(); КонецПроцедуры &НаКлиенте Процедура ПроверитьЗнач() Список1= Новый СписокЗначений; Список1.Добавить("привет"); Список2 = Список1.Скопировать(); Список3 = Список1.Скопировать(); // объект копируется полностью, // передается на сервер, потом возвращается. // очистка списка видна в точке вызова ПоСсылке(Список1); // объект копируется полностью, // передается на сервер. Назад не возвращается. // Очистка списка НЕ ВИДНА в точке вызова ПоЗначению(Список2); // копируется только указатель объекта // очистка списка видна в точке вызова ПоЗначениюКлиент(Список3); Сообщить(Список1.Количество()); Сообщить(Список2.Количество()); Сообщить(Список3.Количество()); КонецПроцедуры

Резюме

Если вкратце, то резюмировать можно следующим образом:

  • Передача по ссылке позволяет "затереть" объект совсем другим объектом
  • Передача по значению не позволяет "затереть" объект, но изменения внутреннего состояния объекта будут видны, т.к. идет работа с одним и тем же экземпляром объекта
  • При серверном вызове работа идет с РАЗНЫМИ экземлярами объекта, т.к. выполнялось глубокое копирование. Ключевое слово Знач запретит копирование серверного экземпляра обратно в клиентский, и изменение внутреннего состояния объекта на сервере не приведет к аналогичному изменению на клиенте.

Надеюсь, что этот несложный перечень правил позволит вам легче решать споры с коллегами насчет передачи параметров "по значению" и "по ссылке"

Встроенный язык 1С:Предприятия поддерживает два способа передачи параметров в процедуры и функции: передача параметров по ссылке и передача параметров по значению.

По умолчанию, во встроенном языке 1С:Предприятия 8 передача параметров в процедуры и функции осуществляется по ссылке. Это означает, что изменение формального параметра внутри процедуры или функции будет отражаться на значении фактического параметра, переданного при вызове процедуры или функции.


Процедура Процедура1(ФормальныйПараметр1)

ФормальныйПараметр1 = 2 * 3;

КонецПроцедуры

ФактическийПараметр = 10;
Процедура1(ФактическийПараметр);

// будет выведено значение 6 - изменение формального
// параметра внутри процедуры повлияло на изменение

// вызове процедуры: по умолчанию, параметры передаются
// по ссылке!

Передача параметров по значению

При передаче параметра вызываемой процедуры или функции по значению, изменение значения формального параметра внутри процедуры или функции никак не влияет на фактический параметр, передаваемый при вызове процедуры или функции. Указание, что параметр нужно передавать по значению, осуществляется с помощью ключевого слова Знач.

Пример:


Процедура Процедура2(Знач ФормальныйПараметр1)

ФормальныйПараметр1 = 2 * 3;

КонецПроцедуры

ФактическийПараметр = 10;
Процедура2(ФактическийПараметр);

// будет выведено значение 10 - изменение формального
// параметра внутри процедуры НЕ повлияло на изменение
// значения фактического параметра, переданного при
// вызове процедуры: параметр передан по значению!
Сообщить(ФактическийПараметр);

Особенности передачи переменных различных типов данных по значению

Передача переменных различных типов данных по значению имеет свои особенности. Они заключаются в том, что при работе с методами и свойствами контекста формальных параметров может изменяться состояние фактического параметра, передаваемого при вызове процедуры или функции.

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры ОбработатьТаблицу() создается новый экземпляр таблицы значений, в который добавляется три строки. Это никак не влияет на состояние таблицы значений Тз, переданной в качестве фактического параметра при вызове процедуры ОбработатьТаблицу():


Процедура ОбработатьТаблицу(Знач ТаблЗнач)


ТаблЗнач = Новый ТаблицаЗначений;

// Добавим в таблицу значений две колонки
ТаблЗнач.Колонки.Добавить("Колонка1");
ТаблЗнач.Колонки.Добавить("Колонка2");


Для п = 1 По 3 Цикл
НовСтрока = ТаблЗнач.Добавить();
НовСтрока.Колонка1 = "Колонка";
НовСтрока.Колонка2 = п;
КонецЦикла;

КонецПроцедуры

// Создадим новую таблицу значений
Тз = Новый ТаблицаЗначений;



// Добавим несколько строк в таблицу значений
Для п = 1 По 10 Цикл
НовСтрока = Тз.Добавить();

НовСтрока.Колонка3 = п;
КонецЦикла;

// будет выведено значение 10


ОбработатьТаблицу(Тз);

// будет выведено значение 10: внутри процедуры ОбработатьТаблицу
// в формальный параметр сохранили новую таблицу значений

Рассмотрим в качестве примера ситуацию, когда параметром процедуры, передаваемым по значению, является таблица значений. Внутри вызываемой процедуры СвернутьТаблицу() таблица значений, переданная в качестве параметра при вызове процедуры, сворачивается:


// Указано, что передача параметра ТаблЗнач осуществляется по значению
Процедура СвернутьТаблицу(Знач ТаблЗнач)

// Свернем таблицу значений по колонкам Колонка1 и Колонка3
ТаблЗнач.Свернуть("Колонка1", "Колонка3");

КонецПроцедуры

// Создадим новую таблицу значений
Тз = Новый ТаблицаЗначений;

// Добавим в таблицу значений три колонки
Тз.Колонки.Добавить("Колонка1");
Тз.Колонки.Добавить("Колонка2");
Тз.Колонки.Добавить("Колонка3");

// Добавим несколько строк в таблицу значений
Для п = 1 По 10 Цикл
НовСтрока = Тз.Добавить();
НовСтрока.Колонка1 = "Колонка1";
НовСтрока.Колонка2 = "Колонка2";
НовСтрока.Колонка3 = п;
КонецЦикла;

// будет выведено значение 10
Сообщить("Число элементов в ТЗ до сворачивания: " + Тз.Количество());

// Вызовем процедуру, передав фактический параметр Тз по значению
СвернутьТаблицу(Тз);

// Таблица значений теперь свернута: будет выведено значение 1
Сообщить("Число элементов в ТЗ после сворачивания: " + Тз.Количество());

Таким образом, передача фактического параметра по значению в данном случае не привела к созданию копии таблицы значений. При работе со свойствами и методами таблицы значений мы работаем со свойствами и методами той таблицы значений, которая использовалась при вызове процедуры СвернутьТаблицу().

Разница для всех типов при передаче параметра процедуры или функции по ссылке или по значению проявляется в присвоении фактическому параметру процедуры или функции нового значения. Вызов свойств и методов контекста фактического параметра, если таковые имеются, влияет на формальный параметр независимо от того, передается ли он по ссылке или по значению.

Эта статья продолжает цикл статей «Первые шаги в разработке на 1С». В ней будут рассмотрены следующие вопросы:

  • Что такое процедуры и функции и когда их нужно использовать?
  • В чем отличие процедуры от функции?
  • Что такое параметр процедуры (функции) и как его передать?
  • В каком случае передавать параметр по ссылке, а в каком по значению?
  • Как быстро посмотреть список процедур текущего модуля?

Применимость

Материал полностью актуален для платформы «1С:Предприятие 8» редакций 8.2. и 8.3.

Процедуры и функции

В отдельные процедуры и функции можно выносить общие алгоритмы. Одинаковый программный код из разных модулей (какой-то общий алгоритм) разумно выносить в процедуру или функцию какого-нибудь модуля и обращаться к ней.

При этом мы избавляемся от дублирования кода, заменив его вызовом процедуры (функции). Если возникает потребность внести изменения в алгоритм, то эти изменения будет достаточно внести в одном месте.

Кроме того, процедуры и функции повышают читаемость программного кода. Гораздо проще просмотреть, что выполняет данный код, особенно, если вызовы процедур имеют осмысленные названия.

В итоге облегчается сопровождение прикладного решения.

Следует отметить, что начинающие разработчики иногда для названия процедуры или функции пытаются использовать зарезервированное слово Выполнить .

Зарезервированные слова использовать для этих целей нельзя, и, естественно, в этом случае система будет сообщать об ошибке.

Функция, в отличии от процедуры, может иметь возвращаемое значение. В теле функции для того, чтобы вернуть значение, нужно использовать оператор Возврат и указать то значение, которое будет возвращаться.

Процедура, в отличии от функции, не может иметь возвращаемое значение. Она просто вызывается и выполняет какие-то действия.

Если функция не будет иметь ключевого слова Возврат , то она вернет несуществующее значение, т.е. значение типа данных Неопределено . Вместе с тем, ключевое слово Возврат можно использовать и в процедуре, но в этом случае возвращаемое значение не указывается, а само ключевое слово будет означать: прекратить выполнение процедуры.

Процедура или функция начинает описываться со слова Процедура (Функция). Далее следует Имя процедуры (функции). После имени обязательно указываются круглые скобки. Внутри скобок могут находиться описываемые параметры.

Данные параметры нужно будет передавать при вызове (при обращении к процедуре). После круглых скобок может стоять слово Экспорт (экспортная функция).

Потом следует тело процедуры (функции), т.е. последовательность из любого количества операторов.

В теле могут находиться вызовы других процедур и функций данного модуля или других модулей, которые доступны из текущего программного модуля. Обязательным является наличие заключительного слова КонецПроцедуры (КонецФункции ).

После описания процедуры или функции точку с запятой ставить не нужно. При этом Платформа не считает ошибкой, если точка с запятой стоит после последней процедуры (функции) в модуле.

Однако со временем эта процедура (функция) в результате действий программиста может стать не последней, и тогда будет выдаваться сообщение об ошибке. Примерный вид процедуры и функции представлен на рисунке.

Параметры, переданные в процедуру (функцию) при ее вызове, могут быть использованы при формировании возвращаемого результата функцией или при выборе используемого алгоритма в процедуре.

При описании процедуры или функции мы можем указать, что для какого-либо параметра по умолчанию должно использоваться некоторое значение. Для этого справа от параметра через знак равенства указывается требуемое значение.

В том случае, если при вызове процедуры (функции) значение параметра будет не задано, то оно примет значение, используемое по умолчанию.

Таким образом, параметры, для которых указано значение по умолчанию, являются необязательными для указания при вызове. В описании процедуры(функции) вначале следуют обязательные параметры, а потом необязательные.

Кроме этого, существует передача параметров по ссылке и по значению. Внутри процедуры (функции) параметр может анализироваться, а также может изменяться. Все данные хранятся в оперативной памяти компьютера.

Т.е. при вызове процедуры (функции) мы передавали параметр с одним значением, а после отработки вызываемой процедуры (функции) значение параметра изменилось.

В случае передачи по значению указывается, что параметр нужно передавать по значению.

В этом случае вызывается новая область памяти, отличная от предыдущей, и меняется именно она. Исходное значение параметра не меняется.

По умолчанию все параметры передаются по ссылке. Чтобы передать параметр по значению, в описании процедуры перед параметром нужно поставить ключевое слово Знач .

Следует сказать, что в некоторые процедуры-обработчики передается такой параметр, как Отказ . Значение данного параметра по умолчанию – Ложь .

Если в теле процедуры-обработчика установить данному параметру значение Истина , то процедура не отработает.

Порядок следования процедур и функций в модуле 1С:Предприятие 8 значения не имеет. Из любой процедуры (функции) модуля можно вызывать любую другую процедуру или функцию данного модуля.

Чтобы обратиться к списку процедур текущего модуля в панели конфигуратора можно нажать на кнопку в виде лупы с надписью «PROC» или использовать горячие клавиши (Ctrl+Alt+P ).

Откроется диалоговое окно, в котором описаны функции F(x) и процедуры P() . К ним возможно обращаться.

Список может быть отсортирован в алфавитном порядке (для этого устанавливается галочка «Сортировка»).

При снятой галочке процедуры и функции в списке размещены в соответствии с их следованием в модуле.

Кроме процедур и функций в списке для разных модулей будут доступны разные стандартные обработчики. При выборе обработчика двойным кликом мыши в модуле создается шаблон соответствующей процедуры (обработчика события).

Если в диалоговом окне «Процедуры и функции» выбрать процедуру и нажать на кнопку Перейти , то мы окажемся в начале выбранной процедуры (функции).

Справа от кнопки с надписью «PROC» располагается поле. В этом поле указано имя текущей процедуры (функции).

Первичное знакомство с процедурами и функциями будем считать завершенным. Однако отметим, что платформа содержит множество стандартных процедур и функций, логику которых вам не нужно писать самостоятельно. Достаточно только в случае необходимости вызвать их в нужном месте вашего программного кода. Изучением этих стандартных функций мы и займемся в нашей следующей статье :)

1. Описание процедур и функций рекомендуется выполнять в виде комментария к ним. Необходимость комментирования отдельных участков кода процедур и функций должна определяться разрабочиком исходя из сложности и нестандартности конкретного участка кода.

2. Обязательного комментирования требуют процедуры и функции входящие в программный интерфейс модулей - такие процедуры и функции предназначены для использования в других функциональных подсистемах (или в других приложениях), за которые могут отвечать другие разработчики, поэтому они должны быть хорошо документированы.

См. также: Ограничения на использование экспортных процедур и функций и Использование экспортных процедур и функций в модулях форм

4. Следует избегать комментариев, не дающих дополнительных пояснений о работе не-экспортной процедуры (функции).
Например, неправильно:

// Процедура - обработчик события "ПриОткрытии" формы // &НаКлиенте Процедура ПриОткрытии() // Процедура-обработчик команды "Рассчитать" // &НаКлиенте Процедура Рассчитать() // Процедура-обработчик события "ПриИзменении" элемента формы "РедактированиеТолькоВДиалоге" // &НаКлиенте Процедура РедактированиеТолькоВДиалогеПриИзменении(Элемент)

В этих примерах комментарии избыточны, так как из названий процедур очевидно, что это обработчики событий. А с их описанием и назначением параметров можно ознакомиться в синтакс-помощнике.

// Функция возвращает по данным документа Функция СтатьяДвиженияДенежныхСредств(ДанныеДокумента)

Этот комментарий не дает никакой дополнительной информации о функции.

5. Комментарий размещается перед объявлением процедуры (функции) и имеет следующий вид.

5.1. Секция "Описание" содержит словесное краткое описание назначения и/или принципов работы процедуры(функции). Может быть единственной секцией для процедур без параметров.

5.2. Секция "Параметры" описывает параметры процедуры (функции). Если их нет, секция пропускается. Предваряется строкой "Параметры:", затем с новой строки размещаются описания всех параметров .

5.2.1. Описание параметра начинается с новой строки, далее имя параметра, затем дефис и список типов (*), далее дефис и текстовое описание параметра.
Например:

// Параметры:

Также для каждого параметра можно задать одно или несколько дополнительных описаний типов параметра. Каждое дополнительное описание начинается с новой строки, затем обязательный дефис, далее список типов параметра(*), далее дефис и текстовое описание.
Например:

// Параметры: // Реквизиты - Строка - имена реквизитов, перечисленные через запятую. // Например, "Код, Наименование, Родитель". // - Структура, ФиксированнаяСтруктура - в качестве ключа передается // псевдоним поля для возвращаемой структуры с результатом, // а в качестве значения (опционально) фактическое имя поля в таблице. // Если значение не определено, то имя поля берется из ключа. // - Массив, ФиксированныйМассив – массив имен реквизитов.

5.3. Секция "Возвращаемое значение" описывает тип и содержание возвращаемого значения функции. Для процедур эта секция отсутствует. Предваряется строкой " Возвращаемое значение: ". Затем с новой строки список типов (*), далее дефис и текст.
Например:

// Возвращаемое значение : // Булево - Истина, если хотя бы одна из переданных ролей доступна текущему пользователю ,

5.4. Секция "Пример" содержит пример использования процедуры, или функции. Предваряется строкой "Пример:". Далее с новой строки пример использования.

(*) Примечание: под «списком типов» подразумеваются имена типов, разделенные запятыми. Имя типа может быть простым (в одно слово) или составным - в два слова, разделенных точкой.
Например: Строка , Структура , СправочникСсылка.Сотрудники .

При разработке на платформе 1С:Предприятие 8.3 текст комментария также выводится в контекстной подсказке процедур, функций и их параметров. Подробнее см. раздел «Контекстная подсказка при вводе текстов модулей» главы 26 «Инструменты разработки» в документации к платформе.

Пример описания функции с одним параметром:

// Определяет доступность ролей ИменаРолей текущему пользователю, // а также доступность административных прав. // // Параметры: // ИменаРолей - Строка - имена ролей, доступность которых проверяется, разделенные запятыми. // // Возвращаемое значение: // Булево - Истина, если хотя бы одна из переданных ролей доступна текущему пользователю, // либо у него есть административные права. // // Пример: // Если РолиДоступны("ИспользованиеРассылокОтчетов,ОтправкаПоПочте") Тогда... // Функция РолиДоступны(ИменаРолей) Экспорт

Пример описания процедуры без параметров:

// В обработчике события ПередЗаписью документа выполняется; // - очистка табличной части услуги, в случае если указан договор с комиссионером; // - проверка заполнения реквизита ЕдиницаИзмеренияМест табл. части Товары; // - синхронизация с "подчиненным" счетом-фактурой; // - заполнение склада и заказа покупателя в табличных частях Товары и ВозвратнаяТара; // - удаление неиспользуемых строк табличной части "Серийные номера"; // - заполнение переменной модуля объекта УдалятьДвижение. // Процедура ПередЗаписью() КонецПроцедуры

6. Если требуется прокомментировать процедуру или функцию, которая используется с директивой компиляции, то вначале следует размещать комментарий, а затем -
директиву компиляции. Например:

// Процедура - обработчик события " ПриСозданииНаСервере " формы. // Обрабатывает параметры формы и заполняет реквизиты формы значениями. // А также выполняет следующие действия: // ... // &НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Такой стиль размещения комментария позволяет в первую очередь обращать внимание на определение функции и директиву компиляции, а потом - на комментарий, который может занимать достаточно большое количество строк.

7. Код процедур и функций должен отделяться друг от друга в тексте модуля пустыми строками.

Автоупорядочивание комментариев к процедурам или функциям с директивами компиляции

Для автоматического упорядочивания комментариев к процедурам или функциям с директивами компиляции можно воспользоваться приложенной обработкой ФорматированиеДирективКомпиляции.epf . Для этого необходимо:

  1. Выгрузить модули конфигурации (команда меню Конфигурация -> Выгрузить файлы конфигурации...)
  2. Открыть обработку в режиме 1С:Предприятие и указать каталог, в который были выгружены модули - далее нажать кнопку "Форматировать"
  3. Загрузить модули в конфигурацию (команда меню Конфигурация -> Загрузить файлы конфигурации...)

Нас находят: пример оглашения и описания процедуры без параметров , параметры процедуры ПередЗаписью() , процдура для использованияконкретной роли 1с, Как поммотреть где используется процедура в 1с, Какие наименования функций или процедур нужно исправить?, разбираться и читать в коде 1с процедура и функция, 1с 77 описание функций, прокомментировать код процедуры материалы количество при изменении, процедуры и функции в 1с, 1с документы процедуры и функции