1с выйти из процедуры
Функции 1С и процедуры в 1С работают аналогично другим языкам — функция это именованная подпрограмма для вызова из других мест программного кода.
Далее подробнее про функции 1С и процедуры 1С.
Порядок объявления функций в модуле произвольный (то есть можно в тексте процедуры, расположенной в самом начале модуля использовать процедуры, текст которых будет расположен ниже в этом модуле). Аналогично переменным 1С, функции 1С могут быть экспортными.
Чтобы «выйти» из выполнения функции 1С и процедуры — используют команду «Возврат;». Функция (в отличии от процедуры) «возвращает» результат вычислений, то есть необходимо написать «Возврат ЗНАЧЕНИЕ;». Функции 1С не типизированы, значит могут возвращать значение разных типов, в зависимости от параметров или условий.
Функция отличается от процедуры возможностью вернуть результат вычислений, например:
Функция Функция1(Параметр)
Возврат Параметр * 2;
КонецФункции
Переменная1 = Функция1(10);
//Переменная1 будет равна 20
Параметры функции 1С и процедуры — это ссылки на переменные, существующие в месте вызова. «Ссылка» — значит при изменении значения параметра «внутри» функции 1С, он будет изменен и «снаружи». Чтобы такого не происходило — параметр передают со значением ПЕРЕМ. Однако это не работает со значениями-объектами (списками, таблицами, объектами базы данных), они все-равно будут переданы по ссылке.
При передаче параметра в процедуру/функцию, он передается «по ссылке». Это значит, что изменяя его внутри процедуры, Вы изменяете его значение, при доступе после окончания функции 1С. Таким образом, предыдущий пример можно написать так:
Процедура Процедура1(Параметр)
Параметр = Параметр * 2;
КонецПроцедуры
Переменная1 = 10;
Процедура1(Переменная1);
Сообщить(Переменная1);
//Результатом будет 20
Чтобы передать внутрь процедуры значение переменной, а не ее саму:
Процедура Процедура1(ЗНАЧ Параметр)
//действия..
КонецПроцедуры
При работе с объектами (справочники, документы) необходимо помнить, что внутри функции 1С/процедуры 1С над ними могут быть выполнены действия.
Если у функции 1С/процедуры 1С несколько параметров, то ненужный можно пропустить (указав запятую, если пропущен параметр в середине), при этом будет передано или Неопределено (см. ниже) или значение по-умолчанию:
Функция Функция1(Параметр1, Параметр2, Параметр3 = "Строковое значение")
//Чтото делаем
КонецФункции
//Вызов функции без некоторых параметров
//параметр2 будет равен Неопределено
//параметр3 будет равен "Строковое значение"
Функция1(10);
//Вызов функции без второго параметра
Функция1(10, , "Значение");
Как уже говорилось ранее, процедуры 1С используются в качестве обработчиков событий, возникающих при работе пользователя с формой (открытие, закрытие, нажатие кнопок и т.п.) или работе платформы (старт, завершение и т.п.). Возможные виды обработчиков формы или ее элементов можно увидеть в свойствах — щелкнув мышью на соответствующий элемент формы (и прокрутив окно свойств вниз). Виды обработчиков в модуле объекта можно увидеть с помощью выпадающего списка на панели в конфигураторе — где отображается список еще неопределенных и уже определенных событий. У разных событий различные параметры, при добавлении обработчика 1С автоматически прописывает список параметров.
В модуле формы, объекта располагаются обработчики событий. Обработчик можно добавить (назначить) следующими способами:
Рассмотрим ситуации использования операторов перехода Перейти (GoTo), Возврат (Return), Прервать (Break), Продолжить (Continue). Как вы считаете - это дурной тон, нормальная практика или зависит от ситуации?
Этот вопрос появился у нас в процессе обсуждения некоторых технических вопросов и проведения code-review, но мне интересно обсудить его и на данном тематическом ресурсе. Скажу сразу - мнение в нашей команде разделилось.
Со времен «старой школы» существует мнение, что структурное программирование — это хорошо, а любое отступление от него — это плохо. Однако, общение с профессиональными программистами показывает, что использование операторов break, continue, return на практике применяется довольно часто, потому что это удобно и в большинстве случаев делает программу более понятной. Если взять код типовой конфигурации от компании 1С и немного покопаться, то встречаются эти оба подхода вперемешку (предположу, что писали разные люди в разные временные промежутки).
И действительно Дональд Кнут в свое время писал:
«… Настоящая цель программиста состоит в том, чтобы формулировать наши программы таким образом, чтобы их было легко понимать.»
Давайте рассмотрим примеры использования и не использования этих операторов и сравним.
1. Оператор Перейти (GoTo).
Это совсем дурной тон и его использовать не будем). Однако интересно было бы услышать ваши мысли, возможно в сообществе еще есть «староверцы».
2. Оператор Возврат (Return).
Давайте рассмотрим некоторый виртуальный пример. Задача будет следующая: Требуется написать функцию получения математическое ожидание покупок клиента или средний чек.
Какие выводы мы можем сделать из двух вышеуказанных примеров?
- Во втором примере мы теряем локальность — при достаточно длинном тексте процедуры нужно еще посмотреть, не выполняются ли какие-то действия после условного оператора. Да и не совсем понятно, зачем добавлять лишний уровень вложенности. Теперь представьте, что вы проводите анализ кода (code-review), то вам придется время от времени скролить вверх и вниз всю эту простыню кода, чтобы вернуться к оператору условий.
- Дополнительно во втором примере нам пришлось вводить переменную, в которой хранится результат выполненных операций. Вспоминаем о «Бритве Оккама» и понятии «Не плоди лишних сущностей».
- Как вы уже догадались, то проблему большого куска кода в обоих случаях мы можем подвергнуть (в принципе должны) рефакторингу и заключить в отдельную функцию.
3. Оператор Прервать (Break)
Один из самых востребованных операторов, если рассмотреть программирование на C++. В свое время я часто его использовал в связке с Switch и Операторах цикла (For, While). Обратите внимание, что оператор "Прервать" может использоваться и для выхода из бесконечного цикла.
Рассмотрим вариацию типового примера для подключения к клиенту тестирования механизма автоматизированного тестирования от 1С.
Какие отличия мы видим?
- в первом случае мы последовательно встречаемся с условиями, так проводить анализ значительно проще на мой взгляд
- во втором случае код внутри процедуры получился значительно меньше и сразу видно условие выхода из цикла
- Использование "вечных" условий в операторах цикла - это дурной тон для языка 1С Предприятие.
4. Оператор Продолжить (Continue)
Оператор "Продолжить" (continue) позволяет сразу перейти в конец тела цикла, пропуская весь код, который находится под ним. Это полезно в тех случаях, когда мы хотим завершить текущую итерацию раньше времени.
Будьте осторожны при использовании оператора "Продолжить" с циклом "Пока" (while). Поскольку в этих циклах инкремент счетчиков выполняется непосредственно в теле цикла, то использование "Продолжить" может привести к тому, что цикл станет бесконечным!
Рассмотрим задачу - Требуется выполнить предварительную обработку таблицы данных загруженную из Excel.
В таблице хранится наименование контрагента и некоторые дополнительные данные (сумма и т.п.). В рамках обработки будем искать ссылку на контрагента в базе данных, если данные битые, то будем пропускать поиск.
Процедура "НайтиСсылкуПоНаименованию" ищет ссылку контрагента в базе 1С.
Функция "ЭтоБитыеДанные" проверяет наличие "кривой" информации в полях Сумма, КонтрагентНаименование.
Как видно, то в результате необдуманного выбора оператора цикла, установки счетчика и размещения условия прервать, мы уйдем в бесконечный цикл. Лучше переписать так:
Теперь рассмотрим вариант без использования оператора "Продолжить".
- В первом случае мы легко можем допустить ошибку, которая приведет к бесконечному циклу (эта ошибка будет "плавающая", т.е. не всегда будет срабатывать). Поэтому лучше выбрать другой оператор цикла.
- Большой код, рекомендуем выносить рефакторингом.
- Второй вариант выглядит более логически понятным и "завершенным".
5. Операторы прервать и продолжить
Многие учебники рекомендуют не использовать операторы "Прервать" (break) и "Продолжить" (continue), поскольку они приводят к произвольному перемещению точки выполнения программы по всему коду, что усложняет понимание и следование логике выполнения такого кода.
Тем не менее, разумное использование операторов "Продолжить" и "Прервать" может улучшить читабельность циклов в программе, уменьшив при этом количество вложенных блоков и необходимость наличия сложной логики выполнения циклов.
Функция "ЭтоБитыеДанные" проверяет наличие "кривой" информации в полях Сумма, Контрагент.
Код выше требует рефакторинга, т.к. гонять цикл впустую (вдруг битые данные будут сразу со второго элемента) - это "жесть" конечно. Иными словами для следования структурному подходу требуется изменение структуры.
Рассмотрим результат сравнения:
- Не желание использовать операторы переходов вынудило нас во втором случае полностью переписать код
- Во втором случае потребовалось заводить лишние переменные
- Во втором случае потребовалось вынести часть логики из цикла в конец функции, что увеличивает объем кода выполняющий решения поставленной задачи
- В циклах "Для" и "Для каждого" удобно использовать оператор "Продолжить" для быстрого перехода к следующей итерации по результатам условий, если текущая строка не требует обработки.
Заключение
Я считаю, что использование или не использование операторов зависит от ситуации. В некоторых случаях- это позволяет существенно упростить написание и понимание кода. Однако, в некоторых случаях небрежное или "слепое" использование операторов переходов может привести к нежелательным последствиям.
- Операторы " Продолжить " и " Прервать " удобно использовать в циклах " Для " и " Для каждого "
- Если речь идет про оператор цикла " Пока ", то тут лучше стараться не использовать " Продолжить ", т.к. в некоторых комбинациях возможно создание бесконечного цикла.
- Дурной тон в операторах циклов использовать "вечные" условия по типу " Пока Истина Цикл".
- При использовании оператора " Возврат " надо следить, чтобы не оставалось недостижимого кода.
- Также возможны случаи написания недостижимого кода с операторами " Продолжить " и " Прервать ".
- Оператор " Возврат " удобно использовать в начале функций при выполнении проверок на консистентность (корректность) входных параметров.
- Оператор " Перейти " запрещено использовать.
- Если придерживаться структурного подхода, то следует себя ограничивать в создании вложенности (или "матрешек") с условиями " Если Тогда ", так как это затрудняет понимание кода и увеличивает критерий цикломатичности.
- В процессе разработки (кодирования) всегда выполняем рефакторинг кода и выносим большие блоки в отдельные функции.
- Используйте в процессе работы анализ качества кода (код-ревью) (По следам код-ревью, Как завести у себя в команде код-ревью. Отвечаем на вопросы)
- Используйте тестирование и автоматизированное тестирование (Автоматизация тестирования, Пример создания сценарного UI теста для платформы 1С)
Специальные предложения
Во втором примере всегда делаю ЗначениеВозврата в начале функции.
Плюсом это сразу дает понимание, что возвращается из функции.
Плюсом сразу определяешь ЗначениеВозврата по умолчанию, которое всегда вернется, если даже одно условие с кодом изменения не сработает.
Крутку в любом случае по коду делаешь.
Мне для того и дано колесико мышки, чтобы крутку можно было делать удобно, это не аргумент.
(1) На счет скролла кода:
1. С психологической точки зрения при постоянном переключении туда-сюда больше устаешь и соответственно теряется эффективность.
2. По некоторым рекомендациям проведения код ревью: чем меньше код и более компактный, тем проще проводить эту процедуру.
3. С точки зрения эффективности анализа кода, гораздо проще понять в чем суть:
т.е. чем компактней код тем лучше, но не всегда такого можно добиться.
"Оператор "Перейти" запрещено использовать."
Если бы все было именно так, то этого оператора не было в синтаксисе.
(4) Это правило хорошего тона. Однако, мне встречались реализации на 1С, где довольно часто использовался этот оператор. И выглядел этот кода довольно уныло.
С другой стороны, если взять Ассемблер (или машинные коды), то там как раз в большинстве своем использования операторов перехода и особенно "перейти" (jmp)
(6) при программировании конечных автоматов логичнее использовать goto,
если вы чего-то не . то это не значит что это не . .
Статья из серии "Дейкстру и Вирта не читал , но имею собственное мнение "
Пфффф, у меня по арифметике было "5"!
Выводы гениальны, конечно.. <ОператорName>удобно использовать там, где он уместен.
Не понял, откуда у вас получился вывод, что Оператор "Перейти" использовать запрещено?ОператорName>
Прочитал статью по диагонали. НЕ увидел аргументированного вывода по переходу. Он здесь в принципе не раскрыт. Его можно и нужно использовать в условиях когда например тебе нужно выполнить код через Выполнить() и не хочешь чтобы выполнялась громоздкая конструкция в случае когда какая то проверка не выполнилась. По поводу примеров написанных выше скажу только одно. второй пример супер не оптимальный и можно сократить как миниму несколько возвратов, так же разность возвращаемых данных это просто жесть. Когда попробуешь потом возврат обработать еще такую же простыню получишь
Ключевое слово Процедура начинает секцию исходного текста, выполнение которого можно инициировать из любой точки программного модуля, просто указав Имя_процедуры со списком параметров (если параметры не передаются, то круглые скобки, тем не менее, обязательны). Если в модуле обычного приложения, модуле управляемого приложения или общем программном модуле в теле описания процедуры использовано ключевое слово Экспорт , то это означает, что данная процедура является доступной из всех других программных модулей конфигурации.
При выполнении оператора Возврат процедура заканчивается и возвращает управление в точку вызова. Если в тексте процедуры не встретился оператор Возврат , то после выполнения последнего исполняемого оператора происходит выполнение неявного оператора Возврат . Конец программной секции процедуры определяется по оператору КонецПроцедуры .
Переменные, объявленные в теле процедуры в разделе Объявления локальных переменных , являются локальными переменными данной процедуры, поэтому доступны только в этой процедуре (за исключением случая передачи их как параметров при вызове других процедур, функций или методов).
Имя_проц | Назначает имя процедуры. |
Знач | Необязательное ключевое слово, которое указывает на то, что следующий за ним параметр передается по значению, то есть изменение значения формального параметра при выполнении процедуры никак не повлияет на фактический параметр, переданный при вызове процедуры. Если это ключевое слово не указано, то параметр процедуры передается по ссылке, то есть изменение внутри процедуры значения формального параметра приведет к изменению значения соответствующего фактического параметра. |
Парам1 , . ПарамN | Необязательный список формальных параметров, разделяемых запятыми. Значения формальных параметров должны соответствовать значениям передаваемых при вызове процедуры фактических параметров. В этом списке определяются имена каждого из параметров так, как они используются в тексте процедуры. Список формальных параметров может быть пуст. |
= ДефЗнач | Необязательная установка значения параметра по умолчанию. Параметры с установленными значениями по умолчанию можно располагать в любом месте списка формальных параметров. |
Экспорт | Необязательное ключевое слово, которое указывает на то, что данная процедура является доступной из других программных модулей. |
// Объявления локальных переменных | Объявляются локальные переменные, на которые можно ссылаться только в рамках этой процедуры. |
// Операторы | Исполняемые операторы процедуры. |
Возврат | Необязательное ключевое слово, которое завершает выполнение процедуры и осуществляет возврат в точку программы, из которой было обращение к процедуре. Использование данного оператора в процедуре не обязательно. |
КонецПроцедуры | Обязательное ключевое слово, обозначающее конец исходного текста процедуры, завершение выполнения процедуры. Возврат в точку, из которой было обращение к процедуре. |
Функция
Ключевое слово Функция начинает секцию исходного текста функции, выполнение которой можно инициировать из любой точки программного модуля, просто указав Имя_функции со списком параметров (если параметры не передаются, то круглые скобки, тем не менее, обязательны). Если в модуле обычного, управляемого приложения, внешнего соединения, сеанса или общем программном модуле в теле описания функции использовано ключевое слово Экспорт , то это означает, что данная функция является доступной из всех других программных модулей конфигурации.
Функции отличаются от процедур только тем, что возвращают Возвращаемое значение . Конец программной секции функции определяется по оператору КонецФункции .
Вызов любой функции в тексте программного модуля можно записывать как вызов процедуры, то есть в языке допускается не принимать от функции возвращаемое значение .
Переменные, объявленные в теле функции в разделе Объявления локальных переменных , являются локальными переменными данной функции, поэтому доступны только в этой функции (за исключением случая передачи их как параметров при вызове других процедур, функций или методов).
Вступайте в мою группу помощник программиста.
В ней мы обсуждаем программирование в 1С.
Цикл Для
Оператор цикла Для предназначен для циклического повторения операторов, находящихся внутри конструкции Цикл – КонецЦикла .
Перед началом выполнения цикла значение Выражение 1 присваивается переменной Имя_переменной . Значение Имя_переменной автоматически увеличивается при каждом проходе цикла. Величина приращения счетчика при каждом выполнении цикла равна 1.
Цикл выполняется, пока значение переменной Имя_переменной меньше или равно значению Выражение 2 . Условие выполнения цикла всегда проверяется в начале, перед выполнением цикла.
Имя_переменной | Идентификатор переменной (счетчика цикла), значение которой автоматически увеличивается на 1 при каждом повторении цикла. Так называемый счетчик цикла. |
Выражение 1 | Числовое выражение, которое задает начальное значение, присваиваемое счетчику цикла при первом проходе цикла. |
По | Синтаксическая связка для параметра Выражение 2 . |
Выражение 2 | Максимальное значение счетчика цикла. Когда переменная Имя_переменной становится больше чем Выражение 2, выполнение оператора цикла Для прекращается. |
Цикл | Операторы, следующие за ключевым словом Цикл выполняются, пока значение переменной Имя_переменной меньше или равно значения Выражение 2 . |
// Операторы | Исполняемый оператор или последовательность таких операторов. |
Прервать | Позволяет прервать выполнение цикла в любой точке. После выполнение этого оператора управление передается оператору, следующему за ключевым словом КонецЦикла . |
Продолжить | Немедленно передает управление в начало цикла, где производится вычисление и проверка условий выполнения цикла. Операторы, следующие в теле цикла за ним, на данной итерации обхода не выполняются. |
КонецЦикла | Ключевое слово, которое завершает структуру оператора цикла. |
Цикл Для Каждого
Оператор цикла Для каждого предназначен для циклического обхода коллекций значений. При каждой итерации цикла возвращается новый элемент коллекции. Обход осуществляется до тех пор, пока не будут перебраны все элементы коллекции.
Имя_переменной_1 | Переменная, которой при каждом повторении цикла присваивается значение очередного элемента коллекции. |
Из | Синтаксическая связка для параметра Имя_переменной_2 . |
Имя_переменной_2 | Переменная или выражение, предоставляющее коллекцию. Элементы этой коллекции будут присваиваться параметру Имя_переменной_1 . |
Цикл | Операторы, следующие за ключевым словом Цикл выполняются для каждого элемента коллекции. |
// Операторы | Исполняемый оператор или последовательность таких операторов. |
Прервать | Позволяет прервать выполнение цикла в любой точке. После выполнение этого оператора управление передается оператору, следующему за ключевым словом КонецЦикла . |
Продолжить | Немедленно передает управление в начало цикла, где производится вычисление и проверка условий выполнения цикла. Операторы, следующие в теле цикла за ним, на данной итерации обхода не выполняются. |
КонецЦикла | Ключевое слово, которое завершает структуру оператора цикла. |
Цикл Пока
Оператор цикла Пока предназначен для циклического повторения операторов, находящиеся внутри конструкции Цикл – КонецЦикла . Цикл выполняется, пока логическое выражение равно Истина. Условие выполнения цикла всегда проверяется вначале, перед выполнением цикла.
Работа функций и процедур 1С аналогична прочим языкам. Функцией принято называть именную подпрограмму, посредством которой программный код вызывается из других источников.
Объявляются функции в модуле в произвольном порядке. То есть имеется возможность использования в тексте процедуры не в порядке очередности, а находящейся в конкретном модуле существенно ниже. Как и в случае с переменными 1С, доступно экспортирование функции 1С.
С помощью команды «Возврат;» осуществляется «выход» из выполняемой функции и процедуры 1С.
Функцией (и в этом заключается ее отличие от процедуры), выполняется «возврат» полученного результата вычислений, если будет написано «Возврат ЗНАЧЕНИЕ;».
Типизация функции 1С отсутствует, а потому возможно возвращение значения различных типов. Зависит это от параметров либо условий.
Возвращение функцией результата вычислений
Возврат Параметр * 2;
//Переменная1 будет равна 20
Параметры функции 1С и процедуры являются ссылками на переменные, присутствующие в месте вызова. Они подразумевают, что, если изменится параметр в «теле» функции1С, то аналогичное действие произойдет и «снаружи». Чтобы это исключить, передача параметра осуществляется со значением ПЕРЕМ.
Но когда речь идет о значениях-объектах (объекты базы данных, таблицы, списки), эта схема не работает, и их передача будет выполняться по ссылке. А это означает, что в результате изменения параметра внутри процедуры, происходит его изменение после завершения функции 1С.
Изменение параметра функции внутри процедуры
Параметр = Параметр * 2;
//Результатом будет 20
Передача в процедуру значения переменной
Процедура Процедура1(ЗНАЧ Параметр)
Работая с объектами (документами, справочниками), нельзя забывать о возможности выполнения действий внутри функции/процедуры 1С. В том случае, когда функция 1С/процедура 1С имеет несколько параметров, то ненужные могут быть пропущены (указывается запятая или пропускается номер в середине).
Действия внутри функции, процедуры
Функция Функция1(Параметр1, Параметр2, Параметр3 = “Строковое значение”)
//Вызов функции без некоторых параметров
//параметр2 будет равен Неопределено
//параметр3 будет равен “Строковое значение”
//Вызов функции без второго параметра
Выше по тексту уже говорилось, об использовании процедур 1С для обработки событий, которые возникают если пользователь работает с формой:
- нажимает кнопки;
- открывает, закрывает форму;
- прочие подобные действия.
Или платформой:
- осуществляет запуск;
- закрывает;
- прочие подобные действия.
Чтобы получить доступ к просмотру возможных видов обработчиков или элементов формы, достаточно перейти в свойства. Для этого достаточно выполнить клик клавишей мыши, наведя курсор на нужный элемент формы, прокручивая вниз окно свойств.
На панели конфигуратора имеется всплывающий список с видами обработчиков в модуле объекта. В нем отображены все события, как уже определенных, как и неопределенных.
Разные события имеют различные характеристики, а потому, когда добавляется обработчик 1С, происходит автоматическое переписывание списка параметров.
Для размещения обработчиков событий используется модуль формы объекта. Для добавления (назначения) обработчика можно использовать несколько соответствующих способов.
Читайте также: