1. PHP / Говнокод #12990

    +161

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    $useDummy = true;
            do {
                if (!file_exists($filename)){ break; }
                require_once $filename;            
                if (!class_exists($className)){ break; }                        
                $useDummy = false;
            } while(false);

    Новый оператор ветвления do ... while

    Запостил: dimkich, 13 Мая 2013

    Комментарии (81) RSS

    • Не вижу ГК. Нормальная идиома для выхода из блока, не являющегося циклом.
      Ответить
      • $useDummy = true;
        if (file_exists($filename)) {
            require_once $filename;
            if (class_exists($className))
                $useDummy = false;
        }
        Зачем тут эта, кхм, идиома? Имхо лучше уж функцию и return'ы, если уж хочется быстрого выхода, и таких веточек много.
        Ответить
        • Конкретно в данном случае - да, не нужна.

          Я про общий случай.

          Хотя, конечно, без неё теоретически можно всегда обойтись. Ценой лесенки отступов.
          Ответить
          • > Я про общий случай.
            В общем случае она тоже не нужна. В 80% случаев лесенка больше 3 уровней заставляет задуматься о функциях (ну по крайней мере меня).

            P.S. Ну не только лесенкой, но и ретурнами можно.
            Ответить
            • > но и ретурнами можно.
              где-то я читал, что правильней иметь только одну точку возврата
              Ответить
              • >где-то я читал, что правильней иметь только одну точку возврата
                это нужно для языков, которые ниасисли RAII
                Ответить
              • > где-то я читал, что правильней иметь только одну точку возврата
                А я где-то читал, что goto не нужно юзать...

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

                P.S. Безусловно, во всех этих советах есть доля истины - они страхуют новичка от слишком частого использования goto, return и прочих мощных синтаксических конструкций, которые при неправильном использовании превратят код в лапшу. Но надо понимать, что это не закон, а всего лишь подсказка...
                Ответить
                • честно говоря, я вообще пишу нечитаемый код - инлайню, например... и тоже клал болт на негоуту и одновозврат и прочие рекомендации
                  Ответить
                  • > инлайню, например...
                    Преждевременная оптимизация? Или инлайн тут преследует какие-то более высокие цели?
                    Ответить
                    • просто не люблю таких инструкций:
                      var a=smth();
                      do(a);
                      вскгда руки чешутся слелать из этого
                      do(smth());
                      и наоборот, из
                      func1(f(1));
                      func2(f(1));
                      всегда делаю
                      var a=f(1);
                      func1(a);
                      func2(a);
                      если, конечно, не требуется именно двух вызовов.

                      а еще люблю паттерн fluent interface (что Кузя называет "программированием на стрелочках"), и "упрощенные аксессры" вида prop() и prop(val) вместо каноничных getProp() и setProp(val).... еще вспомню свои грехи - расскажу.
                      Ответить
                      • > вскгда руки чешутся слелать из этого
                        do(smth());
                        Ну а почему нет? Если там, конечно, не получается километровая строка.

                        > prop() и prop(val) вместо каноничных getProp() и setProp(val)
                        В бусте, кстати, местами такие юзают.

                        P.S. Под "инлайню" я обычно подразумеваю - копипащу тело функции целиком в точку вызова.
                        Ответить
          • В общем случае удобнее применить goto.
            Но да, для мозга, изъеденного червями, это очень сложно - понять, когда религия неготоизма мешает целесообразности.
            Ответить
            • > изъеденного червями
              изъебанного паттернами и принесенного на алтарь кодорелигиозных божков
              Ответить
            • Иногда это приводит к лютейшим макаронам.
              Ответить
              • А оператор while иногда приводит к 5-кратно вложенному циклу.
                Ответить
                • Это был совсем не осуждающий комментарий, между прочим. Ключевое слово тут - "иногда" и не относится к этому случаю.
                  Ответить
        • Перед return'ом может понадобиться что-нибудь сделать, не выходя из функции. Не копипастить же это «что-нибудь».
          Ответить
          • Да вот что-то у меня не было на практике таких случаев, когда это что-то не зависит от того, какая из веточек обломалась.

            Обычно или это что-то вообще не нужно, и можно не парясь напихать ретурнов.

            Или это что-то стоит после каждой веточки, в духе
            if (blabla) {
              if (foo) {
                if (bar) {
                  ...
                }
                close(foo);
              }
              close(blabla);
            }
            и тогда или лесенка, или кресто-RAII, или вынос кишков в осмысленную функцию..
            Ответить
        • >Имхо лучше уж функцию и return'ы
          А continue? Его-то ретурном не заменишь.
          Особенно continue на новую итерацию одного из вышележащих циклов.
          Ответить
          • А тут уже по ситуации смотреть надо. К тому же идиома do { ... } while(false) один хрен не позволит адекватно юзать этот самый continue.
            Ответить
            • >А тут уже по ситуации смотреть надо
              http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java#String.lastIndexOf%28char%5B %5D%2Cint%2Cint%2Cchar%5B%5D%2Cint%2Cint %2Cint%29
              Ну вот, практически эталонный пример.
              startSearchForLastChar:
                      while (true) {
                          while (i >= min && source[i] != strLastChar)  i--;
                          if (i < min) return -1;
                          int j = i - 1;
                          int start = j - (targetCount - 1);
                          int k = strLastIndex - 1;
                          while (j > start) {
                              if (source[j--] != target[k--]) {
                                  i--;
                                  continue startSearchForLastChar;
                              }
                          }
                          return start - sourceOffset + 1;
                      }
              Ответить
              • А здесь питонское for ... else было бы как раз кстати ;) Оно как раз для таких случаев.
                Ответить
                • Так а куда его здесь лепить?
                  Ответить
                  • Как-то так (на гипотетической жабе, в которой есть эта питонофича):
                    while (true) {
                        while (i >= min && source[i] != strLastChar)
                            i--;
                        if (i < min) return -1;
                        int j = i - 1;
                        int start = j - (targetCount - 1);
                        int k = strLastIndex - 1;
                        while (j > start) {
                            if (source[j--] != target[k--]) {
                                i--;
                                break;
                            }
                        } else {
                            return start - sourceOffset + 1;
                        }
                    }
                    Ответить
                  • Ну и заодно по второму примеру:
                    int indexOfAnyButt(String str, char[] searchChars) {
                        if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) 
                            return -1;
                        for (int i = 0; i < str.length(); i++) {
                            char ch = str.charAt(i);
                            for (int j = 0; j < searchChars.length; j++) {
                                if (searchChars[j] == ch)
                                    break;
                            } else {
                                return i;
                            }
                        }
                        return -1;
                    }
                    Ответить
                    • Ну да. Теоретически Тарас прав в том что continue не нужен и его можно заменить на break низлежащего цикла. Но только в случае, если после этого цикла ничего не стоит.

                      Или же то что стоит за циклом завёрнуто в такую хитрую конструкцию как for-else, тем самым оно не сработает от бряка.

                      В принципе каждый кодер выкручивается по-своему, вот в бейсике/фортане есть exit do/for/while или continue. Если замиксовать разные циклы, то можно, опять-таки обойтись без goto (в 95% тройной вложенности достаточно).
                      В руби там вообще экзотика retry всякие.

                      Только сишкобляди и поцкалики ебутся с goto.
                      Ответить
                      • > Только сишкобляди и поцкалики ебутся с goto.

                        А все настоящие пацаны уже давно используют COME FROM
                        Ответить
                        • В наше время гото никому не нужен. Только мкроконтролеробоги продолжают ебатся с ними.
                          Ответить
            • Блин. Не успел отредактировать. Менее громоздкий образец
              Apache StringUtils
              int indexOfAnyBut(String str, char[] searchChars) {
              	if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) 
              		return -1;
              	outer : for (int i = 0; i < str.length(); i++) {
              		char ch = str.charAt(i);
              		for (int j = 0; j < searchChars.length; j++)
              			if (searchChars[j] == ch)
              				continue outer;
              		return i;
              	}
              	return -1;
              }
              Ответить
              • Поюзать Set вместо массива. Тогда внутренний цикл будет не нужен.
                Ответить
                • Ну кстати свой простой хеш-мап, скорее даже фильтр блума на 256 эл-тов для поиска нескольких чаров - неплохая идея.
                  Уже давно хочу запилить свой велик и проверить насколько обгонит стандартный метод в лоб.
                  Ответить
              • Ну а вообще, если подумать - строчки
                for (int j = 0; j < searchChars.length; j++)
                    if (searchChars[j] == ch)
                        continue outer;
                return i;
                это же
                if (searchChars.indexOf(ch) != -1)
                    return i;
                Или это ради оптимизации заинлайнено?
                Ответить
                • P.S. Ой, сорри, у массива же нет indexOf. Ну тогда какой-нибудь статик хелпер типа existsInArray. Ведь всяко же получится вполне реюзабельная функция, которая пригодилась бы в 100500 мест.
                  Ответить
                  • В каких-то либах такое говно есть (думаю в 8-й и стандартную запилят). В том же апаче должен быть indexOf - довольно распространённый метод.
                    Проблема жабы тут в том что надо сделать 10 методов
                    1 на Object и на все примитивные типы. В том числе и char.

                    Яркий пример - класс java.util.Arrays.
                    Только его средствами indexOF получается слишком тупым:
                    Arrays.asList(array).indexOf(val);
                    Arrays.binarySearch(Arrays.sort(array), val);
                    Ответить
                    • Ну вот да, этот момент после крестов меня всегда шокирует. В крестах я спокойно делаю векторы и т.п. из любой херни, лишь бы этот тип не совсем извращенный был. А в жабе либо дикий оверхед от всяких Boolean'ов, либо изволь пилить отдельную структуру копипастой.
                      Ответить
                      • > этот момент после крестов меня всегда шокирует.
                        Да выбешивал раньше.
                        Особенно попытки соотвествия типов и их обёрток.
                        Ну сделайте вы хотя бы для унификации:
                        тип <-> Тип //полезно для рефлексии
                        Нет, блядь int vs Integer. char vs Character. Итд.
                        Ответить
                        • Колебались между крестами и паскалем ;)

                          boolean вон удлинили... а int и char остались как есть.
                          Ответить
                          • >boolean вон удлинили
                            Сцуки. А я так люблю писать bool.
                            Ответить
                • >Или это ради оптимизации заинлайнено?
                  Полагаю да. Не вся жаба серверная, и не вся умеет инлайнить сама.
                  Ответить
          • Кстати, я тоже религиозен, я в таких случаях делаю флаги с говорящими именами, а вовсе не метки
            Ответить
            • > я тоже религиозен
              Бугага. Просто признай что в Аде нету ни обычного continue, ни continue на конкретный цикл.
              Ответить
              • Ну просто оно не нужно.
                Ответить
                • Лол, само собой не нужно. Так все обычно и говорят, когда чего-то нету.
                  Ответить
      • Хотел написать, что говно, потому что while(false), но пришлось признать, что конструкция имеет право на жизнь.

        Если ифов будет не два, а десяток, то при классической схеме появятся многократно вложенные фигурные скобки, а здесь хватит и одной пары скобок в do { ... } while. Программирование с goto, но без goto. Можно писать спагетти-код, не используя ни одной метки.
        Ответить
        • Лучше уж goto. Из двух говн выбирают меньшее...
          Ответить
        • >Если ифов будет не два, а десяток, то при классической схеме появятся многократно вложенные фигурные скобки
          Только в быдлоязыках в которых нет break на метку, если я правильно понял о чем вы.
          Ответить
        • Я бы в таком случае подумал о бросании исключения.
          Ответить
          • Траеблядство как есть.
            Исключения - только для исключительных ситуаций. Для обработки штатного события использовать исключения - это полное мудачество!
            Ответить
            • exception-driven programming во всей красе
              Ответить
            • Ну да. Если использовать исключения для исключительных ситуаций, то, внезапно, обработчиков этих исключений становится на порядки меньше, и почти всегда хватает try ... finally (или вообще RAII в крестах) вместо try ... catch.

              А обработчиков по сути всего 1-2, которые или откатывают текущую транзакцию\операцию, или рвут сессию, или крашат прогу, в зависимости от фатальности.
              Ответить
            • >Траеблядство как есть.
              Согласен.
              >Исключения - только для исключительных ситуаций.
              Согласен вдвойне.

              Но в путхоне как вижу - нормальная практика.
              http://stackoverflow.com/questions/653509/breaking-out-of-nested-loops
              Ответить
              • http://mail.python.org/pipermail/python-3000/2007-July/008663.html
                А вот и разгадка! Гвидо сказал что break на метку "слишком сложно", быдлопитонисты и девы языка не осилят.
                И началось "в кривых руках" это не будет нормально использоваться, "Lazy programmers are everywhere" итд.
                Так про любую фичу можно сказать. "Bydloprogrammers are everywhere" - универсальный аргумент против любой конструкции вообще!
                Ответить
              • В пухтоне даже конец массива при его обходе for'ом - исключительная ситуация ;)
                Ответить
                • Вот оно родство с хацкелем. Бесконечные списки - это норма, а конечные - исключение.
                  Ответить
            • А что, необнаружение искомого файла или класса, как в посте, это не исключительная ситуация?
              Ответить
              • Ну в данном случае как бы да, но в контексте обсуждения вопроса выхода из некоего блока в любом месте - нет.
                Ответить
                • Ну это понятно что серебряной пули нет. Я говорил про конкретный случай.
                  А в ситуации где исключения логически не подходят... цепочка if'ов плюс функции, наверно.
                  Ответить
      • >Нормальная идиома для выхода из блока
        Для ущербного языка, где break может задавать только нечитаемый уровень вложенности - да, нормальный такой костыль.
        http://ideone.com/V0PSqV
        ПЫХОПРОБЛЕМЫ

        И тут же вопрос: зациклится ли такой код?
        label: break label;
        Ответить
        • Дык если мне не изменяет память, управление прыгает на точку после помеченного жабьей меткой оператора? Не совсем логично, конечно, смотрится...
          Ответить
          • Ну да. Вопросами подобного рода собеседовать нубов - самый раз.
            Правильно зацикливать - continue, но его без цикла не сделаешь.
            В общем хоть что-то в жабе сделали очень грамотно - goto вырвали с корнем и запретили, но сделали "структурные" переходы на начало/конец именованного блока.
            Ответить
            • Ну да, мне вот что в жабе нравится - нашли адекватное решение во всех местах, в которых в Си я бы применил goto (finally, break из пачки циклов и т.п.).
              Ответить
              • Ну да, искали-искали, и нашли то ли в Аде-83, то ли в ещё более раннем языке...
                Ответить
                • Но там-то goto наглухо не запрещали!
                  Тем более что другие "современные" сишкоблядские (PHP,С#) языки так и до сих пор (2013) не осилили выход по метке. О крестах и сишке я молчу.

                  И спору нет, по мне ада гораздо приятнее срамного поцкаля.
                  Ответить
                  • с++ тоже не осилил в переход по метке. сишка впрочем осилила
                    Ответить
                    • Речь о break/continue по метке на именованные блоки кода. И отказе от goto.
                      Вот:
                      INDX: for (var i=1;i<10;++i) for (var j=0;j<10;++j) if (j>3) break INDX;
                      console.log(i,j)

                      >сишка впрочем осилила
                      Не осилила.
                      Из сишкоблядских емнип только жаба, жс и D.
                      Ответить
    • Напомнило недавно попавшуюся программку:
      while( 1 )
      {
      //пять экранов ифов, бряков и свечей
      }
      while( 1 );

      Проблема зависания нашлась за десять минут без отладчика, после чего почему-то сразу вспомнился Тарас.
      Ответить
    • do {} while (false);
      это убожество в данном случае, так как этот оператор предназначен как цикл, а не костыль для здорового

      нужно было использовать

      try { }
      catch(Exception $e) {}
      Ответить
      • Поздравляю. Один костыль заменен на другой, еще более мудацкий.
        Именно то об чем выше писал Тарас.
        Тем более что исключения и пхп, эмм...
        Ну обработка ошибок в пхп явно сишкоблядская и потому даже исключения не спасут отца русской демократии.
        Ответить
        • > Один костыль заменен на другой, еще более мудацкий.

          Зато он не использовал goto и его духовный брахман не будет его ругать.
          Ответить
          • Каждый раз, когда ты используешь goto, умирает котёнок.

            Спаси мир от кошачьей экспансии. Юзай goto!
            Ответить
        • я лишь указал, что оператор не используется по назначению

          если говорить как я написал бы, то выглядело бы так

          $useDummy = true;
          @include_once $filename;
          if(class_exists($className)) {
          $useDummy = false;
          }
          Ответить
        • и для желающих заменять php другими словами как пхп и т.д. - ваш словарный запас от этого только кажется скуднее, чем вам кажется
          Ответить
          • >и для желающих заменять php другими словами как пхп
            рнр, сойдёт?
            Ответить
            • пнп-переход?
              Ответить
            • если бы бог был программистом, он бы написал
              while(1);

              пиши как хочешь, я пошел лесом
              Ответить
            • Как ты смеешь писать PHP маленькими буквами?!
              Ответить
              • не поверишь, специально оставил, для особо придирчивых

                ..всё так предсказуемо в этом мире
                Ответить

    Добавить комментарий