Операторы перехода в программном коде: использовать или нет?

16.11.20

Разработка - Рефакторинг и качество кода

Рассмотрим ситуации использования операторов перехода Перейти (GoTo), Возврат (Return), Прервать (Break), Продолжить (Continue). Как вы считаете - это дурной тон, нормальная практика или зависит от ситуации?

Этот вопрос появился у нас в процессе обсуждения некоторых технических вопросов и проведения code-review, но мне интересно обсудить его и на данном тематическом ресурсе. Скажу сразу - мнение в нашей команде разделилось.

Со времен «старой школы» существует мнение, что структурное программирование — это хорошо, а любое отступление от него — это плохо. Однако, общение с профессиональными программистами показывает, что использование операторов break, continue, return на практике применяется довольно часто, потому что это удобно и в большинстве случаев делает программу более понятной. Если взять код типовой конфигурации от компании 1С и немного покопаться, то встречаются эти оба подхода вперемешку (предположу, что писали разные люди в разные временные промежутки).

И действительно Дональд Кнут в свое время писал:

«… Настоящая цель программиста состоит в том, чтобы формулировать наши программы таким образом, чтобы их было легко понимать.» 

Давайте рассмотрим примеры использования и не использования этих операторов и сравним.
 

1. Оператор Перейти (GoTo).

 

Это совсем дурной тон и его использовать не будем). Однако интересно было бы услышать ваши мысли, возможно в сообществе еще есть «староверцы».

2. Оператор Возврат (Return).

 

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

 
 Используем оператор возврата 

 

Функция ПолучитьСреднийЧек(Партнер) Экспорт 
	
	// уходим если ошибка, обрабатывать не стоит
	Если НЕ ЗначениеЗаполнено(Партнер) Тогда
		Возврат новый Структура(Неопределено,"Данные пустые");
	КонецЕсли;
	
	Запрос = новый Запрос;
	Запрос.Текст="ВЫБРАТЬ
	|	СРЕДНЕЕ(РасчетыСКлиентами.Сумма) КАК СреднийЧек
	|ИЗ
	|	РегистрНакопления.РасчетыСКлиентами КАК РасчетыСКлиентами
	|ГДЕ
	|	РасчетыСКлиентами.АналитикаУчетаПоПартнерам.Партнер = &Партнер
	|	И РасчетыСКлиентами.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
	|	И РасчетыСКлиентами.Сумма <> 0
	|
	|ИМЕЮЩИЕ
	|	НЕ СРЕДНЕЕ(РасчетыСКлиентами.Сумма) ЕСТЬ NULL";
	
	Запрос.УстановитьПараметр("Партнер",Партнер);
	Результат = Запрос.Выполнить();
	
	Если Результат.Пустой() Тогда
		Возврат новый Структура(Неопределено,"Результат пустой");
	КонецЕсли;
	
	// На самом деле тут может быть многоа кода
	// очень много кода
	// более размера одного экрана
	// ...
	// ...
	
	Выборка.Следующий();
	Возврат новый Структура(Выборка.СреднийЧек,"Все успешно");
	
КонецФункции

 

 

 
Не используем оператор возврата 

 

Функция ПолучитьСреднийЧек(Данные) Экспорт
	
	СтруктураВозврата = Неопределено;
	
	// уходим если ошибка, обрабатывать не стоит
	Если ЗначениеЗаполнено(Партнер) Тогда
		
		Запрос = новый Запрос;
		Запрос.Текст="ВЫБРАТЬ
		|	СРЕДНЕЕ(РасчетыСКлиентами.Сумма) КАК СреднийЧек
		|ИЗ
		|	РегистрНакопления.РасчетыСКлиентами КАК РасчетыСКлиентами
		|ГДЕ
		|	РасчетыСКлиентами.АналитикаУчетаПоПартнерам.Партнер = &Партнер
		|	И РасчетыСКлиентами.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
		|	И РасчетыСКлиентами.Сумма <> 0
		|
		|ИМЕЮЩИЕ
		|	НЕ СРЕДНЕЕ(РасчетыСКлиентами.Сумма) ЕСТЬ NULL";
		Запрос.УстановитьПараметр("Партнер",Партнер);
		Результат = Запрос.Выполнить();
		
		Если НЕ Результат.Пустой() Тогда
			
			// На самом деле тут может быть многоа кода
			// очень много кода
			// более размера одного экрана
			// ...
			// ...
			
			Выборка.Следующий();
			СтруктураВозврата = новый Структура(Выборка.СреднийЧек,"Все успешно");
		Иначе
			СтруктураВозврата = новый Структура(Неопределено,"Результат пустой");
		КонецЕсли;
	Иначе
		СтруктураВозврата = новый Структура(Неопределено,"Данные пустые");
	КонецЕсли;
	
	Возврат СтруктураВозврата;
	
КонецФункции

 

 

 

Какие выводы мы можем сделать из двух вышеуказанных примеров?

  • Во втором примере мы теряем локальность — при достаточно длинном тексте процедуры нужно еще посмотреть, не выполняются ли какие-то действия после условного оператора. Да и не совсем понятно, зачем добавлять лишний уровень вложенности. Теперь представьте, что вы проводите анализ кода (code-review), то вам придется время от времени скролить вверх и вниз всю эту простыню кода, чтобы вернуться к оператору условий.
  • Дополнительно во втором примере нам пришлось вводить переменную, в которой хранится результат выполненных операций. Вспоминаем о «Бритве Оккама» и понятии «Не плоди лишних сущностей».
  • Как вы уже догадались, то проблему большого куска кода в обоих случаях мы можем подвергнуть (в принципе должны) рефакторингу и заключить в отдельную функцию.


     
  • В первом случае мы свами можем попасть на никогда не выполняемый код. Обычно про такое должен выдавать предупреждение компилятор.
     
     Пример кода, который никогда не выполняется
    Функция ЭтоТипБулево(Значение) Экспорт
    	
    	Если ТипЗнч(Значение)=Тип("Булево") Тогда
    		Возврат Истина;
    	Иначе
    		Возврат Ложь;
    	КонецЕсли;
    	
    	// сюда мы никогда доходить не будем
    	Сообщить("А сердечник можно делать из дерева! 
    	| Все равно этот код никогда не выполнится...");
    	Возврат Неопределено;
    	
    КонецФункции
  • Удобно использовать оператор "Возврат" в начале функции при выполнении обязательных проверок на корректность входных параметров. В этом случае легко отвязывается задача проверки параметров от всего куска кода процедуры.
     
     Пример обработки выходных параметров

     

    Функция ПолучитьСреднийЧек(Партнер) Экспорт 
    	
    	// I) Проверяем входные параметры
    
    	// уходим если ошибка, обрабатывать не стоит
    	Если НЕ ЗначениеЗаполнено(Партнер) Тогда
    		Возврат новый Структура(Неопределено,"Данные пустые");
    	КонецЕсли;
    
    	// II) Выполняем основную задачу
    	// ...
    	// ...
    	// ...
    
    КонецФункции
    

     

     

3. Оператор Прервать (Break)


Один из самых востребованных операторов, если рассмотреть программирование на C++. В свое время я часто его использовал в связке с Switch и Операторах цикла (For, While). Обратите внимание, что оператор "Прервать" может использоваться и для выхода из бесконечного цикла.
Рассмотрим вариацию типового примера для подключения к клиенту тестирования механизма автоматизированного тестирования от 1С.

 
 Используем оператор прервать 

 

Подключен = Ложь;
ОписаниеОшибкиСоединения = "";
ТестовоеПриложение = Новый ТестируемоеПриложение(,НомерПорта,);

ВремяОкончанияОжидания = ТекущаяДата() + 70;  // 70 секунд ожидаем подключение
Пока Истина Цикл
	
	Попытка
		ТестовоеПриложение.УстановитьСоединение();
		Подключен = Истина;
		Прервать;
	Исключение
		ОписаниеОшибкиСоединения = ОписаниеОшибки();
	КонецПопытки;
	
	Если ТекущаяДата() >= ВремяОкончанияОжидания Тогда		
		Прервать;
	КонецЕсли;
	
КонецЦикла;

 

 

 
 Не используем оператор прервать

 

Подключен = Ложь;
ОписаниеОшибкиСоединения = "";
ТестовоеПриложение = Новый ТестируемоеПриложение(,НомерПорта,);

ВремяОкончанияОжидания = ТекущаяДата() + 70;  // 70 секунд ожидаем подключение
Пока (ТекущаяДата() <= ВремяОкончанияОжидания) И (Подключен=Ложь) Цикл
	
	Попытка
		ТестовоеПриложение.УстановитьСоединение();
		Подключен = Истина;
	Исключение
		ОписаниеОшибкиСоединения = ОписаниеОшибки();
	КонецПопытки;
	
КонецЦикла;

 

Какие отличия мы видим?

  • в первом случае мы последовательно встречаемся с условиями, так проводить анализ значительно проще на мой взгляд
  • во втором случае код внутри процедуры получился значительно меньше и сразу видно условие выхода из цикла
  • Использование "вечных" условий в операторах цикла - это дурной тон для языка 1С Предприятие. 

 

4. Оператор Продолжить (Continue)

 

Оператор "Продолжить" (continue) позволяет сразу перейти в конец тела цикла, пропуская весь код, который находится под ним. Это полезно в тех случаях, когда мы хотим завершить текущую итерацию раньше времени. 

Будьте осторожны при использовании оператора "Продолжить" с циклом "Пока" (while). Поскольку в этих циклах инкремент счетчиков выполняется непосредственно в теле цикла, то использование "Продолжить" может привести к тому, что цикл станет бесконечным!

Рассмотрим задачу - Требуется выполнить предварительную обработку таблицы данных загруженную из Excel.

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

 
 Необдуманное использование оператора продолжить

 

ш=0;

Пока ш<ТаблицаДанных.Количество()-1 Цикл
	
	стр = ТаблицаДанных[ш];
	
	// такая ошибка сделает наш цикл бесконечным
	Если ЭтоБитыеДанные(стр) Тогда
		Продолжить;
	КонецЕсли;
	
	// Обрабатываем данные во внешней процедуре
	НайтиСсылкуКонтрагентаПоНаименованию(стр);

	// Еще много кода пост обработки
	// ...
	// ...
	// ...
	// ...
	
	ш=ш+1;
	
КонецЦикла;

Процедура "НайтиСсылкуПоНаименованию" ищет ссылку контрагента в базе 1С.

Функция "ЭтоБитыеДанные" проверяет наличие "кривой" информации в полях Сумма, КонтрагентНаименование.

 

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

 
 Более правильный вариант

 

ш=0;

Для ш=0 по ш<ТаблицаДанных.Количество()-1 Цикл
	
	стр = ТаблицаДанных[ш];
	
	// такая ошибка сделает наш цикл бесконечным
	Если ЭтоБитыеДанные(стр) Тогда
		Продолжить;
	КонецЕсли;
	
	// Обрабатываем данные во внешней процедуре
	НайтиСсылкуКонтрагентаПоНаименованию(стр);

	// Еще много кода пост обработки
	// ...
	// ...
	// ...
	// ...
	
КонецЦикла;

 

 

Теперь рассмотрим вариант без использования оператора "Продолжить".

 
 Не используем оператор продолжить

 

ш=0;

Пока ш<ТаблицаДанных.Количество()-1 Цикл
	
	стр = ТаблицаДанных[ш];
	
	// такая ошибка сделает наш цикл бесконечным
	Если НЕ ЭтоБитыеДанные(стр) Тогда
	
		// Обрабатываем данные во внешней процедуре
		НайтиСсылкуКонтрагентаПоНаименованию(стр);
		// Еще много кода пост обработки
		// ...
		// ...
		// ...
		// ...
		
	КонецЕсли;
	
	ш=ш+1;
	
КонецЦикла;

 

 

Выводы:

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

 

5. Операторы прервать и продолжить

 

Многие учебники рекомендуют не использовать операторы "Прервать" (break) и "Продолжить" (continue), поскольку они приводят к произвольному перемещению точки выполнения программы по всему коду, что усложняет понимание и следование логике выполнения такого кода.

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

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

 
 Используем операторы прервать и продолжить

 

Функция ПолучимБаланс(ТаблицаДанных) Экспорт

	Баланс = 0;
	
	// 1. Обрабатываем массив данных с типами элементов: Позиция(Число) ,Выбрана (булево), Контрагент (Справочник), Сумма (число).
	// 2. Количество записей 1 000 000 элементов
	Для каждого стр из ТаблицаДанных Цикл
		
		Если НЕ стр.Выбрана Тогда
			Продолжить;
		КонецЕсли;
		
		// если битая ссылка, то нужно выдать ошибку
		Если ЭтоБитыеДанные(стр)=Истина Тогда
			Баланс=Неопределено;
			Сообщить("Позиция "+стр.Позиция+" битые данные!");
			Прервать;
		КонецЕсли;		
		
		Баланс = Баланс+стр.Сумма;		
			
	КонецЦикла;
	
	Возврат Баланс; 
КонецФункции

Функция "ЭтоБитыеДанные" проверяет наличие "кривой" информации в полях Сумма, Контрагент.

 
 Не используем операторы прервать и продолжить

 

Функция ПолучимБаланс(ТаблицаДанных) Экспорт
	
	Баланс = 0;
	БитыеДанные = Ложь;
	
	// 1. Обрабатываем массив данных с типами элементов: Позиция(Число) ,Выбрана (булево), Контрагент (Справочник), Сумма (число).
	// 2. Количество записей 1 000 000 элементов
	Для каждого стр из ТаблицаДанных Цикл
		
		Если стр.Выбрана Тогда			
			БитыеДанные = ЭтоБитыеДанные(стр);
			Если БитыеДанные =Ложь Тогда
				Баланс = Баланс+стр.Сумма;
			Иначе
				БитыеДанные =Истина;
				Баланс = Неопределено;
				Сообщить("Позиция "+стр.Позиция+" битые данные!");
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Баланс;
КонецФункции

 

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

 
 Не используем операторы прервать и продолжить вариант 2

 

Функция ПолучимБаланс(ТаблицаДанных) Экспорт
	
	Баланс = 0;
	ш=0;
	
	// 1. Обрабатываем массив данных с типами элементов: выбрана (булево), Сумма (число).
	// 2. Количество записей 1 000 000 элементов
	Пока ш<ТаблицаДанных.Количество()-1 И ЭтоБитыеДанные(ТаблицаДанных[ш])=Ложь Цикл
		
		Если ТаблицаДанных[ш].Выбрана Тогда
			Баланс = Баланс+ТаблицаДанных[ш].Сумма;
		КонецЕсли;
		
	КонецЦикла;
	
	// если ш меньше размера таблицы, значит мы не дошли до конца без ошибок
	Если ш<ТаблицаДанных.Количество()-1 Тогда
		
		Баланс = Неопределено;
		Сообщить("Позиция "+стр.Позиция+" битые данные!");
		
	КонецЕсли;
	
	Возврат Баланс;
КонецФункции

 

 

Рассмотрим результат сравнения:

  • Не желание использовать операторы переходов вынудило нас во втором случае полностью переписать код
  • Во втором случае потребовалось заводить лишние переменные
  • Во втором случае потребовалось вынести часть логики из цикла в конец функции, что увеличивает объем кода выполняющий решения поставленной задачи
  • В циклах "Для" и "Для каждого" удобно использовать оператор "Продолжить" для быстрого перехода к следующей итерации по результатам условий, если текущая строка не требует обработки.
     
     Пример перехода к следующей итерации в цикле, если не требуется обработка на текущем шаге

     

    // ...
    
    Для каждого стр из ТаблицаДанных Цикл
    		
    	Если НЕ стр.Выбрана Тогда // Переходим сразу к следующей итерации
    		Продолжить;
    	КонецЕсли;
    
        // Далее обрабатываем данные
        // ...
    
    КонецЦикла;
    
    // ...

     

     

Заключение

 

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

  • Операторы "Продолжить" и "Прервать" удобно использовать в циклах "Для" и "Для каждого"
  • Если речь идет про оператор цикла "Пока", то тут лучше стараться не использовать "Продолжить", т.к. в некоторых комбинациях возможно создание бесконечного цикла.
  • Дурной тон в операторах циклов использовать "вечные" условия по типу " Пока Истина Цикл".
  • При использовании оператора "Возврат" надо следить, чтобы не оставалось недостижимого кода.
  • Также возможны случаи написания недостижимого кода с операторами "Продолжить" и "Прервать".
  • Оператор "Возврат" удобно использовать в начале функций при выполнении проверок на консистентность (корректность) входных параметров.
  • Оператор "Перейти" запрещено использовать.
  • Если придерживаться структурного подхода, то следует себя ограничивать в создании вложенности (или "матрешек") с условиями "Если Тогда", так как это затрудняет понимание кода и увеличивает критерий цикломатичности.
  • В процессе разработки (кодирования) всегда выполняем рефакторинг кода и выносим большие блоки в отдельные функции.
  • Используйте в процессе работы анализ качества кода (код-ревью) (По следам код-ревью, Как завести у себя в команде код-ревью. Отвечаем на вопросы)
  • Используйте тестирование и автоматизированное тестирование (Автоматизация тестированияПример создания сценарного UI теста для платформы 1С)

качество кода операторы перехода

См. также

Когда понадобился новый оператор

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда понадобился новый оператор, но его нет в синтакс-помощнике, что делать?

18.03.2024    1162    ZhokhovM    2    

4

Когда разработчик платформы не добавил проверку препроцессоров

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Когда разработчик платформы решил пойти на кухню за кофе, а проверку препроцессоров не добавил, и вот тут-то и началось: "Что, опять все сломалось? Ну и кофе же я забыл сделать!".😅

18.03.2024    2695    ZhokhovM    4    

9

Реструктуризация - бесконечная история

Рефакторинг и качество кода Платформа 1С v8.3 Бесплатно (free)

При разработке программ требуемый функционал ставят на первое место, но есть еще и архитектура программы. На горизонте 5-10 лет она становится важнее функционала, который должен работать при масштабировании и росте данных. Реструктуризация 5 терабайтной базы 1С 8.2 в формат 1С 8.3, складывает весь пазл архитектурных просчетов, которые сделали ради функционала. Как это исправить? - для разработки правильной архитектуры, нужно всего лишь сместить фокус с функционала и подумать о «вечном».

29.09.2023    1910    1CUnlimited    15    

22

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 2

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

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

27.09.2023    6972    Lemmonbri    136    

36

Чистый код. Мой взгляд на жизнь в макаронных джунглях. Часть 1

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

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

19.09.2023    4353    Lemmonbri    16    

31

5 подходов при доработке конфигурации 1С, чтобы в будущем не было мучительно больно её обновлять

Архитектура Рефакторинг и качество кода Обновление 1С Платформа 1С v8.3 Бесплатно (free)

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

10.08.2023    9592    0    1c-izhtc    37    

21

Задача на ошибки и неоптимальности при проведении приходной накладной

Рефакторинг и качество кода Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Задачу эту дают на собеседованиях, видимо, те франчи, которые не в состоянии оценить человека по резюме и в ходе беседы. По идее задачи, подобные этой, должны давать начинающим студентам. Но дают всем подряд. Итак: мои 5 копеек. Критика приветствуется.

11.07.2023    2216    magic1s    32    

11
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. Steelvan 302 16.11.20 11:04 Сейчас в теме
Во втором примере всегда делаю ЗначениеВозврата в начале функции.
Плюсом это сразу дает понимание, что возвращается из функции.
Плюсом сразу определяешь ЗначениеВозврата по умолчанию, которое всегда вернется, если даже одно условие с кодом изменения не сработает.

Крутку в любом случае по коду делаешь.
Мне для того и дано колесико мышки, чтобы крутку можно было делать удобно, это не аргумент.
PLAstic; user1464234; +2 Ответить
2. ivanov660 4332 16.11.20 11:12 Сейчас в теме
(1) На счет скролла кода:
1. С психологической точки зрения при постоянном переключении туда-сюда больше устаешь и соответственно теряется эффективность.
2. По некоторым рекомендациям проведения код ревью: чем меньше код и более компактный, тем проще проводить эту процедуру.
3. С точки зрения эффективности анализа кода, гораздо проще понять в чем суть:
//..
ВыполнитьДействие1();
ВыполнитьДействие2();
ВыполнитьДействие3();
//..
Процедура ВыполнитьДействие1()
// какая-то обработка
Для каждого ...
КонецПроцедуры
Показать

чем
//..
Для каждого .....
//Условия
// ...
Для каждого ...
//
Для каждого ...
//
Показать


т.е. чем компактней код тем лучше, но не всегда такого можно добиться.
3. PLAstic 295 16.11.20 12:50 Сейчас в теме
(2) Сначала отвечу на это сообщение. Тут нужен здравый смысл. Если процедура длинная, но при выделении её частей в отдельные процедуры приходится передавать целую портянку параметров, то логично, что нужно оставить эту процедуру в покое - на протяжении всего её контекста задействовано множество взаимосвязанных параметров и следование правилу "не более N строк" в данном случае наоборот, затруднит понимание алгоритма.
По поводу же статьи, тут тоже всё логично. Я 15 лет назад первый раз сходил на несколько курсов Арутюнова Сергея из 1УЦ (он и сейчас их ведёт), который помог понять логику разработчиков и увидеть смысл. Конечно, лишние уровни вложенности затрудняют чтение, поэтому и встречаются проверки с возвратом в начале типовых процедур/функций. Полностью согласен с (1), тоже оформляю структуру возврата в начале и использую во всех возвратах. Формат ответа любой функции/процедуры всегда д.б. един. Следует избегать случаев, когда при каких-то условиях мы возвращаем Неопределено, а когда-то структуру. Или один раз у нас структура пустая, а в другой - с набором реквизитов.
4. bulpi 215 16.11.20 14:15 Сейчас в теме
"Оператор "Перейти" запрещено использовать."
Если бы все было именно так, то этого оператора не было в синтаксисе.
Dementor; 1v7; starik-2005; Vlad_2008; Perfolenta; brr; +6 1 Ответить
5. ivanov660 4332 16.11.20 14:25 Сейчас в теме
(4) Это правило хорошего тона. Однако, мне встречались реализации на 1С, где довольно часто использовался этот оператор. И выглядел этот кода довольно уныло.
С другой стороны, если взять Ассемблер (или машинные коды), то там как раз в большинстве своем использования операторов перехода и особенно "перейти" (jmp)
6. alexey.kutya 301 16.11.20 14:33 Сейчас в теме
Ни разу не было желания использовать Перейти (GOTO).
Все остальные использую, если это эффективно.
IgorS; Stylo; +2 Ответить
19. teller 23.11.20 06:55 Сейчас в теме
(6) при программировании конечных автоматов логичнее использовать goto,
если вы чего-то не ... то это не значит что это не ... .
Статья из серии "Дейкстру и Вирта не читал , но имею собственное мнение "
7. FesenkoA 57 16.11.20 14:33 Сейчас в теме
Пфффф, у меня по арифметике было "5"!

ш=-1;
Пока ш<ТаблицаДанных.Количество()-1 Цикл

	ш=ш+1;

	стр = ТаблицаДанных[ш];
	
	Если ЭтоБитыеДанные(стр) Тогда
		Продолжить;
	КонецЕсли;

	НайтиСсылкуКонтрагентаПоНаименованию(стр);
КонецЦикла;
Показать
mussolene; +1 Ответить
8. potoyalo 17.11.20 07:17 Сейчас в теме
Выводы гениальны, конечно.. <ОператорName> удобно использовать там, где он уместен.
Не понял, откуда у вас получился вывод, что Оператор "Перейти" использовать запрещено?
Perfolenta; brr; +2 Ответить
9. mussolene 19 17.11.20 07:26 Сейчас в теме
Прочитал статью по диагонали. НЕ увидел аргументированного вывода по переходу. Он здесь в принципе не раскрыт. Его можно и нужно использовать в условиях когда например тебе нужно выполнить код через Выполнить() и не хочешь чтобы выполнялась громоздкая конструкция в случае когда какая то проверка не выполнилась. По поводу примеров написанных выше скажу только одно. второй пример супер не оптимальный и можно сократить как миниму несколько возвратов, так же разность возвращаемых данных это просто жесть. Когда попробуешь потом возврат обработать еще такую же простыню получишь
brr; Dementor; +2 1 Ответить
10. mussolene 19 17.11.20 07:33 Сейчас в теме
Функция ПолучитьСреднийЧек(Партнер) Экспорт
	
	СтруктураВозврата = Новый Структура("СреднийЧек,Ошибка",0,"");
	
	Если Не ЗначениеЗаполнено(Партнер) Тогда
		СтруктураВозврата.Ошибка = "Не заполнены данные!!!";
		Возврат СтруктураВозврата;
	КонецЕсли;

	Запрос = новый Запрос;
	Запрос.Текст="ВЫБРАТЬ
	|	СРЕДНЕЕ(РасчетыСКлиентами.Сумма) КАК СреднийЧек
	|ИЗ
	|	РегистрНакопления.РасчетыСКлиентами КАК РасчетыСКлиентами
	|ГДЕ
	|	РасчетыСКлиентами.АналитикаУчетаПоПартнерам.Партнер = &Партнер
	|	И РасчетыСКлиентами.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг
	|	И РасчетыСКлиентами.Сумма <> 0
	|
	|ИМЕЮЩИЕ
	|	НЕ СРЕДНЕЕ(РасчетыСКлиентами.Сумма) ЕСТЬ NULL";
	Запрос.УстановитьПараметр("Партнер",Партнер);
	Результат = Запрос.Выполнить();
	Выборка = Результат.Выбрать();
	
	Если Выборка.Следующий() Тогда
		ЗаполнитьЗначенияСвойств(СтруктураВозврата,Выборка);	
	Иначе
		СтруктураВозврата.Ошибка = "Данные не получены!!!";
	КонецЕсли;
	
	Возврат СтруктураВозврата;
	
КонецФункции
Показать
11. mussolene 19 17.11.20 07:48 Сейчас в теме
(9) Так же остается вопрос в инициализации переменных постоянно. Вы вкурсе что инициализация переменной это новая ячейка памяти. Представьте что у вас 1 кк пользователей запустили код в котором инициализируется несколько десятков переменных. Вам не хватит памяти нормально обрабатывать данные.

И вообще в чем проблема при использовании операторов не понимаю. Как можно все это говорить??? При определенных условия операторы условного перехода ограничивают потребление памяти и время выполнения определенного кода. Это касается не только 1С.

По поводу выводов в конце статьи. Согласен только с тем что код нужно писать оптимально по некоторым пунктам.
12. Rais96 17.11.20 07:50 Сейчас в теме
Всегда использую оператор Перейти, если нужен выход из сложного или вложенного цикла. Код чище и главное понятнее. Мнимый запрет на goto, сформирован вначале распространения структурного программирования, потом ввели break, continue, которые по сути те же goto. А методика преподавания не поменялась, потому и в промышленное программирование приходят с аксиомой что goto запрещено. Мы программируем не для красоты, а чтобы было понятнее и проще разобраться в коде, а что при этом нарушаются какие-то понятия программирования, так пусть теоретики подстраивают свои теории под практику.
Award; starik-2005; romanpl777; Drivingblind; itoptimum; brr; Perfolenta; Dementor; mussolene; +9 1 Ответить
14. Perfolenta 204 17.11.20 13:52 Сейчас в теме
(12) поддерживаю, оператор Перейти вполне полезен в некоторых ситуациях и ни чем не хуже любых других операторов...
Он был назначен виновником всех бед тогда, когда блочных операторов ещё не было и даже процедур в современном понимании еще не было... тогда использование Goto было безальтернативным и превращало код во "взрыв на макаронной фабрике"...
но те времена давным-давно прошли...
Сегодня, если в методе есть один-два оператора Перейти код не превращается в сложный для чтения и не повышает вероятность ошибок...
Если у вас стоит цель запутать код, то вы и без оператора Перейти справитесь на отлично, а если мозги на месте, то и оператор Перейти будет полезен...
starik-2005; itoptimum; +2 Ответить
15. ivanov660 4332 17.11.20 17:12 Сейчас в теме
(14) Если ВЫ действительно говорите что использование оператора Goto оправдано в текущий момент и вы его используете, то для меня это звучи ужасно.
Если про использование других операторов прервать, возврат, то нормальная практика.
16. Perfolenta 204 17.11.20 23:17 Сейчас в теме
(15) есть яды, которыми лечат... молотком не надо стучать по голове...
неужели вы пугаетесь увидев оператор Перейти, не понимаете, что происходит и вынуждены тратить лишнее время?
мне кажется, что нет...
Производительность кода он тоже не снижает, к ошибкам не приводит... в чем проблема?
Зато он удобен при выходе из нескольких вложенных циклов,
годится для перехода в конец метода для выполнения завершающих действий...
Такие случаи сами по себе редки, но в них он смотрится хорошо и удобно, так чего его не использовать? Только из-за чьих-то предубеждений (смысл которых потерялся в прошлом веке)?
Zevzm; Dementor; starik-2005; romanpl777; pm74; Award; +6 Ответить
17. nporrep 50 18.11.20 22:21 Сейчас в теме
(15) Рекомендации по ограничению (не запрету!) использования безусловного перехода (jmp) в пользу передачи управления (call/ret) стали актуальным при смещении парадигмы от "линейного" программирования к блочному, дабы не запутывать спагетти.

Но сейчас, в эпоху асинхронной многопоточности, goto используется даже в ультрасовременном golang (микросервисы-каналы-горутины-ралли и вот это вот всё), а использование приема перехода к метке особенно актуально при кодогенерации, когда исполняемый код программно создается по широкому набору условий, и неизвестен заранее...
18. makfromkz 35 19.11.20 07:31 Сейчас в теме
(12) Также поддерживаю, в Фортан4 был оператор вычисляемый Goto
Попробуйте его реализовать по методике структурного программирования, если все метки находятся в линейном алгоритме.

Я когда писал на Си программу эмуляции мультиплексного канала, тоже хотел следовать "структурности", но увидев накладные расходы "структурности", плюнул и вернулся к goto
13. mussolene 19 17.11.20 08:06 Сейчас в теме
В примерах про продолжить (4) просто гениальное использование циклов от аля ХЗ кого. Почему нельзя нормально итератором пройти и цикл не будет бесконечным

Для Каждого Стр Из ТаблицаДанных Цикл
     Если ЭтоБИтыеДанные(Стр) Тогда
           Продолжжить
     КонецЕсли;
     //Обработка вашего кода

КонецЦикла


Очень сложная конструкция я вам скажу(нет)
20. Hans 2 01.12.20 20:50 Сейчас в теме
Написал бы в примерах кода "Правильно", "Неправильно". Я так предполагаю что использование оператора Возврат посреди функции это плохо. Возврат должен быть только в начале или конце.
21. ivanov660 4332 02.12.20 12:10 Сейчас в теме
(20)
1. Там где не правильно и могут быть ошибки я отметил
2. Оба подхода можно применять. Это две "методологии": структурный (без операторов перехода) и "прогрессивный" (используем операторы перехода там где удобно).
3. Вопрос родился из-за существующих двух разных школ при разработке кода на 1С.
22. Hans 2 02.12.20 13:09 Сейчас в теме
(21) Про школы отдельную статью. Что за школы?
23. user636866_pismopriwlo 27.10.21 13:09 Сейчас в теме
Обработка конвертации данных V8Exchan83.epf написана с активным использованием оператора goto
EMelihoff; +1 Ответить
Оставьте свое сообщение