"PHP" / Говнокод #26832 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
Именно поэтому я за «PHP» #3
#1: https://govnokod.ru/26462 https://govnokod.xyz/_26462
#2: https://govnokod.ru/26827 https://govnokod.xyz/_26827

Запостил: gostinho gostinho, (Updated )

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

  • https://www.php.net/manual/ru/function.sleep.php#105149
    // A really simple, but effective way of majorly slowing down bruit force attacks on wrong password attempts.
    
    // In my example below, if the end-user gets the password correct, they get to log in at full speed, as expected.
    // For every incorrect password attempt, the users response is delayed by 2 seconds each time; mitigating the
    // chances of a full bruit force attack by a limit of 30 lookups a minute.
    
    // I hope this very simple approach will help make your web applications that little bit more secure.
    
    <?php
    public function handle_login() {
        if($uid = user::check_password($_REQUEST['email'], $_REQUEST['password'])) {
            return self::authenticate_user($uid);
        }
        else {
            // delay failed output by 2 seconds
            // to prevent bruit force attacks
            sleep(2);
            return self::login_failed();
        }
    }
    ?>

    Какая защита )))
    Ответить
    • Комменты к документации «PHP» — это просто склад эпического дерьма.
      С той же страницы:
      // This will allow you to use negative values or valuer below 1 second.
      
      <?php slaap(0.5); ?>
      
      <?php
      function slaap($seconds)
      {
          $seconds = abs($seconds);
          if ($seconds < 1):
             usleep($seconds*1000000);
          else:
             sleep($seconds);
          endif;   
      }
      ?>

      > This will allow you to use negative values
      Только в «PHP» можно отправлять поток управления в прошлое. Именно поэтому я за «PHP».
      // Here is a simplified way to flush output to browser before completing sleep cycle. 
      // Note the buffer must be "filled" with 4096 characters (bytes?) for ob_flush() to work before sleep() occurs.
      <?php
      ob_implicit_flush(true);
      $buffer = str_repeat(" ", 4096);
      echo "see this immediately.<br>";
      echo $buffer;
      ob_flush();
      sleep(5);
      echo "some time has passed";
      ?>

      Какой flush )))
      Ответить
    • Типа если у тебя N потоков обрабатывает запрос, то я сделал тебе N неправильных запросов, и ты отдыхаешь?
      Ответить
    • script.php?sleep=10 // Will stop after 10 secs


      какой API :))
      Ответить
  • // delay failed output by 2 seconds
            // to prevent bruit force attacks and make DDoS attacks more effective
    Ответить
  • Басня "Пыхомакака и сигналы"

    Since sleep() can be interrupted by signals i've made a function which can also be interrupted, but will continue sleeping after the signal arrived (and possibly was handled by callback). It's very useful when you write daemons and need sleep() function to work as long as you 'ordered', but have an ability to accept signals during sleeping.
    
    <?php
    function my_sleep($seconds)
    {
        $start = microtime(true);
        for ($i = 1; $i <= $seconds; $i ++) {
            @time_sleep_until($start + $i);
        }
    }
    ?>


    > can also be interrupted, but will continue sleeping after the signal arrived
    WAT?
    Ответить
  • if you for some reason need a constant-time implementation of realpath(), try
    
    <?php
    
    function realpath_constant_time(string $path, float $target_seconds, bool &$constant_time_success = null){
        $start_time=microtime(true);
        $ret=realpath($path);
        $constant_time_success = @time_sleep_until($start_time+$target_seconds);
        return $ret;
    }
    ?>
    
    for example, a realtime that always uses exactly 1 millisecond (should be more than enough for SSD-based servers, perhaps rotating harddrive based servers may need something closer to 10 milliseconds, i don't know):
    
    <?php
    realpath_constant_time("/path/to/../to/file.txt",0.001,$constant_time_success);
    ?>
    
    and you can use $constant_time_success to see if you needed more time (and thus failed to do realpath() in constant-time), or if you succeeded.
    Ответить
    • Мартышка прерывает выполнение реалпаса, если он слишком медленный?

      >серверс
      VPSы? Не, не слышал
      Ответить
      • Наоборот, удлинняет слипом, если риалрас оказался слишком быстрым.
        Ответить
          • Пытаются защититься от атак замерами таймингов, видимо. Чтобы ты не понял какие файлы существуют.

            Какое секьюрити )))
            Ответить
            • А есть ли реальный пример того, что можно таким образом взломать? Ну, допустим, узнал я, что есть на сервере файл "includes/functions.php". И что дальше?
              Ответить
              • А х.з., если у тебя доступ есть, то ты и так можешь попробовать открыть, нету смысла делать это через realpath. А если нету - то имя ничего особо не даст.

                Может быть там юзерские файлы какие-то, имена которых не хочется светить?

                Ну или какие-то свойства системы выяснить по именам чтобы поискать соотв. эксплойты.
                Ответить
  • Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in /home/stb100/public_html/wp-content/plugins/types/vendor/toolset/types/embedded/includes/wpml.php on line 646

    Сайт Стеленбосского университета в ЮАР.
    Ответить
  • https://habr.com/post/513558/
    >>>
    История с синтаксисом атрибутов в PHP 8 продолжается.
    
    Вкратце: сначала был << >>, переголосовали за @@, а теперь новый виток обсуждений.
    У @@ были проблемы с парсером, но они решены благодаря нижеупомянутому RFC про
    неймспейсы. Тем не менее у него есть другие проблемы, и в качестве альтернативы
    предлагался вариант #[ ] как в Rust, но и у него есть минусы.

    >>> В PHP 8, при сравнении чисел и строк с помощью нестрогого == оба операнда приводятся к строке и сравниваются как строки, если один из них не является числовой строкой.
    >>> 0 == 'foobar' теперь официально false.

    >>> В PHP 8 будет новый оператор nullsafe: ?->.

    Именно поэтому я за «PHP».
    Ответить
    • Оператор nullsafe — полезное предложение. От кучи лапши можно будет избавиться.

      А вот «Renamed Parameters», как в «Свифте» — это забавно. Можно будет писать запутанный код: function($first:second, $second:first).

      >> Пользователям Laravel 5.5 рекомендуется не использовать драйвер сессий 'cookie'.

      Какой багор )))
      Ответить
      • А при чём тут Свифт? Это скорее как в Пистоне.

        В Свифте позиция аргумента fixed
        Ответить
  • «Создайте систему, которой сможет пользоваться даже дурак, и только дурак захочет ею пользоваться», — Принцип Шоу.
    Ответить
    • То есть любой не-дурак склонен к оверинжинирингу?
      Ответить
      • Да, кстати. Дурак сделает хуйню, умный сделает по-умному и охуеет от сложности, а гений сделает по-умному, но времени это займёт как хуйня.
        Ответить
        • не совсем кмк

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

          Есть три стадии программиста

          Джун делает всё тупо и на коленке, хардкодом, в одном файле, c копипастой, потому получается просто

          Миддлу уже так не интеерсно, и он старается сделать Очень Умный Фреймворк, который сам всё сделает.

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

          И только сеньор понимает, что сложность нужно ограничивать, иначе будет пиздец.
          Ответить
          • И как же «сеньор» ограничивает сложность? Помечает классы как final?)
            Ответить
            • о final написано в "Effective Java" прямо у Блоха, так что с этим справляется еще и мидл.

              Сеньор, вероятно, не делает систему расширяемой в том месте, где это не нужно, и не плодит лишних уровней абстракции
              Ответить
              • сегодня не нужно, а завтра нужно

                борьба с "лишними" уровнями это прекрасно, но часто разбивается о камни хотелок бизнеса, меняющихся раз в неделю

                что не отменяет того факта, что некоторые любят написать нечто такое, что само по себе неожиданно не менее сложно, чем весь остальной код. но "сеньорность" на это никак не влияет.
                Ответить
                    • > Vulkan

                      А что с ним? Не припомню там бесполезных вещей и оверинжиниринга.
                      Ответить
                      • По сравнению с OpenGL он ОЧЕНЬ низкоуровневый, я уверен, что возможность работы с буфером видеокарты – это лишнее и оверинжиниринг для кого-нибудь.

                        Хотя я хуйню сказал, да, т.к. вулкан делает ровно то, для чего он нужен.

                        Лучше бы я про QT вспомнил, его можно и за и против ягни приплести.
                        Ответить
                        • > QT

                          Да ну. Тоже плохой пример. Вполне практичная либа, оверинжиниринга там на порядок меньше чем в бусте и стд.

                          Ему разве что нарушение DRY можно приписать, но тогда реальных альтернатив не было. Для многих классов в духе QString и сейчас нету.
                          Ответить
                          • Qt это просто замена стандартной блеватеке, про такое сложно сказать, избыточна она или нет.

                            Но так у них есть классы для работы с FTP, обязательно ли их наличие в UI-тулките, вопрос
                            Ответить
                            • > в UI-тулките

                              А в UI-тулките их и нет, лол. Там же отдельная либа на каждую тему всё-таки. Если тебе просто гуйню наваять -- не подключай QtNetwork.
                              Ответить
                          • С другой стороны, там есть функционал для работы с сетью, а это не то, чего ждёшь от фреймворка для десктопного формошлёпства. Я не спорю, что это может быть удобно, но всё-таки это нарушение ЯГНИ. А для работы с сетью нужна либа для работы с сетью.
                            Ответить
                            • См. выше. Либа для работы с сетью там всё-таки в отдельной либе. Как и либа для работы с SQL. Не нужны -- не подключай.
                              Ответить
                  • угу

                    приходишь ты на совещание, там тебе говорят: "нам надо сделать то, то и сё, а вот это переделать, а вот это уже не нужно"

                    а ты такой с вертухи: YAGNI, KISS, DRY!

                    а тебе: спасибо, у Вас завтра последний день, зайдёте в бухгалтерию
                    Ответить
                    • попробуй все таки нагуглить определение в вики, и почитать первое предложение включая два последних слова)
                      Ответить
                      • зачем?

                        ещё раз: best practises как самоцель это мастурба

                        сеньор, если он сеньор, а не лычкодрочер, должен помогать бизнесу достигать целей своей экспертизой, а не лайки собирать на медиуме, копипастя баззворды с википедии
                        Ответить
                        • >зачем?
                          чтобы понимать, о чем говоришь

                          YAGNI не мешает бизнесу достигать своих целей, и даже наоборот: помогает, потому что экономит время и деньги
                          Ответить
                          • извини, я не работаю по википедии

                            возможно, в твоей компании это ок, я ж не знаю
                            Ответить
                            • то есть встрертя незнакомую аббревиатуру ты выдумываешь ей не случайную семантику?
                              Ответить
                              • предпочитаю делать реальную работу вместо того, чтобы зазубривать семантику аббревиатур
                                Ответить
                                • Тогда зачем обсуждать слова с неизвестной тебе семантикой?

                                  Ягни не означает "отказывать бизнесу в выполнении требований"
                                  Ответить
                                  • во-первых, семантика мне знакома

                                    во-вторых, эти ягни в разговор зачем-то принёс ты

                                    так шо могу лишь ещё раз посоветовать сходить на курсы "русская езык" =)
                                    Ответить
                                    • >во-первых, семантика мне знакома
                                      >предпочитаю делать реальную работу вместо того, чтобы зазубривать семантику аббревиатур
                                      /0

                                      Я принес ягни, и ты сообщил:

                                      [quote]
                                      приходишь ты на совещание, там тебе говорят: "нам надо сделать то, то и сё, а вот это переделать, а вот это уже не нужно"

                                      а ты такой с вертухи: YAGNI, KISS, DRY!
                                      [/quote]

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

                                      Это неверно.

                                      >так шо могу лишь ещё раз посоветовать сходить на курсы "русская езык" =)

                                      "О чем может спорить человек, который не поменял паспорт? Какие взгляды на архитектуру может высказать мужчина без прописки?
                                      И вообще, разве нас может интересовать мнение человека лысого, с таким носом?" (c)
                                      Ответить
                                      • если тебя не интересует моё мнение, то зачем ты страдаешь этой шизофазией?

                                        "гналась за Вами пять вёрст, чтобы сказать, как Вы мне безразличны"?
                                        Ответить
                          • Ягни в интерпрайзе это почти всегда пиздеж

                            Спустя 5-10-15 лет систему будут использовать так как синьйор и представить не мог
                            Ответить
                            • именно по причине того, что мы не знаем, что будет через 15 лет, ягни и предлагает рефакторить походу
                              Ответить
                              • Обсуждали недавно google groups который спустя 15 лет ягни неожиданно оказался тормозным говном
                                Ответить
                                • На момент разработки GG они выбрали единственно верную на тот момент архитектуру.

                                  То, что они 20 лет не развиваются, к "ягни" отношения не имеет.

                                  Ягни не является советом "не развивайтесь двадцать лет"
                                  Ответить
                                  • ягни является советом "давайте выкатим побыстрее и потом допилим". Как показывает пример GC допил проектов сделанных по ягни оказывается нерентабельным
                                    Ответить
                                    • Как показывает пример Facebook, Ebay и Вконтакте подход "давайте выкатим побыстрее и потом допилим" оказывается вполне рентабельным

                                      А пример "hurd" дает нам обратный пример
                                      Ответить
                                      • примеры конечно хорошие но средний бюджет на допил все-таки поменьше чем у фейсбука для флагманского продукта

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

                                        по-моему это одно и тоже и адепты ягни воюют с мельницами или сами с собой
                                        Ответить
                                    • > Как показывает пример GC допил проектов сделанных по ягни оказывается нерентабельным

                                      Я видел и обратные примеры. В одной конторе была ягни-питушня с самого её создания. Её пилили академики, и код там был крайне умный, но без рахитектурных наворотов. Решили её заменить аналогичной питушнёй, но сделанной "по уму". С инъекциями фабрик стратегий прямо в пятую точку разработчику и всем прочим. Итог на сегодняшний день: изначальная ягни-питушня живёт, а замена похоронена.
                                      Ответить
                                      • удивительно, что в этой конторе никто не подумал, что бывают не только крайности
                                        Ответить
                                    • > оказывается нерентабельным

                                      Тут скорее сама задача нерентабельна. Как ты будешь монетизировать архив почтовых переписок, которые читает кучка нердов? Это же не тикток и не инстаграм. Вот и крутится как есть 20 лет.
                                      Ответить
                                      • > Как ты будешь монетизировать архив почтовых переписок

                                        - гуглпочту они ж как-то монетизируют
                                        Ответить
                                        • > гуглпочту они ж как-то монетизируют

                                          Там есть твои приватные данные, а в рассылках всё публичное и доступно в других местах.
                                          Ответить
                          • > отказ от избыточной функциональности, — то есть отказ добавления функциональности, в которой нет непосредственной надобности.

                            Чем-то мне это напоминает сёмино «нинужно»...
                            Ответить
                              • У программиста на питоне нет непосредственной необходимости знать как работает компилятор, например. И таких примеров ещё много можно привести.

                                Я уверен, что и в линухе есть вещи, которые ты ain't gonna need, но кому-то они могут быть очень даже нужны.

                                Плюс, насколько я понимаю, ты предлагаешь добавлять фичи и инфраструктуру для них по мере поступления хотелок начальства? Тогда могут возникнуть серьёзные проблемы, т.к. придётся рефакторить или даже переписывать чуть ли не весь существующий код.
                                Ответить
                                • ну типа у нас сегодня одно окно и всего два интерактора, зачем нам контрактное программирование и продумывать dependency injection. Захуярим всё синглтонами, будет заебись

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

                                  и проч.
                                  Ответить
                                  • Предлагаю не останавливаться на dependency injection, и поддержать загрузку кода по сети, так как в будущем это вполне может быть нужно.

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

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

                                    Машину лучше реализовать как минимум под x86 и arm, причем с JIT.

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

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

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

                                    Не стоит так же забывать про IPX/SPX, которые еще могут встречаться в очень старых системах.
                                    Ответить
                                • Пример не совсем корректен, так как более скилловый программист может выполнять задачи лучше (или, как минимум, не хуже) менее скиллового.

                                  А более сложный код более сложен в поддержке (неожиданно, правда?), менее надежен и более труден для понимания.

                                  >которые ты ain't gonna need, но кому-то они могут быть очень даже нужны.

                                  Если они кому-то нужны, то это не ягни. В ягни речь о том, что не нужно никому.

                                  >Тогда могут возникнуть серьёзные проблемы, т.к. придётся рефакторить

                                  Идеальный код, который поддерживает все возможные кейсы занимает по времени разработки бесконечность.

                                  Именно потому фичи нужно добавлять по мере необходимости, о чем собссно и говорит ягни
                                  Ответить
                                  • > А более сложный код более сложен в поддержке

                                    Сложный код – это когда нет комментариев, а сам код писали Индусы на коленке за еду. В такой код сложно что-то добавить, ведь посыпется всё остальное.

                                    А хороший код должен быть продуманным и следовать принципам SOLID.

                                    > Если они кому-то нужны, то это не ягни.

                                    Тогда зачем нужен ЯГНИ? Мне кажется, что если программист говорит: «В ТЗ написано сделать программу для подсчёта кур, но я пока далеко не продвинулся, ебусь с функцией выгула свино-собак», то ему уже никакое ЯГНИ не поможет, а нормальных людей оно наведёт на непристойные мысли, что клиенту никогда не понадобится считать индюков, макак, прыщебля́дей и т.д.

                                    > Идеальный код, который поддерживает все возможные кейсы

                                    Это правда, но в пределах одной предметной области вполне возможно выстроить замечательную архитектуру и охватить как можно большее количество фич.

                                    > Именно потому фичи нужно добавлять по мере необходимости

                                    Смысл продуманной архитектуры не в том, чтобы добавить все фичи, а чтобы сделать процесс их добавления очень простым и быстрым. Это, кстати, довольно легко организуется, если программист скилловый, а потом фичи добавляются с удовольствием.
                                    Ответить
                                    • > А хороший код должен быть продуманным и следовать принципам SOLID.

                                      SOLID это хуита из ООП, которая за пределами ООП-хуйни неприменима, так что нехуй его вплетать в определение "хорошего кода"
                                      Ответить
                                      • Замени «объекты» на «модули», в которые ты пихаешь функции, и следуй SOLID в процедурном стиле, не вижу тут проблемы.
                                        Ответить
                                        • Что есть «модули»? А если у меня не процедурный стиль, а функциональный? А если это какой-нибудь Prolog?
                                          Ответить
                                          • Модуль – это сложный узел, выполняющий самостоятельную функцию в техническом устройстве, а также вообще отделяемая, относительно самостоятельная часть какой-н. системы, организации.

                                            Я не знаю как ФПшники и процедурники организуют код, но что-то мне подсказывает, что они раскидывают процедуры и функции по файлам, чтобы не было мешанины.

                                            А разве плохо, когда программа состоит из изолированных друг от друга частей с понятными правилами кто кого меняет/вызывает?
                                            Ответить
                                            • > А разве плохо, когда программа состоит из изолированных друг от друга частей с понятными правилами кто кого меняет/вызывает?
                                              У меня в Си это называется "функция". Зачем мне для этого модули?
                                              Ответить
                                        • И вообще, это вот "следуй SOLID, используй такой-то там говнопаттерн, используй какую-то там блядь поеботину, которую какой-то хуй где-то там описал как что-то охуенно важное и необходимое, а иначе это говнокод" - вот это хуйня полнейшая. Если мне надо решить вполне четко поставленную задачу, например прошивку контроллера, который чтоб мерял напряжение через встроенный АЦП и если напряжение превышает заданные пределы, то тогда что-то там делал (пищал через впаянную пищалку, или что-то там отрубал, или еще какую хуйню делал), то никакой солид-хуёлид тут нахуй не встал, просто берешь и пишешь код, который делает то, что делает, и не ебешь себе мозги всякой там хуетой про разделение каких-то там блядь модулей, единственной ответственностью и тому подобной нерелевантной чепухой
                                          Ответить
                                          • Да, тут я согласен.

                                            Вообще, SOLID нужен для всякой энтерпрайз питушни, где без него код быстро превратится в лапшу и умрёт, а прошивке такое обычно не грозит.
                                            Ответить
                                            • Да, понятно что SOLID это для каких-то больших хуитеней, и там вводят какие-то правила единственной ответственности, LSP и прочее, но даже для больших хуитеней этот SOLID не всегда применим. Возьмем некую большую хуитень на Си (пример больших хуитеней на Си - Linux kernel, PostgreSQL), в языке Си нет понятия классов, соответсвенно, нет и наследования. Если нет наследования, каким боком тут вообще может быть LSP? Мы вообще никак не можем расширять базовые классы, потому что классов вообще нет в языке.

                                              А что насчет OCP (open–closed principle), что за хуйню он должен означать, если классов нет и, соответственно, наследования тоже нет?
                                              Ответить
                                              • Конкретно LSP следовать не нужно, т.к. ООП же нет. Да и «следовать SOLID» не значит быть каким-то сектантом, всегда нужно думоть самому. Но к некоторым умным вещам из того же SOLID стоит прислушаться:

                                                The open–closed principle states "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification".

                                                Как видишь, «software entities» – это не только классы.
                                                Ответить
                                                • А вообще, все эти паттерны и принципы – это аналог приличий: хорошо, когда о них знаешь и ведёшь себя соответственно, но все мы знаем, что всегда манерные только пидорасы и джентльмены.
                                                  Ответить
                                              • > что за хуйню он должен означать, если классов нет

                                                Эм, да OCP -- это же банальное "не ломай интерфейс без причины, сука!"

                                                Причём здесь вообще классы? Оно и для сишки со структурами и функциями прекрасно работает. Если эти функции больше одного раза юзаются, конечно.
                                                Ответить
                                                • > Эм, да OCP -- это же банальное "не ломай интерфейс без причины, сука!"

                                                  А зачем для этого придумывать некий принцип, если это и так очевидно? Почему тогда нет принципа "не давать функциям и переменным длинные и нечитаемые имена"? А то вот кто-то напишет еще код вида:
                                                  int dfhgkja_n8y578e54ng8(int pihgt9h)
                                                  {
                                                    int osreugn8bhr75h78 = 6;
                                                    ....
                                                  }


                                                  На вики https://ru.wikipedia.org/wiki/Принцип_открытости/закрытости пишут что есть OCP Мейера и еще какое-то полиморфное OCP.

                                                  Собственно, цитата:
                                                  >Принцип открытости/закрытости означает, что программные сущности должны быть:
                                                  >
                                                  > открыты для расширения: означает, что поведение сущности может быть расширено путём создания новых типов сущностей.
                                                  > закрыты для изменения: в результате расширения поведения сущности, не должны вноситься изменения в код, который эту сущность использует.
                                                  Э? А как это относится к не ломанию интерфейсов? Ну и если сущности будут закрыты для изменения и даже закрыты для расширения, я интерфейс один фиг могу сломать, выкинув старую сущность и написав новую.

                                                  Тут про какие-то "сущности" говорят, что это вообще за "сущности"? Структуры? А как я их закрою для изменения? Может командой chmod ugo-r some_struct_defs.h ?
                                                  Ответить
                                                  • т.е. "chmod ugo-w some_struct_defs.h" - чтоб файл никто не редактировал. А расширять надо через инклуд этого хедера и всовыванием той структуры в другую структуру, добавляя тем самым новые поля, лол.

                                                    Мне вообще концепция ООП(вокруг которой построена вся эта SOLID-концепция) совершенно не нравится - https://habr.com/ru/post/451982/
                                                    Ответить
                                                    • Давненько не было у нас срачей про ООП)


                                                      Имхо, ООП это просто инструмент.
                                                      Иногда он нужен, иногда нет.

                                                      Но адпеты ООП еще в конце 90-х всех заебали рассказами, что ООП это серебрянная пуля, а за одно и все хорошие практики записали на счет ООП.

                                                      Инкапсуляция, говорили они, есть только в ООП.

                                                      Хотя хороший API разумеется инкапсулирует в себе детали реализации, даже если он написан на QBasic.

                                                      Полиморфизм кококо, говорили они.

                                                      А разве одинаковая работа линукса с любой файловой системой через VFS это не полиморфизм?

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

                                                      А нужно было просто признать, что ООП это такой же примерно прием как передача объекта по ссылке.
                                                      Иногда полезен, иногда нет.

                                                      Такая же хуйня произошла с GUI.

                                                      А SOLID есть и без ООП

                                                      Наприме Single-responsibility principle
                                                      это же перефраз "UNIX way"
                                                      Ответить
                                                        • > как выглядит LSP без ООП

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

                                                          Нарушение LSP в данном случае -- нахуярить под каждый чип свой уникальный интерфейс, под который придётся подпиливать всю остальную логику.
                                                          Ответить
                                                          • >Нарушение LSP в данном случае -- нахуярить под каждый чип свой уникальный интерфейс

                                                            Причем технически API должен совпадать, а семантика должна отличаться, иначе это не интересно)

                                                            Например, драйвер последовательного порта получает ioctl, и там указатель на массив байт, и должен их послать в порт, и там дёрнуть прерывание в конце (хз так ли это на самом деле).

                                                            А вот ты пишешь драйвер, который вроде бы умеет получать то же самое ioctl, но шлёт в порт только каждый пятый байт. Или сначала дергает прерывание, а потом начинает слать в порт.

                                                            Это вроде бы и есть классическое нарушение LSP, и в общем протекание абстракции
                                                            Ответить
                                                            • > Причем технически API должен совпадать, а семантика должна отличаться

                                                              Ну ок, натянуть интерфейс от UART'а на SPI. А потом требовать, чтобы клиент сначала высрал 10 нулевых байт через write, а только потом звал read. Где-то я такую херь даже видел.
                                                              Ответить
                                                          • > Нарушение LSP в данном случае -- нахуярить под каждый чип свой уникальный интерфейс, под который придётся подпиливать всю остальную логику.

                                                            Нет, LSP это не только про соблюдения единого API. Это и про то, что если ты некую хрень расширяешь чем-то, то это не должно ломать поведение того, что до этого в базовом классе. Например, если у тебя есть звуковая карта, которая умеет только лишь воспроизводить звук через ЦАП (микрофонного входа нет), ты сделал некий драйвер с неким API, а потом появилась звуковуха еще и с входом под микрофон, и ты унаследуешь интерфейс, добавляя еще хуйню чтоб аудиосемплы принимать. А если у тебя будет хуйня только с микрофонным входом, и ты унаследуешься от хуиты в которой есть функция воспроизведения аудиосемплов, это уже хуйня какая-то, потому как зачем тебе это воспризведение? Использование функции воспроизведения аудиосемплов тогда не имеет смысла, так что надо наслеоваться от хуйни, которая вообще нихуя не умеет по-сути, т.е. из нее отнаследовать хуйню для АЦП, потом от нее же хуйню для ЦАП, а потом надо еще эти хуйни совместить (когда и то и то есть), и как это в ООП-парадигме описывается?
                                                            Ответить
                                                            • Лучше всего заменить наследование делегированием

                                                              class SoundDevice
                                                              у него массив capabilities: Capability[]

                                                              Sink extends Capability //апутпут
                                                              Source extends Capability //микрофон

                                                              Алгоритм для работы с микрофоном может искать нужный capability.

                                                              Если инофрмции о типе в рантайме нет, но можно использовать visitor, прости господи
                                                              Ответить
                                                              • Ну т.е. получается так, что одна из основных концепций ООП - наследование хуйни из хуйни с расширением всякой дрисни при таком наследовании - обосралась?

                                                                А если у нас какие-то ебанутые ограничения на одновременное юзание sink и source? Например, если совмещенные АЦП и ЦАП от одного источника получает тактовые импульсы, и получается что samples per second на АЦП и на ЦАП должно быть строго одинаково, т.е. не может быть такой хуйни, что АЦП работает на 8000 а ЦАП 44100? Ну а если все же иногда можно, например если в одном 8000 а в другом 16000, то тогда можно 16000 поделить на 2 встроенным делителем частоты, и тогда норм? А если в кодеке, совмещающем ЦАП и АЦП есть какие-то особые функции, например аппаратное эхоподавление, которое работает только тогда, когда частоты дискретизации строго совпадают, и тогда вот трюк с делением на 2 уже не работает?

                                                                Вот как все эти говноньюансы какой-то там микросхемки учитывать в этом делегировании? Как тут соблюдать LSP?
                                                                Ответить
                                                                • > Ну т.е. получается так, что одна из основных концепций ООП - наследование хуйни из хуйни с расширением всякой дрисни при таком наследовании - обосралась?

                                                                  Конечно, причём на многих уровнях одновременно.
                                                                  Начнём с того, что понятие объекта из ООП вредно и избыточно, поскольку оно заигрывает с понятием объекта в реальном мире. А отношения между абстрактными понятиями в реальном мире сами люди друг-другу-то объяснить не могут, чего говорить о тупой машине. К примеру, можно ли наследовать `математику' от класса `наука'? У всех будут разные мнения, т.к. в реальном мире понятие `наука' довольно расплывчато, и поэтому, например, позитивизм приводит к такому неистовому багру учёных.
                                                                  В функциональщине с тайпклассами абстракции куда более простые и эффективные. Они математические. Хоть они и менее интуитивные, но зато если ты доказал, что при подстановке твоей питушни в тайпкласс `зигоморфизм' все уравнения зигоморфизма выполняются, то твоя питушня — зигоморфизм и точка.
                                                                  В ООП не так. Всякий раз, когда я наблюдал код-ревью у адептов ЙАЖА, это были сраные "диалоги" Платона. Является ли свойство X частью интерфейса Y? Один йажник считает, что X-ность является частью эйдоса Y-ковости. Другой считает, что нет. Поставить точку в этом споре нельзя, ибо всё донельзя субъективно. 1/2
                                                                  Ответить
                                                                  • 2/2

                                                                    Далее об избыточности. Класс в ООП-язычках типа йажи выполняет одновременно четыре несвязанные роли:

                                                                    1) это контейнер для функций и контроль видимости (то, что в нормальных языках делает модуль),

                                                                    2) он создаёт контракты (то, что в нормальных языках делает class declaration)

                                                                    3) он выполняет контракты (то, что в нормальных языках делает instance declaration)

                                                                    4) он до кучи занимается лочками (synchronized methods)

                                                                    В итоге получается паззл, который с первого раза собрать невозможно, отсюда рефакторинг. ЙАЖА-программисты меня часто спрашивают, как я рефакторю ФП в Emacs. А необходимости в этом особой нет, т.к. все куски кода друг с другом слабо связаны и двигать их туда-сюда, чтобы что-то новое добавить, не нужно.
                                                                    Ответить
                                                                • Выразить требование к одинаковости samples per second у двух разных устройств статически вряд-ли получится (во всяком слуае в яже).
                                                                  В тайпскрипте можно изъебнуться с literal types, на крестах наверное можно наметушить, но к ООП это отношения не имеет)

                                                                  В яже придется описывать контракт в документации, проверять в рантайме, и кидать исключение.

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


                                                                  Основные концепции ООП (официально) это абстракция, инкапсуляция и полиморфизм. Наследование не обязательно. И кстати все три концепции можно выразить без ООП.
                                                                  Ответить
                                                                  • > Основные концепции ООП (официально) это абстракция, инкапсуляция и полиморфизм.

                                                                    - Алан Кей смотрит на тебя с недоумением
                                                                    Ответить
                                                                    • а шо, там правда есть наследование?

                                                                      какой багор ))
                                                                      Ответить
                                                                  • > И кстати все три концепции можно выразить без ООП.

                                                                    Зачем тогда вообще ООП? Чтобы пердолиться с наследованием и думать которому из классов прикрутить метод?
                                                                    Ответить
                                                                    • А тебе, что, не нравится ебаться и пердолиться? Разве ты не программис? ;~;
                                                                      Ответить
                                                                      • В крестах ООП не так ярко выражено как в джаве. У нас тут свободные функции есть. Жаль, что полиморфизм на них не работает, конечно (хотя пропозал про мульти-методы где-то был), с ним ООП можно было бы вообще закопать. Вместе с костылями в духе визиторов-хуизиторов.
                                                                        Ответить
                                                                        • мультиметоды это выстрел себе в ногу в рантайме

                                                                          зачем они в крестах?
                                                                          Ответить
                                                                          • > зачем они в крестах?

                                                                            Чтобы визиторов не городить, как минимум.
                                                                            Ответить
                                                                              • Наследование работает когда у тебя фиксированный набор функций, а объектов дохуя и они добавляются.

                                                                                Визитор работает когда у тебя фиксированный набор объектов, а функций дохуя и они добавляются.

                                                                                Мультиметоды просто работают, и им не нужна вся эта ООПшная хуйня.
                                                                                Ответить
                                                                                  • > extensions

                                                                                    А нахуя в крестах этот псевдо-оопшный костыль? Там и так свободные функции есть.
                                                                                    Ответить
                                                                                    • экстеншены удобны для дискаверабилити.

                                                                                      Вот у меня есть петуз.
                                                                                      Что можно сделать с питузом?

                                                                                      Я пишу pituz.[space], и получаю список всех экстеншен методов из библиотек, и нахожу нужную.

                                                                                      Это позволяет мне быть дебилом, и вместо чтения документации жать пробел.

                                                                                      А автору экстеншена позволяет писать код в случайном месте, называть его случайным образом, и не документировать.
                                                                                      Ответить
                                                                                      • > дискаверабилити

                                                                                        Поиск по типам аргументов можно привернуть, как в доке по хаски. Будешь просто какой-то хоткей на переменной/типе жать вместо точки.
                                                                                        Ответить
                                                                                        • Можно, угу.

                                                                                          С другой стороны, разве не пиздато писать

                                                                                          10.times{} как в руби?
                                                                                          Ответить
                                                                                    • > А нахуя в крестах этот псевдо-оопшный костыль?

                                                                                      Чтобы визиторов не городить, как минимум. (c)
                                                                                      Ответить
                                                                                      • Экстеншены разве умеют резолвиться динамически, в рантайме?
                                                                                        Ответить
                                                                                      • А он поможет? Экстеншен ведь к конкретному классу метод прикручивает, он нихуя не полиморфный. Или это в c# так, а у вас можно ещё и к интерфейсу привернуть или новый интерфейс сбоку реализовать?
                                                                                        Ответить
                                                                                        • можно прикрутить и к интерфейсу (ну, протоколу в терминах эппла)
                                                                                          Ответить
                                                                                          • > Make an existing type conform to a protocol

                                                                                            Охуеть. Почти как в функциональщине, не то что в сраных джавах и сишарпах.
                                                                                            Ответить
                                                                                            • Это круто конечно, можно сделать свинью реализующей протокол "объект для жарки" вообще не трогая сам класс Pig.

                                                                                              Но как то поможет-то?

                                                                                              Или ты предлагаешь добавить экстененом метод в Livestock, и компилятор обяжет тебя реализовать его для ВСЕХ наследников?

                                                                                              А откуда он знает про всех, вдруг они в другой либе?
                                                                                              Ответить
                                                                                              • добавить экстеншеном интерфейс метода невозможно

                                                                                                только реализацию

                                                                                                ниже привёл пример, как сделать реализацию по умолчанию и для конкретного класса

                                                                                                честно скажу, что никогда так писать в настоящем проекте не приходилось)
                                                                                                Ответить
                                                                                            • >Почти как в функциональщине
                                                                                              или в скриптушне с обезъяньими заплатками

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

                                                                                              class String
                                                                                                def make_some_tea
                                                                                                  puts 'tea'
                                                                                                end
                                                                                              end
                                                                                              
                                                                                              def make_tea(tea_producer)
                                                                                                tea_producer.make_some_tea
                                                                                              end
                                                                                              
                                                                                              make_tea 'monkey patch'


                                                                                              Правда никаких интерфейсов тут нет, бо типизация струк утиная.

                                                                                              Но в отличие от экстеншенов, которые в Котлине (и полагаю, что и в C#) резолвятся в комайл тайме, и превращаются в обычные вызовы функций с первым аргументом, в Руби говно навешивается прямо внутрь самого класса.

                                                                                              зы: пздц конечно руби на винде шустрый, рубокоп три минуты мой код в три строки обсасывал
                                                                                              Ответить
                                                                                • именно по этому я за груви, там метод може диспатчиться в зависимости от типа объекта в рантайме
                                                                                  Ответить
                                                                              • У тебя есть интерфейс или абстрактный класс Livestock.

                                                                                У него есть две реализации: Rooster и Pig.

                                                                                У тебя есть логика, говорящая, что свинью нужно запечь, а петуха зажарить.

                                                                                Ты получаешь инстанс Livestock.

                                                                                Можно проверить его тип (цепочкой instanceof) и построить логику на этом.

                                                                                Но во-первых не всегда тип известен в рантайм, во-вторых можно случайно проебать один из типов (если в языке нет каких нить sealed classes для этого)

                                                                                Ты делаешь интерфейс Visitor с методами visitPig и visitRooster.
                                                                                Первый метод полуает Pig, другой Rooster.

                                                                                И реализуешь его.

                                                                                Далее, в Livestock ты делаешь метод visit, получаюший этот интерфейс.

                                                                                Pig реализует его вызывая visitPig(this)
                                                                                Rooster тоже соответственно.
                                                                                Ответить
                                                                                • Какой бройлерплейт на ровном месте )))

                                                                                  Именно поэтому я против "ООП".
                                                                                  Ответить
                                                                                  • Я ниразу не защищаю паттерн, просто рассказал, как он работает
                                                                                    Ответить
                                                                                  • Каким образом компилятор поймет, что указатель на Livestock на самом деле указывает на свинью?
                                                                                    Ответить
                                                                                      • Ну вот есть у меня Livestock и я не знаю свинья там или курица. Как мне позвать bake?
                                                                                        Ответить
                                                                                        • хм, ну концептуально это хороший вопрос

                                                                                          пока в голову пришло что-то такое

                                                                                          protocol Animal { }
                                                                                          class Cat: Animal { }
                                                                                          class Dog: Animal { }
                                                                                          
                                                                                          extension Animal {
                                                                                              func pet() {
                                                                                                  print("pet")
                                                                                              }
                                                                                          }
                                                                                          
                                                                                          extension Cat {
                                                                                              func pet() {
                                                                                                  print("pet cat")
                                                                                              }
                                                                                          }
                                                                                          
                                                                                          let c = Cat()
                                                                                          let d = Dog()
                                                                                          
                                                                                          c.pet()
                                                                                          d.pet()


                                                                                          выведет

                                                                                          pet cat
                                                                                          pet
                                                                                          Ответить
                                                                                          • А существующие Animal'ы не скомпилятся если им не прикрутить реализацию?

                                                                                            А тьфу, тут дефолтная сработала.
                                                                                            Ответить
                                                                                          • >let c = Cat()
                                                                                            в этом месте компилятор знает тип "c".

                                                                                            А теперь представим функцию, которая получает Animal.
                                                                                            Пусть тип "c" будет Animal.

                                                                                            Тогда сработает?
                                                                                            Ответить
                                                                                            • если ты работаешь с типом Animal, то вызов метода какого типа ты ожидаешь?)

                                                                                              но вообще к, сожалению, нет, так не сработает
                                                                                              Ответить
                                                                                              • > если ты работаешь с типом Animal, то вызов метода какого типа ты ожидаешь

                                                                                                Правильного. Ну как это работает с обычными виртуальными методами.

                                                                                                Ну понятно, всё-таки экстеншены как в C# сделаны, без динамического полиморфизма.

                                                                                                Но хотя бы интерфейс к существующему объекту привернуть можно, уже прогресс.
                                                                                                Ответить
                                                                                                • вот такое нагуглил мнение

                                                                                                  The short answer is that protocol extensions don't do class polymorphism. This makes a certain sense, because a protocol can be adopted by a struct or enum, and because we wouldn't want the mere adoption of a protocol to introduce dynamic dispatch where it isn't necessary.

                                                                                                  Структуры и энамы в Свифте наследование не поддерживают

                                                                                                  Возможно, поэтому не стали делать
                                                                                                  Ответить
                                                                                                • > как это работает с обычными виртуальными методами

                                                                                                  - в данном случае это и не виртуальные методы в общем
                                                                                                  Ответить
                                                                                                  • Угу, по сути просто свободная функция. В крестах это так бы выглядело:
                                                                                                    void bake(Animal& animal) { ... }
                                                                                                    void bake(Dog& dog) { ... }
                                                                                                    
                                                                                                    bake(cat); // animal
                                                                                                    bake(dog); // dog
                                                                                                    Ответить
                                                                                                    • выходит, что больше подходит такой вариант

                                                                                                      protocol Animal {
                                                                                                          func pet()
                                                                                                      }
                                                                                                      
                                                                                                      class Cat { }
                                                                                                      class Dog { }
                                                                                                      
                                                                                                      extension Cat: Animal {
                                                                                                          func pet() {
                                                                                                              print("pet cat")
                                                                                                          }
                                                                                                      }
                                                                                                      
                                                                                                      extension Dog: Animal {
                                                                                                          func pet() {
                                                                                                              print("pet dog")
                                                                                                          }
                                                                                                      }


                                                                                                      но это решение другой задачи 🙂
                                                                                                      Ответить
                                                                                                    • ещё так работает

                                                                                                      protocol Animal {
                                                                                                          func pet()
                                                                                                      }
                                                                                                      
                                                                                                      class Cat {
                                                                                                          func pet() {
                                                                                                              print("pet cat")
                                                                                                          }
                                                                                                      }
                                                                                                      
                                                                                                      class Dog {
                                                                                                          func pet() {
                                                                                                              print("pet dog")
                                                                                                          }
                                                                                                      }
                                                                                                      
                                                                                                      extension Cat: Animal { }
                                                                                                      
                                                                                                      extension Dog: Animal { }
                                                                                                      Ответить
                                                                                                    • Угу. экстеншены это просто сахар над обычными функциями (или статическими методами, как называли бы их ООПБляди)
                                                                                                      Ответить
                                                                                              • Я хочу построить свою логику в зависимости от типа.

                                                                                                Ко мне пришел Animal. Если это коза, то я делаю одно. Если корова, то другое.

                                                                                                Как мне это сделать?
                                                                                                Ответить
                                                                                                • protocol Animal { }
                                                                                                  
                                                                                                  class Cat: Animal { }
                                                                                                  
                                                                                                  class Dog: Animal { }
                                                                                                  
                                                                                                  class Duck: Animal { }
                                                                                                  
                                                                                                  class AnimalPetter {
                                                                                                      func pet<U>(animal: U) where U: Animal {
                                                                                                          print("Pet some animal")
                                                                                                      }
                                                                                                  }
                                                                                                  
                                                                                                  extension AnimalPetter {
                                                                                                      func pet(animal: Cat)  {
                                                                                                          print("Pet cat")
                                                                                                      }
                                                                                                      
                                                                                                      func pet(animal: Dog)  {
                                                                                                          print("Pet dog")
                                                                                                      }
                                                                                                  }
                                                                                                  
                                                                                                  let petter = AnimalPetter()
                                                                                                  petter.pet(animal: Cat())
                                                                                                  petter.pet(animal: Dog())
                                                                                                  petter.pet(animal: Duck())


                                                                                                  Pet cat
                                                                                                  Pet dog
                                                                                                  Pet some animal
                                                                                                  Ответить
                                                                                                  • Ну ты опять статически разрулил, заранее зная тип. Кастани их всех в Animal для начала и сложи в массив. А потом пройдись циклом и обработай.
                                                                                                    Ответить
                                                                                                    • ну задача-то решена

                                                                                                      логика построена в зависимости от типа, экстеншены присутствуют. каких развлечений вам ещё хочется?
                                                                                                      Ответить
                                                                                                    • > Кастани их всех в Animal для начала и сложи в массив.

                                                                                                      - ну вы просто как обычно формулируете условия задачи чанками
                                                                                                      Ответить
                                                                                                      • > ну вы просто как обычно формулируете условия задачи чанками

                                                                                                        Х.з., по-моему всё понятно было у МАКАКи: на входе Animal (а не конкретный тип).
                                                                                                        Ответить
                                                                                                        • ладно, я признаюсь, что был неправ, написать на экстеншенах (по крайней мере, в Свифте) эквивалент визитора нельзя, можно только его скосплеить
                                                                                                          Ответить
                                                                                                          • на всякий случай груви, например

                                                                                                            class Cat {
                                                                                                            
                                                                                                            }
                                                                                                            
                                                                                                            class Dog {
                                                                                                            
                                                                                                            }
                                                                                                            
                                                                                                            def pet(Cat cat) {
                                                                                                                println "prr"
                                                                                                            }
                                                                                                            
                                                                                                            def pet(Dog dog) {
                                                                                                                println "rraf"
                                                                                                            }
                                                                                                            
                                                                                                            def multi(animal) {
                                                                                                                pet(animal)
                                                                                                            }
                                                                                                            
                                                                                                            
                                                                                                            def animal = (System.currentTimeMillis() % 2 == 0) ? new Cat() : new Dog()
                                                                                                            multi(animal)
                                                                                                            Ответить
                                                                                                      • > формулируете условия задачи чанками

                                                                                                        Именно поэтому мы за «YAGNI».
                                                                                                        Ответить
                                                                                                  • А в какой строчке тут можно увидеть
                                                                                                    >Ко мне пришел Animal.
                                                                                                    ?

                                                                                                    В смысле где тут переменная типа Animal?
                                                                                                    Ответить
                                                                                      • Я не понял, какое отношение экстеншен методы имеют к визитору и мультиметодам и причем тут вообще они.
                                                                                        Ответить
                                                                    • Чтобы разрешать доступ к структурам данных только для определенных методов (что правда можно сделать через опак структуры)

                                                                      Чтобы требовать контракт для группы связанных функций (хотя это тоже наверное можно без ООП).
                                                                      Ответить
                                                                  • >В тайпскрипте можно изъебнуться
                                                                    interface Device<T extends number> {
                                                                        freq: T;
                                                                    }
                                                                    
                                                                    
                                                                    class Dev1 implements Device<42> {
                                                                        freq: 42 = 42;
                                                                    }
                                                                    
                                                                    class Dev2 implements Device<100500> {
                                                                        freq: 100500 = 100500;
                                                                    }
                                                                    
                                                                    class Collection<T extends number> {
                                                                        add(device: Device<T>): void {
                                                                    
                                                                        }
                                                                    }
                                                                    
                                                                    const coll = new Collection<42>();
                                                                    coll.add(new Dev1());
                                                                    // coll.add(new Dev2()); //не скомпилица


                                                                    на джаву не переводица
                                                                    Ответить
                                                                    • Этот тред про "PHP". Переведи на.
                                                                      Ответить
                                                        • Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом.


                                                          Файл в /proc является частным случаем (подтипом) абстрактного понятия "файл".

                                                          Функция "fopen" должна работать с файлами на /proc так же, как и с обычными.

                                                          Например, я могу открыть ``/proc/1/io``

                                                          Это и есть LSP.

                                                          Так вижу.
                                                          Ответить
                                                  • сущности тут это API.

                                                    В линукс есть, например, API для псевдотерминалов.

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


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


                                                    OCP, как и любой принцип и паттерн, говорит про очевидные вещи, которые ты используешь каждый день, просто не всегда знаешь, как они называются.
                                                    Ответить
                                    • >Сложный код – это когда нет комментариев

                                      Сложный код это кода:
                                      * Высока цикломатическая сложность
                                      * Высоко количество различных состояний системы
                                      * Высоко количество абстракций

                                      Первые два пункта усложняют понимание того, как поведет себя система при оперделенных входных данных.

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


                                      >А хороший код должен быть продуманным и следовать принципам SOLID.


                                      Безусловно. Лучше быть богатым и здоровым, чем бедным и больным.

                                      К сожалению, полностью продумать код ты можешь только если ты уже решил ТОЧНО ТАКУЮ ЖЕ задачу, да и то, только если в мире ничего не поменялось с последней версии (что вряд-ли)

                                      Но так не бывает, так что всё равно приходится что-то рефакторить.

                                      Именно потому водопад с его "давайте всё досконально продумаем, и за пять лет сделаем" был обоссан

                                      >Тогда зачем нужен
                                      Чтобы не тратить время на то, что не нужно прямо сейчас.

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

                                      Во-вторых ты заранее не можешь знать, что будет нужно.
                                      Результаты эксперементов иной раз бывают совершенно непредсказуемые и контринтуитивные.

                                      Ты тратишь время на интеграцию с FB, а потом оказывается, что 90% твоих пользователей хотят на самом деле ВК.

                                      Ты тратишь время на разработку клиента под Android, а потом оказывается, что 90% твоих пользователей используют ios.

                                      Ты не никак не мог этого ожидать, пока не увидел статистику.

                                      > не в том, чтобы добавить все фичи, а чтобы сделать процесс их добавления очень простым и быстрым.

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

                                      >Это, кстати, довольно легко организуется,

                                      Если бы это было так, то не нужен был бы ни рефакторинг, но инструменты для него.

                                      Люди с первого раза продумывали бы хорошие API, и потом писали бы под них плагины.
                                      Ответить
                                      • какой парадокс проектного менеджмента )))

                                        >Ты не никак не мог этого ожидать, пока не увидел статистику.

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

                                          К примеру, ты запускаешь веб версию, и видишь, что к тебе в основном заходят с айфонов, и делаешь выводы
                                          Ответить
                                            • Такая проблема тоже есть. Но у нас например маркетологи постоянно делают какие-то опросы, чтобы лучше понять кто наши пользователи, и чего они на самом деле хотят.
                                              Ответить
                                              • > чего они на самом деле хотят

                                                Чтобы любители опросов прошли нахуй.

                                                Хотя на 1-2 вопроса можно и ответить.
                                                Ответить
                                                • Как-то раз я проходил спонсорский опрос в онлайн игре, чтобы получить монетки для куриной фермы. Ответив на половину, он закрылся и меня послали нахуй: «Вы не являетесь целевой аудиторией этого опроса».
                                                  Ответить
    • Sendmail effect: Any complex technology which doesn’t come with documentation must be the best available.
      Ответить
      • Почти угадал. Ещё не купил, но первый по твоей ссылке приглянулся.
        Ответить
      • > Блядь, как же это говно тормозит-то!

        Это всё из-за YAGNI!
        Ответить
        • За окошком дождь и град. Это YAGNI виноват!
          Кошка бросила котят - Это YAGNI виноват,
          Зайку бросила хозяйка - Кто виновен, угадай-ка!
          Вот кончается доска У несчастного бычка,
          Наша Таня громко плачет - Рядом YAGNI, не иначе!
          Свет погас, упал забор, У авто заглох мотор,
          Зуб здоровый удалили Иль залез в квартиру вор,
          Не понравилось кино, Наступили вы в говно…
          У любого катаклизма Объяснение одно…
          Знает каждый технократ - Это YAGNI виноват!
          Кто вчера в моём подъезде Лифт зассал до потолка?
          Мне, товарищи, поверьте- Это YAGNI или DRY!
          Я поймал по пьяни «белку» - Это SOLID'a проделки!
          Куча под столом говна. Это PHP вина!
          Засорился унитаз - Это defecate-plus-plus приказ,
          Накидал туда бычков, Воду слил - и был таков!
          По ночам бельё ворует, Стёкла в нашем доме бьёт.
          Пьяным во дворе танцует. Это YAGNI - обормот!
          Нет спасенья от злодея! Джавой пишет на стенах,
          Изломал кусты в аллее. Это YAGNI - ох и ах!
          Программиста дождик мочит - YAGNI весело хохочет.
          Затопило вашу дачу? - Это SOLID, не иначе!
          Вас гроза в пути застала? - То рука YAGNÍ достала.
          Холод, ветер, снегопад - Снова YAGNI виноват.
          Сносит крышу ураганом? - Это linux мстит баранам.
          Шторм, цунами, наводненье? - Это YAGNI, без сомненья!
          Ливень, оползень, циклон - Виноват конечно он
          Сель, лавина, камнепад? - Ясно: YAGNI виноват!
          Смерч, тайфун, землетрясенье - Нет от singleton спасенья!
          В темя клюнула ворона? - это был адепт ООПа.
          KISSы, JITы жалят вас? - Это хипстерский СпецНаз.
          Видишь этого скрипта? - Он на службе у ЯГНЯ!
          Если верите в такое - Это здравый смысл и реалистичная картина мира, близкая к объективной истине.
          Ответить
  • Сегодня мы стали свидетелями феноменальной по своей крутости блокировки твиттера от РКН.

    Похоже, Роскомнадзор просто сравнивал адреса по подстрокам. И любые домены, которые содержали в названии «t.co», замедлялись. Поэтому «под раздачу попали» Microsoft.com, rt.com, Reddit.com, поддомены GitHub и другие сайты.

    Алгоритм незамысловатый. Уверены, что есть варианты «эффективней». Давайте попробуем придумать новый алгоритм для РКН. На будущее, так сказать.
    Ответить
  • https://twitter.com/ValdikSS/status/1369633722954379273?s=20

    Провёл больше тестов. Сравнение доменов происходит по подстроке, ищется строка “https://t.co” (короткий домен твиттера)
    Любой домен, содержащий в каком-либо месте строку https://t.co, замедляется.
    У Github — http://githubusercontent.com
    
    githubuserconten_t.co_m


    Ебать, я думал это шутка была.
    Ответить
    • Не стоит объяснять шуткой то, что можно легко объяснить долбоебизмом
      Ответить
    • В РКН тоже есть глупенькая лолечка, которая не умеет в рагулярки (;–;)
      Ответить
      • А провайдер, когда эту хуйню применял, ничего не заметил?
        Ответить
        • На Хабре, кстати, писали, что некоторые провайдеры ничего не замедляли.
          Ответить
          • Ну там изначально и заявлялось, что тормоза внесут для всех мобильных и некоторых проводных.
            Ответить
        • Дык таблицы автоматом прилетают, заметить можно только если специально тестировать или юзеры пожалуются.
          Ответить
          • Ну твиттер - это первый сайт, который попал в реестр замедлительных?
            Как можно было не заметить такую рагулярку? Или провайдеры тестировали не на нём?
            Ответить
            • Звездочки для доменов вроде давным-давно привернули. Просто до этого их юзали более-менее разумно.

              Так что саму регулярку могли и проглядеть. А замедляйку тестировали на своём каком-нибудь тестовом сайте.
              Ответить
            • Ну т.е., я думаю, что это не какой-то прям новый реестр, а просто новое действие добавили в существующую таблицу.

              Можно в доке по формату почитать, она открытая, в отличие от самого реестра. Звёздочки для доменов и маски для айпи там вроде больше года уже.
              Ответить
      • Я не уверен, что подстроку в строке нужно искать регуляркой: можно налететь на catastrophic backtracking и соснуть.

        Есть всякие Ахо-Карасики для этого.... хотя.... можно интересно реализовать их на регулярках?
        Ответить
        • > можно интересно реализовать их на регулярках

          Я сегодня узнал, что нет, нельзя, потому что в таблице на Википедии так написано.
          Ответить
            • А я тебя зачем-то наебал )))

              Наоборот, у тебя это получится (и очень даже легко), потому что и регулярки, и Ахо-Карасики – это finite state automata.
              Ответить
  • const c = something;
    switch (anything) {
        case 'ONE':
            const c = something_else;
        case 'TWO':
            /* используем цэ */
    }
    Какой конст )))
    Ответить
  • https://qna.habr.com/q/975871
    $article = mysqli_query($connection, "SELECT * FROM `articles` WHERE `id` = " . (int) $_GET[id]);
    if(mysqli_num_rows($article) <= 0 ){
      ?>
      <div id="content">
          <div class="container">
            <div class="row">
              <section class="content__left col-md-8">
                <div class="block">
                  <h1>Статья не существует!<h1>
                  <div class="block__content">
                    <div class="full-text">
                     Запрашиваемая вами статья не существует!
                    </div>
                  </div>
                </div>
              </section>
              <section class="content__right col-md-4">
                <?php require "includes\sitebar.php"; ?>
              </section>
            </div>
          </div>
        </div>
        <?php
      } else 
    {
        $art = mysqli_fetch_assoc($article);  
        mysqli_query($connection, "UPDATE `articles` SET `views` = `views` + 1 WHERE `id` = " . (int) $art['id']);
      ?>
      <div id="content">
          <div class="container">
            <div class="row">
              <section class="content__left col-md-8">
                <div class="block">
                  <a><?php echo $art['views'];?>Просмотров</a>
                  <h2><?php echo $art['title'];?></h2>
                  <div class="block__content">
                    <img src = "static/images/<?php echo $art['image'];?>" style="max-width: 100%;">
                    <div class="full-text">
                      <?php echo $art['text']; ?></div>
                  </div>
                </div>    
            <div class="block">
              <a href="#comment-add-form">Добавить свой</a>
                  <h3>Коментарии</h3>
                  <div class="block__content">
                    <div class="articles articles__vertical">
                      <?php

    Говорят, в аду для программистов их заставляют пять дней в няделю дебажить код ня PHP ..・ヾ(。><)シ.
    Ответить
    • Почему любой код на пхп -- вонючее говно, а любой программист на пхп -- тупой дебил?
      Ответить
    • Если вам интересна тема IT в Дагестане, то можете подключиться к любой из этих ссылок:


      Ну давайте посмотрим на каналы!

      > PHP Dagestan — телеграм-чат для PHP-разработчиков

      https://m.ok.ru/video/5446567231

      Название звучит как канал для пранков вольнова. Туда заходят дагестаняне, а потом звонят ему: «Лэээ саламалекум, это ты там пхп обсирал?»

      > А может на PHP ? — телеграм-канал для PHP-разработчиков

      Вы случайно не... ?

      > Dev Seagulls Fem — instagram страница женского дагестанского IT-сообщества

      Уже вступила туда? :з

      > Горский дизайн — телеграм-чат для дизайнеров

      Это надо было в одноклассниках такую группу создавать. Или там уже такое название занято?

      > Работа для дизайнера — телеграмм-канал

      Информативно )))

      > Работа в ИТ — телеграмм-канал c it вакансиями

      Линкедин? ХХРУ? Да пошли они гахуй, есть же чатик в телеге!

      > Легкие мемi на английском — мой телеграмм-канал с легкими мемами на английском для изучения языка

      Там, наверное, самые, блин, убогие на свете «мемi», которые только может увидеть человек в своей жизни.
      Ответить
    • Это реальная баба или очередная хастебка?
      Ответить
    • Чем меньше рейтинг наберёт этот комментарий, тем больше PHP говно. Голосуем.
      Ответить
    • Чем меньше рейтинг наберёт этот комментарий, тем больше PHP не говно. Голосуем.
      Ответить
    • Давайте подведём результаты голосования. "PHP" - не говно по мнению большинства.
      Ответить
  • Чрезвычайное проешествие!

    Оказывается, при чтении пароля с терминала нужно перевести его в raw режим, чтобы пароль не был виден! Про это написали целую статью!
    https://habr.com/ru/company/macloud/blog/566748/

    Стивенс ставит лайк
    Ответить
  • В интернете очень много устаревшей информации, которая приводит к заблуждению, распространению неверных решений и написанию плохого кода у начинающих PHP-разработчиков. PHP: Правильный Путь — легкочитаемое руководство для быстрого ознакомления с правилами эффективного использования PHP

    https://phptherightway.com/#mysql_extension

    <?php
    namespace Database;
    
    class Database
    {
        protected $adapter;
    
        public function __construct(AdapterInterface $adapter)
        {
            $this->adapter = $adapter;
        }
    }
    
    interface AdapterInterface {}
    
    class MysqlAdapter implements AdapterInterface {}


    <?php // user_profile.php ?>
    
    <?php $this->insert('header', ['title' => 'User Profile']) ?>
    
    <h1>User Profile</h1>
    <p>Hello, <?=$this->escape($name)?></p>
    
    <?php $this->insert('footer') ?>
    Ответить
  • В такие бухты хочется барахты.

    Так уж вышло, что приличное количество классных людей, которых я знаю, — из Владивостока. А ещё так получилось, что мой любимый стрит-фуд — главный на улицах Владивостока. Да и вообще, в Приморье живописные бухты, в которые можно сделать приятные барахты.

    Мы с ребятами сделали тест с уникальным гидом в конце и разыгрываем авиабилеты во Владивосток. Открой для себя новый Владивосток, как говорится в брошюрах.
    Ответить
      • О, порт с глазами синими,
        Родной Владивосток!
        Здесь Русь берет начало,
        А ты ее исток!

        Своей неколебимостью
        На краешке земли
        Хранишь ты Русь от ворогов,
        Как предки берегли.

        И моря синь играючи,
        Ласкает бережок.
        О, порт с глазами синими,
        Родной Владивосток!
        Ответить
        • Полоскала каргополочка белье.
          Стыли руки на морозе у нее.
          В полынье вода - не чай,
          Припевала невзначай,
          Чуть слетала песня та,
          Паром таяла у рта.

          На Онеге белый снег да белый лед.
          Над Онегой белый дым из труб идет.
          Дым идет белей белья
          Изо всякого жилья,
          Изо всякой мастерской -
          Прямо в небо день-деньской.

          Город Каргополь, он, город невелик!
          А забыть его мне сердце не велит:
          Может, он и мал слегка,
          Да Онега велика,
          Да немерены леса,
          Да без краю небеса.

          Так и вижу - на Онеге белый лед,
          Так и слышу - каргополочка поет.
          Пусть мороз лютует зло.
          Все равно у нас тепло.
          Грел бы душу лад да труд,
          Шел бы дым из наших труб.
          Ответить
            • там же отмазка, что основатели были virgins в бизнесе, а не эта ваша очередная пошлятина
              Ответить
        • Согласился бы стать первым человеком, побывавшим на Марсе, но без обратного билета?
          Ответить
          • Согласился бы подраться с казуаром за право быть самым сильным титулованным питухом? На подготовку к битве даётся 10 дней, битва будет идти до первого фрага.
            Ответить
            • А кто это? Битва на смерть, я так понимаю?
              Ответить
              • Казуары — крупные нелетающие птицы. Взрослые особи шлемоносного казуара достигают 1,5—1,8 метров высоты (некоторые особи могут достигать двух метров) и весят около 60 килограммов. Поэтому казуары — самые крупные птицы в Австралии и вторые по величине птицы в мире (после страуса).

                Мне кажется, у меня не будет шанса выжить.
                Ответить
                • Хочу уточнить. Я должен натренировать боисового питуха, или сам лично драться? Какой оружие можно использовать?
                  Ответить
          • Зависит исключительно от того, сколько SSDшек с няшками позволят взять.
            Ответить
            • Если дать человеку SSD с няшками, он будет някать неделю.
              Если дать ему графпланшетку, он будет някать всю жизнь.


              Отличный повод поучиться рисовать, благо отвлекать ничего не будет.
              Ответить
              • > отвлекать ничего не будет
                Ха. Мысли уровня "вот выйду на пенсию - отдохну".

                Явно же придётся строить колонию, охотиться на марсианских тушканов, топить печку. И эксперименты проводить ещё начиная со времени полёта.
                Ответить
                • И смотреть последние новости про вымирающую землю, попивая сок из марсианских яблок.
                  Ответить
                  • Слушая новости по "атомному радиоприёмнику" (чтобы это ни значило) если я верно помню последний рассказ "марсианских хроник"
                    Ответить
                      • Не блевота, а классика фантастики 60-х. Но правду говоря Бредбери не мой любимый писатель, хотя словом владел классно
                        Ответить
                        • > фантастики
                          с чего ты взял? только из-за сатирки про вьетнам?
                          Ответить
                          • На марсе дело происходит, ну

                            Я понимаю, кстати, почему он тебе не нравится. Там многовасто левой хуиты. Но в 60-е это было в духе времени
                            Ответить
                            • > На марсе
                              у меня от этого берроуз

                              > понимаю, почему он тебе
                              а вот тут обидно было
                              Ответить
    • Не понимаю я путешественников.

      Как для меня выглядит путешествие во Владивосток: богатый масквич выиграл билет, прошел анальное зондирование и досмотр урками в аэропорту (как в той песне про вертухая), прилетел в другой город, где живут такие же заёьпнные люди, ходят по говну и лужам, месят грязь. На небе ни облачка: оно просто монотонно серое, старые вороны и чайки клюют трупы крыс, которые сдохли от голода. Пенсионерки еле тащятся на почту России за пенсией, чтобы не сдохнуть с голода. Красноглазые студенты тоже пытаются не сдохнуть с голода: кто-то работает весь день на ногах заёбаннвй разносит листовки и пиццы блядские, кто-то пиздит богатых и отбирает у них вещи. На улицах пробки сплошные, в автобусах и метро давка, масквич едет полюбоваться на бухту, где бухие мужэки и их семейства бухают, едят шашлыки, орут и матерятся, курят, пердят, ссут в море, а срут за гаражами в 10 метрах от живописной бухты. На пляже битое стекло, мусор, говно, вода ледяная, недалеко кто-то моет машину в море.

      И вот маасквич стоит и ЛЮБУЕТСЯ красотами, пока вокруг него почти каждый человек думает о том, как бы ухватить пожрать, кого бы выебать в самые неожиданные отверстия, кому бы свернуть шею, где бы посрать/поссать и т.д. ...
      Ответить
      • 400 тысяч россиян живут на грани голода, а недоедают более 9 млн человек, сообщает телеканал "Дождь" со ссылкой на доклад Детского фонда ООН (ЮНИСЕФ).

        Организация подготовила свой доклад, основываясь на официальных данных Росстата.

        Как сказано в отчете, 400 тысяч россиян эксперты относятся к группе "экстремальной уязвимости". Этим людям приходится пропускать приемы пищи, ограничивать количество еды или не есть вообще из-за отсутствия денег или других ресурсов.

        8,8 миллионов россиян эксперты поместили в группу "умеренной уязвимости". То есть им приходится экономить и либо есть меньше, либо покупать низкокачественные продукты.
        Ответить
      • Ну что за пессимизм? Можно же путешествовать в места, где нет людей. Там обычно чисто, и никто не срёт.
        А в людные засранные места ездят не путешественники, а дуристы.
        Ответить
        • > где нет людей

          На луну? Хотя и там уже натоптали и мусора накидали.
          Ответить
          • Куда-нибудь, куда хотя бы час идти пешком. Если там кто-то и был, то мала вероятность, что он там сейчас. Лес, степь или середина реки подойдёт.
            Ответить
            • > мала вероятность, что он там сейчас

              А мусор от него есть.
              Ответить
        • > Можно же путешествовать в места, где нет людей.

          Зато там есть волки, которые хотят отгрызть кому-нибудь лицо, дикие собаки, которые как волки, насекомые, которые откладывают личинки под кожу и в глаза, рои ос-убийц, пауки, яд которых вызывает некроз и смерть за 30 минут, анальные змеи, мозговые паразиты, разъярённые казуары, беглые зеки, голодные жители-канибалы окрестных заброшенных деревень, ядовитые споры мозговых грибков... И это ещё далеко не всё, а если рядом есть вода, то там ещё больше всякой живности.
          Ответить
  • "PHP" - не говно. Только всё остальное говно. Это каждый *Govno знает.
    Ответить
  • А хуле так тихо сегодня? Говнокод всё?
    Ответить
    • Вот и приходится с самим собой пиздеть.
      Ответить
        • Конец месяца, все доделывают проекты, которые не успели доделать из-за сидения на говнокоде. Т.е. все проекты.
          Ответить
                • --у меня каникулы
                  --а у меня кутикулы

                  какой стерторизм
                  Ответить
                    • Надо к врачу сходить, а то тёлки не будут соглашаться кочан полоскать.
                      Ответить
                        • Плачет маленький людоед под пальмой. К нему подходит миссионер.
                          - Ну же, не плачь. Где твой папа?
                          - Я его скууушал...
                          - А мама где?
                          - Я её тоооже скууушал...
                          - Ну и кто же ты после этого?
                          - Сиротиииинушка...
                          Ответить
                            • Давайте анекдоты 1994-го года рассказывать

                              Анекдот_про_нового_руссково_и_ляляки
                              Ответить
                              • https://v1.anekdot.ru/an/an9512/951203.html

                                - Передайте, пожалуйста, талончик.
                                - У меня руки заняты, вот грузин стоит, он передаст.
                                - Слюшай, ти сам передаст, папа твой - передаст, и дэти твои
                                вырастут передастами!
                                Ответить
                                • -- Ваш билетик?
                                  -- Мой билетик.
                                  -- Ну ваш билетик?
                                  -- Ну мой билетик.
                                  -- Ну покажите его
                                  -- Ну купите себе, и смотрите
                                  -- Вы что, больной?
                                  -- А вы что, доктор?
                                  -- Я кондуктор
                                  -- А я сантехник
                                  Ответить
                                •  – Пропустите меня! Я с яйцами!
                                  – Все с яйцами.
                                  – Я с куриными!
                                  – Пропустите инвалида.
                                  Ответить
                                  • ЦРУ удалось узнать, что российские ракеты состоят из хуйни, пиздюлины, и объединяющей их поебени

                                    Причем все три части взаимозаменяемы
                                    Ответить
                              • знаешь анекдот про Насреддина и "спасибо тебе, жена"?
                                Ответить
                                  • не могу нагуглить текст

                                    смысл в том, что жена дала ему инжир вместо яблок, когда он собирался идти к какому-то вельможе, а тому что-то не понравилось и он начал бросать в Ходжу принесённые фрукты, ну а инжир мягкий и ушибов не оставляет

                                    вот Насреддин и бегал и орал "спасибо тебе жена"

                                    шутки за 40 девственниц
                                    Ответить
                    • Дорогой, сегодня твоя очередь гулять с Калигулой
                      Ответить

Добавить комментарий для bormand Отменить ответ

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8