Команда возврат в 1с
Войдите как ученик, чтобы получить доступ к материалам школы
Внутренний язык программирования 1С 8.3 для начинающих программистов: функции и процедуры в 1С часть 1
Автор уроков и преподаватель школы: Владимир Милькин
Сегодня мы приступаем к изучению того, без чего не может обойтись ни одна более менее серьезная программа - функций и процедур.
Функции и процедуры в языке 1С 8.3
Давайте я подведу вас к необходимости функций, заодно вы поймёте что это такое и почему они столь полезны для программистов.
Пусть нам требуется написать программу, которая вычисляет произведение суммы и разности двух введенных чисел. Выглядеть она будет так:
В данном случае формула вычисления результата достаточно проста, но она могла бы быть гораздо сложнее. А что если нам нужно вычислять её не один раз, а несколько? Причем в разных местах программы.
Неужели нам снова и снова придётся писать код для её вычисления:
Это никуда не годится. Нам придётся повторять один и тот же код, что приведёт к раздутости программы. И кроме того, переписывая его очередной раз мы можем допустить ошибку по невнимательности.
Вот бы придумать такое имя, которое будет связано с этой формулой и при обращении к нему мы будем обращаться ко всей этой формуле целиком. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Пусть этим именем будет ПроизведениеСуммыИРазности.
Получается теперь мы можем написать:
И всё? Нет, конечно! Ведь непонятно произведение суммы и разности каких именно чисел нужно считать. Гораздо лучше будет передать эти числа нашему имени в качестве параметров, как мы обычно делаем при вызове команды:
Это, так называемый, вызов функции. Он выглядит точно также как и вызов многих других команд компьютера, которые мы уже неоднократно делали. Только это наша собственная команда, работу которой определяем мы, а не компьютер.
Давайте, наконец, определим нашу функцию, чтобы компьютер, встретив её вызов, не растерялся, а выполнил то, что мы хотим:
Что включает в себя определение этой функции?
Прежде всего ключевое слово Функция следом за которым идёт имя, которое мы придумали сами.
Затем следуют имена параметров, заключенные в круглые скобки. Параметры - это данные, которые мы передадим в нашу функцию при её вызове. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь. Она с ними что-то сделает и возвратит результат. Каждый параметр имеет своё имя, которое мы также придумываем сами. Это имя можно использовать только внутри функции.
Дальше идёт тело. Это команды компьютеру, которые будут выполняться в тот момент, когда мы сделаем вызов нашей функции. Тело заканчивается ключевым словом КонецФункции.
Внутри функции могут выполняться абсолютно любые знакомые нам команды: условные операторы, циклы и прочее. Но хотя бы один раз внутри каждой функции должна присутствовать команда:
Где вместо Результат может быть любое выражение, которое вернётся из функции в качестве её результата.
Мы можем вызывать функцию столько раз в программе сколько нам потребуется.
Процедуры это те же самые функции, но они не возвращают результат и объявляются при помощи других ключевых слов: Процедура и КонецПроцедуры.
Но функции и процедуры не следует писать лишь бы где! Для определения наших функций мы будем использовать новый модуль. Чтобы его добавить следуйте инструкциям ниже.
1. Раскройте список "Общие" в дереве конфигурации.
2. Найдите в нём пункт "Общие модули" и нажмите на нём правой кнопкой мыши. Выберите "Добавить".
3. Добавился модуль. В правой части окна конфигуратора задайте его имя и свойства, как показано ниже.
Внимание! Пожалуйста, ещё раз убедитесь, что вы поставили галки (Клиент, Сервер, Внешнее соединение) также, как на рисунке выше.
4. Перейдите в этот модуль. Всё! Здесь можно писать наши функции и процедуры. Напишите процедуру с именем Привет, без параметров, после вызова которой компьютер просто здоровается с нами.
Обратите внимание на ключевое слово Экспорт, которое идёт следом за круглыми скобками. Его наличие обязательно, так как мы определяем функцию в одном модуле (Уроки), а использовать будем совсем в другом (модуль управляемого приложения).
5. Теперь вернитесь в модуль управляемого приложения.
6. И сделайте вызов нашей процедуры. Так как она находится в другом модуле к её имени добавляется "Уроки.".
Для процедур это необязательное ключевое слово, производящее "досрочное" завершение работы процедуры. Поэтому возврат в конце процедуры смысла не имеет. Функции же умеют возвращать значения таким образом, что функции можно использовать в выражениях. Для этого используется ключевое слово Возврат с обязательным указанием возвращаемого значения. Можно ничего не возвращать, тогда функция вернет Неопределено. Но это плохой стиль. Функции создают как раз для того, чтобы они что-то возвращали (в противном случае создают процедуру). Поэтому чаще всего в конце функции присутствует ключевое слово Возврат (естественно, могут быть и "досрочные" возвраты).
Вообще, разделение на процедуры и функции довольно формальное - для удобства. В ряде языков разделения нет - есть только функции.
(4) "Вообще, разделение на процедуры и функции довольно формальное - для удобства. В ряде языков разделения нет - есть только функции."
Вообще-то, разделение не формальное, а концептуальное. При хорошем стиле программирования функции не имеют права на побочные эффекты, а для процедуры побочный эффект - главная задача. Использование строгих функций без побочных эффектов облегчает работу компилятора и создает верифицируемый код. К СОЖАЛЕНИЮ, во многих (практически во всех) языках это различие стерто, и по сути процедура - всего лишь функция не возвращающая значение.
Процедура это Функция которая не умеет возвращать значения.
Во многих ЯП нет процедур, есть только функции, причем в некоторых количество возвращаемых значений может быть любым от 0 до сколько надо.
(11) Лишние действия по заталкиванию в структуру и извлечению.
(12) Типы возвращаемых значений и их наличие в структуре не контролируются автоматом
(13) Лишние, зато отладка одно удовольствие. А типы и в параметрах не контролируются, если мы про 1с.
(14) Для меня удовольствие когда отладка не нужна, ибо синтаксис не дает допускать глупые ошибки типа повторного использования переменных с записью значений других типов и т.д.
Количество говнокода меньше, хотя согласен что печатать больше ибо еще типы надо указывать.
Но сча интеллесенсе (подстрочные подсказки по первым буквам) есть в любых практически ide и даже умных редакторах, так то не сильно тормозит ваяние.
(15) Кроме удобства отладки четкое разделение входа и выхода (без модификации параметров) облегчает заимствование функций для других проектов. Потому что если ты знаешь что функция "чистая" - то тебе не надо думать ни о чем, кроме как о её вызове. Синус же не портит данные в базе.
(16) Прикольно что в голанге все параметры в функциях передаются по значению а не по ссылке по умолчанию.
Это отличие от 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С 8.3 для начинающих программистов: функции и процедуры в 1С часть 2
Автор уроков и преподаватель школы: Владимир Милькин
На прошлом уроке мы начали знакомство с функциями и процедурами в языке 1С 8.3. Так как это действительно важная тема посвятим ей и это занятие.
Функции в 1С 8.3 - продолжение.
Итак, мы уже уяснили, что все программы состоят из команд компьютеру.
А функции - это способ группировки этих команд точно также как, например, папки на компьютере - способ группировки для файлов.
Ещё функцию можно рассматривать как чёрный ящик, внутри которого лежат какие-то команды для компьютера. Чёрный ящик имеет имя. И чтобы заставить компьютер выполнить команды из этого ящика нам нужно указать его имя, например, так:
Как видите, вызов "чёрного ящика" сам по себе является командой. При вызове чёрного ящика - выполнятся все команды, которые находятся внутри него.
Более того один ящик может содержать в себе не только команды, но и другие ящики, точно также как папки могут быть вложенными в другие папки. Ну вы поняли аналогию.
Но чёрные ящики (функции) имеют такую особенность:
- Они могут содержать входные отверстия (одно или несколько) для того, чтобы мы в них могли что-то положить (параметры).
- И они обязательно содержат одно выходное отверстие, из которого мы сможем забрать результат работы ящика.
- Ящик-функция просто обязан вернуть нам хотя бы какой-то результат в выходное отверстие.
Пусть нам нужен ящик, в который мы будем класть два числа, а он будет возвращать их сумму.
- Придумываем имя для этого ящика - "СуммаЧисел".
- Придумываем имена для входных отверстий этого ящика (параметров). Их два (числа), поэтому пусть будет - "ЧислоА" и "ЧислоБ".
- Пишем объявление самого ящика (функции):
А вот как выглядит ящик, который принимает всего одно число и возвращает квадрат этого числа:
Вызывается он так:
Функции (ящики) могут принимать и один, и два и три и гораздо больше входных параметров. А могут и совсем не принимать.
Для примера давайте напишем функцию, которая всегда возвращает в качестве результата работы строку "Привет":
Так как функция (ящик) совсем не содержит входных параметров (отверстий), то внутри круглых скобок при вызове писать ничего не нужно:
Процедуры в языке 1С 8.3 - продолжение .
С функциями более менее должно быть понятно теперь думаю всем. А что же такое процедуры? Да те же чёрные ящики:
- И входные отверстия (параметры) у них имеются.
- И команды они в себе также могут содержать.
- И другие ящики они также в себя могут включать.
А главное отличие процедур от функций в том, что они не содержат выходного отверстия. То есть процедура не возвращает нам обратный результат.
Таким образом, если нам нужно объединить группу команд, которая что-то сделает и вернёт нам результат (например, сумму чисел), то используем функции.
А если обратного результата не будет - то процедуры. Процедуры являются как бы укороченными функциями. Более простыми. Они могут принимать входные параметры и что-то с ними делать, но они не возвращают нам обратный результат после своей работы. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
- Определим имя нашего ящика - "ОписаниеЧисла".
- Определим имя входного параметра - "ЧислоА";
- Определим описание нашего ящика:
Читайте также: