Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 13:27
Оценка: +1
Вообщем есть мнение (не только мое), что применение break и continue в циклах — не очень хорошо. Во-первых — всегда можно обойтись без них, во-вторых — применение их рушит цепочку действий и ветвлений в циклах, что очень часто приводит к ошибкам.
Был цикл, который сортировал объекты по двум листам.
for (Entity e : entities) {
   if (e.isApproved()) {
      approvedEntities.add(e);
   } else {
      pendingEntities.add(e);
   }
}

Потом сюда вносят исправление, так чтобы сортировка добавляла в список утвержденных те, которые валидны:
for (Entity e : entities) {
   if (e.isValid()) {
      approvedEntities.add(e);
      continue;
   }
   if (e.isApproved()) {
      approvedEntities.add(e);
   } else {
      pendingEntities.add(e);
   }
}

В данном примере сразу видно где ошибка, но зачастую этих проверок и сортировок бывает много и они громоздкие — поэтому вероятность именно такой ошибки очень велика.
К тому-же, в комбинации с метками они запутывают код:
loop:
while (true) {
   System.out.println("1");
   break loop;
}
System.out.println("2");

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


Кросспост из ru_java
Re: Про break и continue в циклах
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 12.10.05 14:03
Оценка: +3
Здравствуйте, aefimov, Вы писали:

A>Вообщем есть мнение (не только мое), что применение break и continue в циклах — не очень хорошо. Во-первых — всегда можно обойтись без них, во-вторых — применение их рушит цепочку действий и ветвлений в циклах, что очень часто приводит к ошибкам.


Дэйкстрой попахивает. Я против уважаемого ничего не имею, даже может наоборот, но..... Когда он жил и какое время сейчас? Я говорю о развитии языков. В то время ввиду особенностей реализаци безусловного перехода в старых языках это самое использование могло привести к большим проблемам (потеря контекста или как там еще). Что касается java, то применение break (иногда вместо goto), continue с точки зрения целостности программы совсем не опасно. Остается одна проблема — читабельности кода, которое является понятием чисто субъективным. Для кого-то удобно читать цепочки ифов, запоминать семантику временных переменных, 3-5 сложное условие выхода из цикла. Для меня лично удобнее читать небольшие по размеру методы последовательно анализируя проиходящее в них. И если в какой-то точке становится понятно что дальнейшее выполнение цикла может быть прервано — почему бы не превать его в этой точке?

A>Был цикл, который сортировал объекты по двум листам.

A>
A> поскипал 
A>

A>Потом сюда вносят исправление, так чтобы сортировка добавляла в список утвержденных те, которые валидны:
A>
A> поскипал 
A>


Ну так налицо проблема с руками у кодера. Вероятно человек просто не знал что в java можно использовать конструкцию else if.

A>В данном примере сразу видно где ошибка, но зачастую этих проверок и сортировок бывает много и они громоздкие — поэтому вероятность именно такой ошибки очень велика.


Вот и я говорю, что если методы делать не большими (в идеале 10-15 строчек) то будет абсолютно эквипенисуально, используются там continue и break или нет.

A>Вообщем, я лично не использую и не рекомендую использовать эти операторы в циклах. Хотелось бы услышать и более другие мнения по этому поводу.


Я лично рекомендую пользоваться всем, но пользоваться с умом.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[2]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 14:12
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Дэйкстрой попахивает. Я против уважаемого ничего не имею, даже может наоборот, но..... Когда он жил и какое время сейчас? Я говорю о развитии языков. В то время ввиду особенностей реализаци безусловного перехода в старых языках это самое использование могло привести к большим проблемам (потеря контекста или как там еще). Что касается java, то применение break (иногда вместо goto), continue с точки зрения целостности программы совсем не опасно. Остается одна проблема — читабельности кода, которое является понятием чисто субъективным. Для кого-то удобно читать цепочки ифов, запоминать семантику временных переменных, 3-5 сложное условие выхода из цикла. Для меня лично удобнее читать небольшие по размеру методы последовательно анализируя проиходящее в них. И если в какой-то точке становится понятно что дальнейшее выполнение цикла может быть прервано — почему бы не превать его в этой точке?

Вот в том то и дело, чтобы максимально упростить код — нужно максимально просто его представить — бинарное дерево переходов помойму самое хорошее средство простого представления. Либо то, либо другое. А с breakами и continuями появляется еще третье ветвление, потом четвертое и так далее. И если с кодом работают N человек то они N раз наступят на одни и теже грабли
Ты еще упоменул про break вместо goto. Реально в каких случаях это может использоваться? Не зря ведь запретили goto в Java...

L>Ну так налицо проблема с руками у кодера. Вероятно человек просто не знал что в java можно использовать конструкцию else if.

Дык кудаж без них — хочется просто максимально убрать возможность допустить такие вот ошибки.

L>Я лично рекомендую пользоваться всем, но пользоваться с умом.

Дипломатично
Re: Про break и continue в циклах
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 12.10.05 14:16
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Вообщем, я лично не использую и не рекомендую использовать эти операторы в циклах. Хотелось бы услышать и более другие мнения по этому поводу.

в догонку. Можете меня запинать, но в контексте использовнаия legacy фреймворка (где не доступен автобиндинг) не нашел более "праильного" решения

        final String status;
        error:
        {
            final int id;
            try {
                id = RequestUtils.getIntParameter(request, "id");
            } catch (InvalidParameterException e) {
                status = "Invalid id value";
                break error;
            }

            final String name;
            try {
                name = RequestUtils.getStringParameter(request, "name");
            } catch (InvalidParameterException e) {
                status = "Invalid name value";
                break error;
            }

            try {
                Currency.getInstance(name);
            } catch (IllegalArgumentException e) {
                status = "Unknown currency name";
                break error;
            }

            if (dao.saveRegistryValue(new RegistryValue(id, name))) {
                status =  "New Currency created successfull";
            } else {
                status = "New Currency updated successfull";
            }
        }
        return list(request, response).addObject("status", status);


я конечно понимаю, что все что в error:{ } можно вынести в отдельный метод возвращающий String, но IMHO приведенный код тоже не плохо читается и -один метод.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re: Про break и continue в циклах
От: C0s Россия  
Дата: 12.10.05 14:18
Оценка: 1 (1)
Здравствуйте, aefimov, Вы писали:

A>Вообщем есть мнение (не только мое), что применение break и continue в циклах — не очень хорошо. Во-первых — всегда можно обойтись без них, во-вторых — применение их рушит цепочку действий и ветвлений в циклах, что очень часто приводит к ошибкам.


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

то же самое касается циклов. лично я предпочитаю руководствоваться другим правилом: "в каждой строке исходного текста метода длина абзацного отступа должна быть по возможности минимальной", т.е. если возможно, я стараюсь избегать ifов, с телами длиннее одной строки (а одну строку я пишу там же, где и if). если break/continue мне в этом помогают, то я смело их использую.

но в целом, доводится мне их использовать довольно редко. можно посмотреть с другой стороны: возможно, частое появление break/continue в коде стоит считать признаком неиспользования каких-то паттернов ООП. но всерьез я как-то не задумывался никогда над этим

A>Потом сюда вносят исправление, так чтобы сортировка добавляла в список утвержденных те, которые валидны:

A>В данном примере сразу видно где ошибка, но зачастую этих проверок и сортировок бывает много и они громоздкие — поэтому вероятность именно такой ошибки очень велика.

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

я бы изначально этот код по-другому бы писал, причем одной строкой (предполагается, что approved/pendingEntities имеют одинаковый тип, например, Set или List или Collection, в противном случае потребуется явное приведение к супертипу):
for (Entity e : entities) (e.isApproved() ? approvedEntities : pendingEntities).add(e);


более того, скорее всего, критерий я бы выделил в отдельный класс:
for (Entity e : entities) (someCriteriaAlgorithm.isApproved(e) ? approvedEntities : pendingEntities).add(e);


в такой ситуации тот, кому бы потребовалось изменить критерий, исправлял бы только критерий!

т.е. с моей точки зрения этот пример к теме break/continue отношения не имеет, а имеет отношение к тому, как наглядно и правильно разделять части алгоритмов

A>К тому-же, в комбинации с метками они запутывают код:


метки я не использую, и тоже никому не рекомендую
Re[3]: Про break и continue в циклах
От: NotGonnaGetUs  
Дата: 12.10.05 14:19
Оценка:
Здравствуйте, aefimov, Вы писали:

A> Реально в каких случаях это может использоваться? Не зря ведь запретили goto в Java...


first:
for(...) {
   for(...) {
      if (...1)
       break first;
      if (...2)
       break;
      ...
   }
   ...
   ...
   ...
}


В таких ^^^ сам бог велел
Re[4]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 14:25
Оценка: +1
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>В таких ^^^ сам бог велел


Обычно внутренние циклы бъются на отдельные методы. И это тоже преабразуется к небрейковым переходам
Re[5]: Про break и continue в циклах
От: NotGonnaGetUs  
Дата: 12.10.05 14:40
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте, NotGonnaGetUs, Вы писали:


NGG>>В таких ^^^ сам бог велел


A>Обычно внутренние циклы бъются на отдельные методы. И это тоже преабразуется к небрейковым переходам


ну если повезло и внутри вложенного for нет 5 перменных, которых которые могут изменить своё значение, то да — можно вытащить метод, добавить флаговую переменную или доп условие выхода в верхний for — и break не понадобиться.

но жизнь-то разные сюрпризы преподносит





int a=...;
int b=...;
int c=...;
m1:
for(int i=0; i<100; i++) {
   int d = 0;
   for(int j=0; j<100; j++) {
      if ((a+i) % (b+j) = c) {
         a = 3*a;
         b = 4*i;
         c = 2+j; 
      }
      if (b*c % a == 0) {
          break m1;
      }
      b++;
      d = (a + b)  % c; 
      if (a*b % с == 0) {
          
          break;
      }
   }
   if (d = 0) sout("yyy"); 
}


Как насчёт поупражняться в рефакторинге такого кода?
Re[2]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 14:41
Оценка:
Здравствуйте, C0s, Вы писали:

C0s>а еще бывают люди, которые считают, что return должен быть только в одном месте метода, лучше — в его последней строке, оправдывая это тем, что сложно разбираться в методе, который может возвращать результаты из разных своих частей. они для меня как лишнее доказательство, что все хорошо в меру, т.к. я неоднократно видел, чего стоит "таскать за собой" возвращаемое значение, пропуская оставшиеся этапы обработки, которые уже не нужно выполнять.


Ну есть такое, и это кстати тоже может приводить к ошибкам, однако там компилятор не даст скомпилить код в котором промахнуться с блоком и вставят его после return.

C0s>то же самое касается циклов. лично я предпочитаю руководствоваться другим правилом: "в каждой строке исходного текста метода длина абзацного отступа должна быть по возможности минимальной", т.е. если возможно, я стараюсь избегать ifов, с телами длиннее одной строки (а одну строку я пишу там же, где и if). если break/continue мне в этом помогают, то я смело их использую.


Тут я с вами не соглашусь, потому что простота написания кода (компактность) — это совсем не то, что написание простого кода (понятность).
А ifы без скобок я вообще ненавижу Потому что было уже:
if (lalala)
   try {
     // skip 
   } catch (Exception e) {
     // skip
   }

И когда в запарке закоментарили тело try, чтобы небыло там чегото, закомитили. Потом вяснили что не компилится — потому что try пустой и не кидает Exception — закоментарили весь try-catch. В результате телом ifа стал следующий statement. Эту ошибку уже сразу не обнаружили, а когда обнаружили было совсем поздно. Поэтому теперь у меня скобки форсируются в Code Style.

C0s>но в целом, доводится мне их использовать довольно редко. можно посмотреть с другой стороны: возможно, частое появление break/continue в коде стоит считать признаком неиспользования каких-то паттернов ООП. но всерьез я как-то не задумывался никогда над этим


Да, именно. И старание не пользоваться ими, помойму сподвигает думать в нужном направлении

C0s>я вот, кстати, не понял, где ошибка. точнее, не понял, какова на самом деле была цель исправления


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

C0s>я бы изначально этот код по-другому бы писал


Нам только дай время и денег — переписали бы все что угодно. Но legacy rод — это legacy код и приходится придерживаться некоторых правил, дабы не разрушить его совсем.
Re[6]: Про break и continue в циклах
От: NotGonnaGetUs  
Дата: 12.10.05 14:43
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>Как насчёт поупражняться в рефакторинге такого кода?


'=' в условиях читать как '==' %)
Re: Про break и continue в циклах
От: vladserge Россия  
Дата: 12.10.05 14:48
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Вообщем есть мнение (не только мое), что применение break и continue в циклах — не очень хорошо. Во-первых — всегда можно обойтись без них, во-вторых — применение их рушит цепочку действий и ветвлений в циклах, что очень часто приводит к ошибкам.


Мое мнение и да и нет. Все хорошо в меру и к месту. У меня множество break и continue в циклах случаются, как правило в местах где производительность кода критична, а работа происходит над 8 — 20 переменными в плотной связке.(только ненадо предлагать их передавать упаковав их в объект — производительность критична )
А причиной тому, как правило то, что JAVA не позволяет передавать простые типы по ссылке

Согласен, что обилие меток, а так же break и continue это несколько усложняет чтение кода. Но так чтобы это приводило к сложно отлавливаемым ошибкам такого никогда не случалось.
С Уважением Сергей Чикирев
Re[2]: Про break и continue в циклах
От: C0s Россия  
Дата: 12.10.05 14:48
Оценка:
Здравствуйте, Lucker, Вы писали:

L>в догонку. Можете меня запинать, но в контексте использовнаия legacy фреймворка (где не доступен автобиндинг) не нашел более "праильного" решения

L>я конечно понимаю, что все что в error:{ } можно вынести в отдельный метод возвращающий String, но IMHO приведенный код тоже не плохо читается и -один метод.

да зачем запинывать-то ... я бы действительно сделал отдельный метод, но бросающий исключение с текстом в случае неполадок и возвращающий boolean как флаг create или update. но это не более, чем дело привычки, судя по всему. с моей точки зрения я предпочту свой вариант, но при этом признаю, что оба одинаково читабельны
Re[2]: Про break и continue в циклах
От: vladserge Россия  
Дата: 12.10.05 15:02
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Здравствуйте, aefimov, Вы писали:


A>>Вообщем, я лично не использую и не рекомендую использовать эти операторы в циклах. Хотелось бы услышать и более другие мнения по этому поводу.

L>в догонку. Можете меня запинать, но в контексте использовнаия legacy фреймворка (где не доступен автобиндинг) не нашел более "праильного" решения

Да все пучком.
При желании Спагети-код можно и безо всяких меток, break и continue наколбасить.
И наоборот именно метоки, break и continue могут сделать код ВЕСЬМА читаемым.(ваш пример)

Так что несогласен я. Руки прочь от break и continue!
С Уважением Сергей Чикирев
Re[7]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 15:25
Оценка: :)
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>>Как насчёт поупражняться в рефакторинге такого кода?

NGG>'=' в условиях читать как '==' %)

Да там и буковка c русская Ладно, вот чего получилось:
public class Test {
    private int a;
    private int b;
    private int c;

    public Test(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public int get(int i) {
        int d = 0;
        for (int j = 0; 
            j == 0 || j < 100 && a * b % c == 0; 
            d = (a + ++b) % c) {
            calc(i, j++);
        }
        return d;
    }

    private void calc(int i, int j) {
        if ((a + i) % (b + j) == c) {
            a = 3 * a;
            b = 4 * i;
            c = 2 + j;
        }
        if (b * c % a == 0) {
            throw new IllegalArgumentException("i = " + i + ", j = " + j);
        }
    }

    private static void foo(int a, int b, int c) {
        Test test = new Test(a, b, c);
        try {
            for (int i = 0; i < 100; i++) {
                if (test.get(i) == 0) {
                    System.out.println("yyy");
                }
            }
        } catch (IllegalArgumentException e) {
            // Ignore...
        }
    }
}
Re[2]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 15:32
Оценка:
Здравствуйте, vladserge, Вы писали:

V>Мое мнение и да и нет. Все хорошо в меру и к месту. У меня множество break и continue в циклах случаются, как правило в местах где производительность кода критична, а работа происходит над 8 — 20 переменными в плотной связке.(только ненадо предлагать их передавать упаковав их в объект — производительность критична )

А в чем падение производительности?
Re[2]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 15:34
Оценка:
Здравствуйте, Lucker, Вы писали:

L>в догонку. Можете меня запинать, но в контексте использовнаия legacy фреймворка (где не доступен автобиндинг) не нашел более "праильного" решения


Это провокация
Re[8]: Про break и continue в циклах
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 12.10.05 15:40
Оценка: +1 :)))
Здравствуйте, aefimov, Вы писали:

да, вам, парни, обфускаторы не нужны
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[9]: Про break и continue в циклах
От: aefimov Россия
Дата: 12.10.05 15:46
Оценка:
Здравствуйте, Lucker, Вы писали:

Мы тренированные по декомпиленному скремблерованному коду понять где же эта долбанная лицензия проверяется. И как проверяется
Re[3]: Про break и continue в циклах
От: vladserge Россия  
Дата: 12.10.05 16:11
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте, vladserge, Вы писали:


V>>Мое мнение и да и нет. Все хорошо в меру и к месту. У меня множество break и continue в циклах случаются, как правило в местах где производительность кода критична, а работа происходит над 8 — 20 переменными в плотной связке.(только ненадо предлагать их передавать упаковав их в объект — производительность критична )

A>А в чем падение производительности?

ок, представте себе статический метод который может ЧАСТО вызываться несколькими потоками в теле метода создаются 10-20 взаимосвязанных простых переменных алгоритм достаточно сложен.
Проверка показала, что время требуемое на создание объекта примерно равно(чуть меньше) скорости выполнения метода.
Но зато потом создание таких обектов приводит к более частому запуску GC.
С Уважением Сергей Чикирев
Re[8]: Про break и continue в циклах
От: vladserge Россия  
Дата: 13.10.05 02:50
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте, NotGonnaGetUs, Вы писали:


NGG>>>Как насчёт поупражняться в рефакторинге такого кода?

NGG>>'=' в условиях читать как '==' %)

A>Да там и буковка c русская Ладно, вот чего получилось:

A>
A>public class Test {
A>    private int a;
A>    private int b;
A>    private int c;

A>    public Test(int a, int b, int c) {
A>        this.a = a;
A>        this.b = b;
A>        this.c = c;
A>    }

A>    public int get(int i) {
A>        int d = 0;
A>        for (int j = 0; 
A>            j == 0 || j < 100 && a * b % c == 0; 
A>            d = (a + ++b) % c) {
A>            calc(i, j++);
A>        }
A>        return d;
A>    }

A>    private void calc(int i, int j) {
A>        if ((a + i) % (b + j) == c) {
A>            a = 3 * a;
A>            b = 4 * i;
A>            c = 2 + j;
A>        }
A>        if (b * c % a == 0) {
A>            throw new IllegalArgumentException("i = " + i + ", j = " + j);
A>        }
A>    }

A>    private static void foo(int a, int b, int c) {
A>        Test test = new Test(a, b, c);
A>        try {
A>            for (int i = 0; i < 100; i++) {
A>                if (test.get(i) == 0) {
A>                    System.out.println("yyy");
A>                }
A>            }
A>        } catch (IllegalArgumentException e) {
A>            // Ignore...
A>        }
A>    }
A>}
A>


И что, Вы серьезно полагаете, что наводненние Вашего кода вот такими классами и методами (разумное-то навзвания которым затруднительно придумать calc1, calc2, calc3, get1, get2.... ) упростит понимание кода?
С Уважением Сергей Чикирев
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.