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

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С)

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

См. также

Пример проведения Code-review #1

Рефакторинг и качество кода Программист Платформа 1С v8.3 Абонемент ($m)

В статье расскажу и покажу процесс проведения Code-review на примере обработки с GitHub.

1 стартмани

04.06.2024    3511    mrXoxot    46    

32

Результаты ревью кода 1500+ решений каталога Инфостарт: наиболее частые ошибки разработчиков в коде

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

Поделюсь своим опытом аудита кода авторских продуктов с Infostart.ru как одним из элементов применения DevOps-практик внутри Инфостарт. Будет настоящий код, боевые скриншоты, внутренние мемы от команды ИТ-лаборатории Инфостарт и прочее мясо – все, что любят разработчики.

10.04.2024    9942    artbear    84    

101

Ниндзя-код

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

Предлагаю вашему вниманию советы мастеров древности. Программисты прошлого использовали их, чтобы заострить разум тех, кто после них будет поддерживать код. Гуру разработки при найме старательно ищут их применение в тестовых заданиях. Новички иногда используют их ещё лучше, чем матёрые ниндзя. Прочитайте их и решите, кто вы: ниндзя, новичок или, может быть, гуру? (Адаптация статьи "Ниндзя-код" из учебника JavaScript)

01.04.2024    2863    DrAku1a    15    

35

Практическое программирование: когда скорость важнее совершенства

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

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

01.04.2024    815    Prepod2003    6    

2

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

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

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

18.03.2024    1545    ZhokhovM    5    

4

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

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

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

18.03.2024    3224    ZhokhovM    4    

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

Крутку в любом случае по коду делаешь.
Мне для того и дано колесико мышки, чтобы крутку можно было делать удобно, это не аргумент.
PLAstic; user1464234; +2 Ответить
2. ivanov660 4372 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 4372 16.11.20 14:25 Сейчас в теме
(4) Это правило хорошего тона. Однако, мне встречались реализации на 1С, где довольно часто использовался этот оператор. И выглядел этот кода довольно уныло.
С другой стороны, если взять Ассемблер (или машинные коды), то там как раз в большинстве своем использования операторов перехода и особенно "перейти" (jmp)
6. alexey.kutya 303 16.11.20 14:33 Сейчас в теме
Ни разу не было желания использовать Перейти (GOTO).
Все остальные использую, если это эффективно.
IgorS; Stylo; +2 Ответить
19. teller 23.11.20 06:55 Сейчас в теме
(6) при программировании конечных автоматов логичнее использовать goto,
если вы чего-то не ... то это не значит что это не ... .
Статья из серии "Дейкстру и Вирта не читал , но имею собственное мнение "
7. FesenkoA 58 16.11.20 14:33 Сейчас в теме
Пфффф, у меня по арифметике было "5"!

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

	ш=ш+1;

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

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

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

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

КонецЦикла


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