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

    +156

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    if (count($vCard) == 1) {
        print_r($vCard -> n);
        print_r($vCard -> tel);
    } else {
        foreach ($vCard as $vCardPart)
        {
            print_r($vCardPart -> n);
            print_r($vCardPart -> tel);
        }
    }

    https://github.com/nuovo/vCard-parser

    Ну за каким хуем обрабатывать один элемент как отдельный случай?!

    Запостил: bormand, 23 Июня 2014

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

    • P.S. Почему матерюсь: если в файле всего одна карточка, то нельзя бежать foreach'ем, а надо сразу лезть в поля. Эталонный пример дырявой абстракции...
      Ответить
      • форыч тормозит
        Ответить
      • ну вот пример динамики: элемент может быть как коллекцией, так и самим элементом, если он в ней один.
        это чтобы не городить такие штуки как element->values->value
        Ответить
        • > элемент может быть как коллекцией, так и самим элементом, если он в ней один
          Дурость это неюзабельная, а не пример динамики. По крайней мере в том виде, в котором мы это видим в данной либе.

          > это чтобы не городить такие штуки как element->values->value
          Это прекрасно, но разве так сложно было сделать, чтобы этот сраный один элемент возвращал итератор, возвращающий самого себя? Чтобы людям, которые хотят просто спарсить карточки в цикле не приходилось писать говно из топика... Иначе получается, что штуки типа element->values->value городить не надо, зато надо проверять count на единицу, и обрабатывать этот случай ОТДЕЛЬНО, ну либо юзать весьма неприятный хак с оборачиванием в массив, про который я написал ниже.
          Ответить
          • >элемент может быть как коллекцией, так и самим элементом, если он в ней один.
            Я писал такое как опять-таки оптимизацию.
            Экономия на обжекте-обертке.
            Например есть MultiMap с миллионами данных в котором у ключа может быть несколько значений.
            Но такое бывает редко.
            http://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures
            LinkedList :: Bytes: 24.00
            Оверхед LinkedLista большой и занимает много памяти (95% одиночных элементов обёрнуты в него), потому проверял instanceofом тип, ну и немного говнологики.
            Правда от конечного пользователя все подобные хаки сокрыты.
            Ответить
            • Ну этот одинокий элемент все равно же поддерживал общий интерфейс, и по нему можно было бегать for'ом, не обращая внимания, на то, что он forever alone? Ведь правда же?

              > Правда от конечного пользователя все подобные хаки сокрыты.
              Во-во.
              Ответить
        • Если выше непонятно объяснил:
          // вот так НЕЛЬЗЯ, либа этого не позволяет
          $cards = new vCard('1.vcf');
          foreach ($cards as $card) {
              // нам похер, сколько там карт, хоть 0
          }
          
          // и даже так НЕЛЬЗЯ, ибо абстракция дырявая как жопа Саши Грей
          // и оператор скобки не перегрузили интерфейс ArrayAccess не реализовали
          $cards = new vCard('1.vcf');
          $n = count($cards);
          for ($i = 0; $i < $n; ++$i) {
              $card = $n == 1 ? $cards : $card[i];
              // работаем с $card
          }
          
          // а нужно так, с блядской проверкой на 1
          $cards = new vCard('1.vcf');
          if (count($cards) == 1) {
              // обрабатываем одну карту
          } else {
              foreach ($cards as $card) {
                  // обрабатываем одну из многих карт
              }
          }
          Ответить
          • я обычно юзаю foreach(is_array($cards)?$cards : array($cards) as $card)
            Ответить
            • Ну опять же - это закапывание симптомов вместо лечения болезни.
              Ответить
            • if (!is_array($cards)) $cards=array($cards);

              Есть такие блядские либы которые когда результат 1 возвращают объект а когда больше массив объектов, самое хуёвое, что когда нет результата воpвращают null.
              Ответить
              • > Есть такие блядские либы которые когда результат 1 возвращают объект а когда больше массив объектов
                Это одна из них :)

                > самое хуёвое, что когда нет результата воpвращают null.
                Не, эта либа, слава богу, кидает экцепшн. За это автору респект.
                Ответить
                • респект на ексепшн? культура программирования катится в ад
                  Ответить
                  • > респект на ексепшн? культура программирования катится в ад
                    А что не так с экцепшеном из конструктора?
                    Ответить
                    • ну я думал что это нормальное поведение. а тут за него хвалят, будто это прям вершина. мне кажется за не использование эксепшенов надо наказывать
                      Ответить
                      • > а тут за него хвалят, будто это прям вершина.
                        Ты не забывай, в каком разделе ты находишься... Тут с чистой совестью могли захерачить die, или тупо не обрабатывать ошибку вообще...
                        Ответить
                  • > респект на ексепшн? культура программирования катится в ад
                    На днях пописал немного на C# и сжёг стул. Порыться в мешке значений грозит смертью - это какой-то мини-ад.
                    // JS
                    var x = {};
                    ...
                    var str = x["key"]; // ОК, товарищ. Нет значения - будет undefined.
                    if(str === undefined) return null;
                    return func(str);
                    
                    // C#
                    var x = new Dictionary<string, string>(); // string передаётся по ссылке - почему бы не вернуть null?
                    ...
                    string str = x["key"]; // АЗАЗА ТИ ЛАЛКА НЕТ ЗНОЧЕНЕЯ ЭТА ЭСКЛЮЧИТЕЛЬНОЯ СЕТУАЦЫЯ
                    // ЭКЗЕПШАН АШИПКА 0x0005fb68 АЗАЗА Я ТИБЯ ЗАТРАЛЕЛ
                    if(str == null) return null;
                    return func(str);

                    Порадовался "сишному" Dictionary<TKey, TValue>.TryGetValue. Взял переменную, проверил результат - и никаких богомерзких try, catch, скобочек, сломанной структуры кода.
                    Ответить
                    • Ну так и норм. В чем проблема, капитан?
                      Ответить
                      • В JS [] возвратит значение/undefined, в c++ [] возвратит значение или создаст и возвратит (и есть find с понятным мне названием), а вдруг сразу бьют по рукам и названия непонятные. Непривычно.
                        Ответить
                        • ну тут все утыкается в "непривычно" это не страшно
                          Ответить
                        • Самый нормальный вариант - возвращать два значения, одно - значение полученое по ключу, другое - был ли действительно такой ключ.
                          Т.е. ж.скрипт вариант тут лажает, т.как
                          var foo = { foo: undefined };
                          foo.foo === foo.bar;

                          А чтобы узнать а был ли ключ, нужно сделать:
                          "foo" in foo;


                          Я думаю, что соображения выше вместе с типичным поведением массивов при доступе по несуществующему индексу и мотивировали ошибки при обращении к хеш таблице.
                          По личным наблюдениям ошибка при попытке получить значение по несуществующему ключу - как правило бесполезная, попытка записать по невозможному ключу - хоть и не очень приятная, но оправдана, по крайней мере соображениями типа выделения памяти под массивы. Как правило код все равно сломается, если мы ничего не нашли по нужному ключу, ну а если мы эту ситуацию уже предусмотрели, то вообще замечательно.
                          Ответить
                    • > Взял переменную, проверил результат - и никаких богомерзких try, catch, скобочек, сломанной структуры кода.
                      Дык есть же джве ситуации:
                      1) Отсутствие значения - баг в коде (из поля в базе прочиталась херня, которую мы не знаем как обрабатывать). Тут лучше кинуть исключение и обработать его тупо отбоем запроса, закрытием сессии или даже остановкой сервера. Прокидывать коды возврата в таких случаях - противно.
                      2) Отстутствие значения - нормальная ситуация. Тут как раз поможет TryGetValue. Исключения здесь не особо удобны.
                      Ответить
                      • Вот поменять бы местами...
                        [] для нормальных ситуаций, TryGetValue - для багов в коде (по аналогии с гармоничными привычным [...] и длинным at(...)). TryGetValue для меня означает "ну я сейчас попытаюсь взять значение, а если не получится - ловите исключение".
                        Ответить
                        • Ну я привык наоборот - по дефолту эксепшен, а хочешь в обход - вот тебе метод в обход. на вкус и цвет...

                          Говоряят стетор уходит. Как Ельцин
                          Ответить
                          • Я к вольности привык. Чтоб не все расплачивались за ошибку, а в одной функции вылез NaN. Чтоб хотелось замолить свой грех, добавив проверку результата malloc, а не приводить int к bool и не окружать невинные строки слоями try/catch...

                            Хм, жаль, что уходит. Как человек, способный сказать что-то не про программирование, он полезен для сайта. Можно читать только комментарии wvxvw и товарищей на ГК и расширять кругозор.
                            Ответить
                            • Ябм
                              Хорей
                              Дактиль
                              Амфибрахий
                              Анапест

                              Просвещайтесь с Кегданом.
                              А вообще ГК превратился в форум. Порой интереснее просто болтать о всяком, чем обсуждать код. И это хорошо.
                              Ответить
                            • Это только когда его отпускает.
                              Ответить
            • Зачем так сложно??? Достаточно:

              foreach((array)$cards as $card)
              Ответить
              • > foreach((array)$cards as $card)
                $cards - объект с итератором. Х.з., что там получится после такого каста... Лень тестить, но, имхо, не взлетит.

                > if (!is_array($cards)) $cards=array($cards);
                > foreach(is_array($cards)?$cards : array($cards) as $card)
                Туда же.
                Ответить
    • >Ну за каким хуем обрабатывать один элемент как отдельный случай?!
      Оптимизация же.
      Для малого количества итераций рынарешники вручную анроллят циклы.
      Ответить
      • > Для малого количества итераций рынарешники вручную анроллят циклы.
        Не, я поступил совсем по-читерски:
        // грязный хак
        if (count($cards) == 1)
            $cards = array($cards);
        
        foreach ($cards as $card) {
            // ...
        }
        Ответить
      • switch(count($cards))
        {
            case 0:
                break;
            case 1:
                doShit($cards);
                break;
            case 2:
                doShit($cards[0]);
                doShit($cards[1]);
                break;
            //...
            default:
                foreach ($card as $cards)
                {
                    doShit($card);
                }
        }

        Оптимизировано
        Ответить
    • Типично в таких ситуациях пишут (или берут из библиотеки!) функцию типа
      foreach (ensure_array($whaterver) as $x) { ... }
      и все счастливы.
      Ответить
      • > Типично в таких ситуациях пишут
        Т.е. вместо лечения болезни нужно задавить ее симптомы? PHP way, хуле.
        Ответить
        • Нет, это не из ПХП вообще https://github.com/keithj/alexandria/blob/master/lists.lisp#L259
          Александрия - это очень уважаемая библиотека, без нее практически ни в одном проекте не обходится.
          Ответить
    • https://github.com/nuovo/vCard-parser/blob/master/write-test.php

      охуенный тест!
      Ответить
      • Не упало - значит всё работает.

        P.S. Да не, к либе в целом претензий нет, свою задачу она решает.
        Ответить
        • ну, справедливости ради, у меня на гитхабе вообще нихуя толкового.

          а почему не эта либа?
          https://github.com/fruux/sabre-vobject
          Ответить
          • > а почему не эта либа?
            Да там по задаче надо 2-3 поля из vcard'а выцепить... Поэтому выбирали либу попроще, чтобы можно было прочесть и понять. И либы на 30+ файлов сразу оказались в пролете по этому критерию...
            Ответить
    • Кстати, интересно, за что столько минусов? Просто за мат в подписи? Или кто-то всё-таки считает, что код нормален, и так и надо? Или же код слишком уныл или баянист?
      Ответить
      • прижгло ? на ГК минусуют/плюсуют в зависимости от фазы луны. Такому олдфагу впору уже и забить на это.
        Ответить
      • Я вчера был стохастический.
        Ответить

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