Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2017.08.13;
Скачать: [xml.tar.bz2];

Вниз

Как вы относитесь к использованию меток в Delphi?   Найти похожие ветки 

 
Германн ©   (2016-05-25 02:10) [40]


> Kerk ©   (25.05.16 02:01) [37]
>
>
> > Юрий Зотов ©   (25.05.16 01:58) [35]
> >
> > > Возле метки пишем краткий коммент - и проблема исчезла.
>
> >
> > Еще лучше - дать метке осмысленное имя.
>
> Ну это еще куда ни шло :)
>
> Но все равно я против goto

А мы тебе его и не навязываем. :)


 
Юрий Зотов ©   (2016-05-25 02:21) [41]

> Goto и метки - это не прикладной функционал.

Еще какой прикладной, если с умом комментировать! Вот пример - описание алгоритма склейки диапазонов дат на псевдокоде:

1. Отсортировать список диапазонов
2. result = false
3. i = -1
4. i++ // берем очередной диапазон из списка
5. Если i >= (size - 1), то выход
6. Цикл по j от (i + 1) до (size - 1) включительно {
     если i-й диапазон склеился c j-м, то {
        i-й диапазон заменить на склеенный
 j-й диапазон удалить
 i = - 1
 result = true
     }
    goto 4 // переходим к следующему диапазону в списке
  }
// -----------------------
И вызывать этот код в цикле, пока не вернет false.  


 
Eraser ©   (2016-05-25 02:30) [42]

полностью согласен с [29].


> Юрий Зотов ©   (25.05.16 02:09) [39]


> Дело привычки, всего лишь.

так и есть. лично я последний раз использовал метки году эдак в 2000-ом на паскале, будучи школьником. в Делфи уже не использовал, видимо мода на них начала проходить.
программеры более старшего поколения наверняка использовали метки в enterprise и массово, тогда это не считалось зазорным и проблем не вызывало, поэтому и выработался автоматизм.

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


 
Внук ©   (2016-05-25 09:33) [43]


> лично я последний раз использовал метки году эдак в 2000-
> ом на паскале

Вот-вот. Я не помню, когда последний раз использовал goto, при том что нет у меня установки его избегать любой ценой, совершенно. Просто не нужен. Что как бы намекает нам...


 
Юрий Зотов ©   (2016-05-25 10:25) [44]

> Внук ©   (25.05.16 09:33) [43]
> Что как бы намекает нам...


... на то, что можно обойтись и без этого оператора. Это давно известно.

Однако же, можно обойтись и одним циклом while. Но почему-то никто не говорит, что циклы for и repeat - лишние.

Операции OR и XOR - тоже лишние. Достаточно иметь NOT и AND, все остальное можно построить на них. Правда, код будет чудовищным, но работать он будет верно.

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

Оказывается, много чего лишнего понакручено. А зачем?

Для удобства. Для читабельности. Для снижения вероятности ошибок.

И с goto - та же история. Вот напиши такой кусок без goto - и сравним удобство и читабельность.

start:
<что-то делаем 1>
while <условие 1> do
begin
 while <условие 2> do
 begin
   <что-то делаем 2>
   if <условие 3> then
     goto start;
   <что-то делаем 3>
 end;
 <что-то делаем 4>
end;
<что-то делаем 5>


 
Внук ©   (2016-05-25 10:43) [45]


> Юрий Зотов ©   (25.05.16 10:25) [44]

Нет, намекает это нам на то, что потребность в этом операторе очень низка, и это точно не случай топикстартера.

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


 
Владислав ©   (2016-05-25 11:09) [46]

repeat
 <что-то делаем 1>
 while <условие 1> do
 begin
   while <условие 2> do
   begin
     <что-то делаем 2>
     ПовторитьСначала := <условие 3>
     if ПовторитьСначала then
       Break;
     <что-то делаем 3>
   end;
   if ПовторитьСначала then
     Break;
   <что-то делаем 4>
 end;
until not ПовторитьСначала;
<что-то делаем 5>


 
Владислав ©   (2016-05-25 11:09) [47]

Упс...

repeat
 <что-то делаем 1>
 while <условие 1> do
 begin
   while <условие 2> do
   begin
     <что-то делаем 2>
     ПовторитьСначала := <условие 3>
     if ПовторитьСначала then
       Break;
     <что-то делаем 3>
   end;
   if ПовторитьСначала then
     Break;
   <что-то делаем 4>
 end;
until not ПовторитьСначала;
<что-то делаем 5>


 
KilkennyCat ©   (2016-05-25 11:36) [48]

Получается, что единственный аргумент - читабельность хуже.

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


 
virex(home) ©   (2016-05-25 11:48) [49]

крылья...хвосты...
лишь бы код читаемый был и комментов побольше, что-бы через год вспомнить о чем речь

даже если считаете что исходники вам больше не понадобятся


 
Юрий Зотов ©   (2016-05-25 12:00) [50]

> Владислав ©   (25.05.16 11:09) [47]

А теперь сравним.

1. Читабельность - примерно одинаковая (хотя на мой взгляд вариант с goto для понимания проще, но пусть будет одинаково).

2. Длина кода - 14 и 18 строк.

3. Лишняя переменная ПовторитьСначала.

4. Лишние 2 проверки этой переменной.

То есть, преимуществ никаких, а недостатки есть. И ради чего? Только чтобы не писать goto?


 
Внук ©   (2016-05-25 12:27) [51]


> Юрий Зотов ©   (25.05.16 12:00) [50]

А почему пункты 2-4 отнесены к недостаткам и почему там употреблено слово "лишний"? Не потому ли, что OR и XOR, goto, String и т.д. тоже лишние? :)


 
Владислав ©   (2016-05-25 12:55) [52]

> Юрий Зотов ©   (25.05.16 12:00) [50]

Все это субъективное.

1. Без goto читабельность лучше, хотя бы потому, что с goto нужно держать в уме, что тело внешнего цикла может не выполниться полностью, а явного указания этого в коде внешнего цикла нет. Кроме этого, в варианте с goto есть неявный цикл, который с ходу таковым не воспринимается. В варианте без goto этот цикл явный.

2. Длина на 4 строки больше. Если это будет 31 и 35, разница уже не кажется такой большой, а вот для варианта с goto длина уже может быть довольно большая.

3. Эта переменная как раз самодокументирует внешний цикл.

4. Их процессор выполняет, а он быстрый.

В итоге сплошные преимущества без goto. А ради чего? Только для того, чтобы уменьшить длину на 4 строки? 8-О

На мой взгляд - это все не аргументы.
Вот если бы было сказано, что процедура с goto выполняется быстрее на столько-то, что увеличивает скорость работы на столько-то, а это критично, поэтому используется вариант с goto, вот это объективный аргумент, который я бы принял, и слова бы не сказал, потому что фобий по этому поводу у меня нет.


 
Kerk ©   (2016-05-25 13:00) [53]


> Владислав ©   (25.05.16 12:55) [52]
>
> Без goto читабельность лучше, хотя бы потому, что с goto
> нужно держать в уме, что тело внешнего цикла может не выполниться
> полностью, а явного указания этого в коде внешнего цикла
> нет. Кроме этого, в варианте с goto есть неявный цикл, который
> с ходу таковым не воспринимается. В варианте без goto этот
> цикл явный.

Вот это главный аргумент. Само наличие goto мгновенно усложняет код.


 
DVM ©   (2016-05-25 13:45) [54]


> Владислав ©   (25.05.16 11:09) [47]

GOTO убрали, BREAK два раза вставили. BREAK или EXIT те же GOTO по сути.
Будем уж последовательны, прервем цикл без BREAK.


 
Внук ©   (2016-05-25 13:57) [55]


> DVM ©   (25.05.16 13:45) [54]

Попробуйте обойтись в программе без инструкций семейства JMP, тогда эта претензия будет понятна.
Речь же о структуре кода. Операторы Break, Continue и функция Exit предсказуемы. Оператор Goto мало того, что способен выкинуть в произвольное место, еще и заставляет анализировать возможные побочные эффекты. Мне это не нравится.


 
Владислав ©   (2016-05-25 14:00) [56]

> DVM ©   (25.05.16 13:45) [54]

"BREAK или EXIT те же GOTO по сути."

Те же, да не те же. Возьмем некий абстрактный цикл с break, и такой же с goto. Можно не смотря на код ответить, какой код начнет выполняться после break? Да. А какой код начнет выполняться после goto? Нет. Сначала надо на код посмотреть.
И еще один момент. Break нам говорит о том, что цикл завершается. Exit говорит о том, что процедура завершается. Goto не говорит ни о чем, нужно разбираться в коде.


 
NoUser ©   (2016-05-25 14:58) [57]

http://www.google.com/search?q=Stiv_Makkonnell_-_Sovershenny_kod_2-e_izdanie.pdf

IV, 17. "Нестандартные управляющие структуры" (404|382)

P.S.
> Kerk ©   (25.05.16 13:00) [53]
а FixInsight по этому поводу что-то ищет/предупреждает ?


 
DVM ©   (2016-05-25 15:10) [58]


> Внук ©   (25.05.16 13:57) [55]


> Владислав ©   (25.05.16 14:00) [56]

Вы оба правы, BREAK, разумеется, выкинет нас из цикла в предсказуемое место за циклом, но, с другой стороны, GOTO тоже нас перекидывает не в рандомное. Конечно, конец цикла найти проще, чем метку в объемной процедуре, но, с другой стороны, огромные процедуры сами по себе признак плохого кода и без меток.

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


 
Внук ©   (2016-05-25 15:14) [59]

Все еще хуже. Насколько я помню, сейчас Юрий программирует в Java, в которой нет goto вообще (я ничего не путаю?). Так что это просто зависть к нам, оставшимся верным Delphi :)


 
Kerk ©   (2016-05-25 15:28) [60]


> а FixInsight по этому поводу что-то ищет/предупреждает ?

Нет. Надо будет добавить :)


 
DVM ©   (2016-05-25 15:33) [61]


> Kerk ©   (25.05.16 15:28) [60]


> Нет. Надо будет добавить :)

Использование GOTO не ошибка, не о чем тут предупреждать.
Не, ну можно, конечно, в предупреждении выводить "Ошибка #100500 Не совпадение с мнением Kerka-а насчет идеального кода" :)


 
Юрий Зотов ©   (2016-05-25 15:34) [62]

> Внук ©   (25.05.16 15:14) [59]

В Джаве есть:
break метка
continue метка

По сути - те же goto. Причем сначала их не было, а в какой-то версии - появились. Значит, необходимость в них все же есть - и это тоже аргумент.


 
Kerk ©   (2016-05-25 15:48) [63]


> DVM ©   (25.05.16 15:33) [61]
>
> > Kerk ©   (25.05.16 15:28) [60]
>
> > Нет. Надо будет добавить :)
>
> Использование GOTO не ошибка, не о чем тут предупреждать.
>
> Не, ну можно, конечно, в предупреждении выводить "Ошибка
> #100500 Не совпадение с мнением Kerka-а насчет идеального
> кода" :)

Так в этом же вся суть проекта! :)

Если серьезно, то кроме потенциальных ошибок там еще есть реагирование на стилевые особенности кода. Слишком длинные методы, слишком большое количество переменных, вложенные with и т.п. Goto хороший кандидат туда же. Тем более что любую проверку можно легко отключить.


 
Внук ©   (2016-05-25 15:58) [64]


> Юрий Зотов ©   (25.05.16 15:34) [62]

Так я про это написал в [45]. Операторы прерывания циклов с метками убили смысл goto совсем. Там, где они поддерживаются, конечно.


 
Eraser ©   (2016-05-25 17:17) [65]

вот такой код
procedure TForm1.Button1Click(Sender: TObject);
label lbl;
begin
 try
   goto lbl;
 finally
   ShowMessage("1");
 end;
 lbl:
 ShowMessage("2");
end;

у меня не компилируется, выдает ошибку
[dcc32 Error] Unit1.pas(36): E2127 "GOTO lbl" leads into or out of TRY statement, or out of FOR-IN statement whose enumerator has destructor

в вот такой

procedure TForm1.Button2Click(Sender: TObject);
var
 I: Integer;
begin
 for I := 0 to 10 do
 begin
   try
     if I > 5 then
       Break;
   finally
     OutputDebugString(PChar(I.ToString));
   end;
 end;
end;

компилируется.

так что label не так близок к break, continue и exit, как кажется.


 
Германн ©   (2016-05-26 01:27) [66]

Попробую суммировать все высказывания со своей колокольни. Goto сам по себе ничем не вреден. Он всего лишь инструмент, которым надо уметь пользоваться. Если им пользуется тот кто умеет, инструмент может иногда помочь сделать код более удобным/более читаемым/более понятным. Если им пользуются троешники, то там "как повезёт".


 
Kerk ©   (2016-05-26 02:06) [67]


> Германн ©   (26.05.16 01:27) [66]

Ну вот к чему это переливание из пустого в порожнее? Ты реально думаешь, что кто-то из присутствующих в этой ветке, в том числе те, кто против использования goto, не умеют им пользоваться? В плоскости умеет/не умеет тут вопрос даже не стоит.


 
Inovet ©   (2016-05-26 03:49) [68]

А почему никто не сказал, что на метку можно перейти из множества мест? Или в Делфи это не так?


 
Dimka Maslov ©   (2016-05-26 09:31) [69]


> Операторы break и continue ведь тоже частные случаи goto


А если бы при помощи операторов break и continue догадались дать возможность прервать несколько циклов за раз, им бы цены не было. Но ведь мир далеко не идеален и для прерывания нескольких циклов нормальной простой и понятной альтернативы goto нет. Исключения, замыкания, анонимные методы - не панацея, лучше и проще они не сделают никогда. А вот написать Break(2) - как было бы классно. В моём собственном скриптовом языке такое реализовано и метки действительно стали вообще не нужны.


 
Владислав ©   (2016-05-26 09:39) [70]

Dimka Maslov ©   (26.05.16 09:31) [69]

"А вот написать Break(2) - как было бы классно"

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


 
Dimka Maslov ©   (2016-05-26 11:03) [71]


> Владислав ©   (26.05.16 09:39) [70]


С чего это вдруг "возможностей меньше, а побочные явления те же". Возможности те же, но "читабельность" сохраняется. Метки и переходы не нужны. Как не нужна лишняя писанина. В таких языках, как C++, где break ещё из switch выводит - вообще была бы песня.

Вот такая конструкция у меня прекрасно работает без побочных эффектов

#func check(i, j)
 #if (i == 2) & (j == 2) then break(2)
#endfunc

#for i = 1 to 5
 #for j = 1 to 5
   #check(i, j)
 #next
#next

Давайте попробуем повторить такое же в Delphi... Даже goto не поможет И не надо говорить, что у break для нескольких циклов возможностей меньше.


 
Владислав ©   (2016-05-26 11:23) [72]

> Dimka Maslov ©   (26.05.16 11:03) [71]

А так будет работать?

#func check3(i, j)
 #if (i == 2) & (j == 2) then break(2)
#endfunc

#func check2(i, j)
 #check3(i, j)
#endfunc

#func check1(i, j)
 #check2(i, j)
#endfunc

#func check(i, j)
 #check1(i, j)
#endfunc

#for i = 1 to 5
 #for j = 1 to 5
   #check(i, j)
 #next
#next


 
Юрий Зотов ©   (2016-05-26 11:35) [73]

> Давайте попробуем повторить такое же в Delphi...
> Даже goto не поможет

Еще как поможет.

function Check(i, j: integer): boolean;
begin
  result := (i = 2) and (j = 2)
end;

for i := 1 to 5 do
 for j := 1 to 5 do
   if Check(i, j) then
     goto lbl;
lbl: ...


 
Юрий Зотов ©   (2016-05-26 11:45) [74]

> Dimka Maslov ©   (26.05.16 11:03) [71]

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


 
Юрий Зотов ©   (2016-05-26 11:50) [75]

Вот так и удобнее, и универсально, и безопасно:

#func check(i, j, n)
#if (i == 2) & (j == 2) then break(n)
#endfunc

#for i = 1 to 5
#for j = 1 to 5
  #check(i, j, 2)
#next
#next


 
Dimka Maslov ©   (2016-05-26 11:52) [76]


> А так будет работать?


Будет. На уровне интерпретатора это реализовано через исключение.


> Юрий Зотов ©   (26.05.16 11:45) [74]


Это просто пример. Обычно, всё же до таких вещей не надо доходить. Достаточно и просто прерывать не сколько циклов. А ещё бывает удобно вложенный цикл прервать, а у внешнего сразу начать новую итерацию, т.е. иметь возможность ещё continue(n) использовать. Вот тут уже никакие goto точно не помогут.


> и опасно.


Ружья куда опаснее. Но ими ведь пользуются после специальной для этого подготовки.


 
Юрий Зотов ©   (2016-05-26 12:00) [77]

> Dimka Maslov ©   (26.05.16 11:52) [76]

> Вот тут уже никакие goto точно не помогут.


goto поможет всегда.

> Ружья куда опаснее. Но ими ведь пользуются после
> специальной для этого подготовки.


И время от времени успешно стреляют себе в ногу.


 
Владислав ©   (2016-05-26 12:09) [78]

> Юрий Зотов ©   (26.05.16 11:50) [75]

Ну вот не вижу я ничего удобного и безопасного в этом.

Написали код:

#func check(i, j, n)
 #if (i == 2) & (j == 2) then break(n)
#endfunc

#for i = 1 to 5
 #for j = 1 to 5
   #check(i, j, 2)
 #next
#next

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

#for i = 1 to 5
 #for j = 1 to 5
   #check(i, j, 2)
 #next
#next

Изменяем вот так:

#for i = 1 to 5
 #for j = 1 to 5
   #check(i, j, 2)
 #next
 #Какой-то новый код
#next

Запускаем, и... Работает неправильно. Почему???

И с goto точно такая же ситуация.

Чтобы на такие грабли не наступить, достаточно не использовать такие операторы.

Ясен пень, это все мое скромное мнение. :)


 
Dimka Maslov ©   (2016-05-26 12:16) [79]


> goto поможет всегда.


for i := 1 to 10 do begin
 L:
 for j := 1 to 10 do begin
    for k := 1 to 10 do begin
      if k = 5 then goto L;
    end;
   DoSomething1;
 end;
 DoSomething2;
end;

Изменится ли значение i после перехода на метку L, если внутри цикла k мы захотим прервать и его, и цикл j и чтобы DoSomethingи не выполнялись? Тут вообще полный этот как его произойдёт. А будь тут всего лишь Continue(3) - всё прекрасно будет.


> И время от времени успешно стреляют себе в ногу.


А это от недостатка подготовки. Мощными, но опасными предметами могут пользоваться только профессионалы, а не кто ни попадя


 
Kerk ©   (2016-05-26 12:33) [80]

Лучше не писать программу так, чтобы поддерживать ее могли только  профессионалы с опасными мощными предметами :)
Такое мое скромное мнение.



Страницы: 1 2 3 4 вся ветка

Форум: "Прочее";
Текущий архив: 2017.08.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.64 MB
Время: 0.005 c
2-1427136740
NovichoK2
2015-03-23 21:52
2017.08.13
освобождение строковых параметров класса


15-1463757911
SergP
2016-05-20 18:25
2017.08.13
Как вы относитесь к использованию меток в Delphi?


2-1426513998
dmk
2015-03-16 16:53
2017.08.13
Возможно ли имея имя класса в переменной обратится


2-1422502870
Drowsy
2015-01-29 06:41
2017.08.13
Вычисляемые поля ДатаСета.


15-1464384606
Юрий
2016-05-28 00:30
2017.08.13
С днем рождения ! 28 мая 2016 суббота





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский