1. Ruby / Говнокод #27327

    +1

    1. 1
    page < records.total_pages ? next_page_exist = true : next_page_exist = false

    очевидное должно быть очевидны

    Запостил: AlexKlim, 29 Марта 2021

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

    • Чувак узнал про тернарник и решил его использовать. Что тут такого?
      Ответить
      • пс пс
        чувак
        next_page_exist = (page < records.total_pages)
        Ответить
        • Это, конечно, хорошо, но я не вижу здесь тернарника. Выглядит скучно и уныло, как будто этот код писал заедушный дед-програмиист.

          Вообще я бы написал вот так (недавно узнал про лямбды):

          auto lamblia = [record, &next_page_exists](const unsigned&& page) -> void { 
              (page < records.total_pages) ? (next_page_exist = true) : (next_page_exist = false);
          };
          lamblia(page);
          Ответить
          • А теперь представь, что будет если он узнает о шаблонах проектирования и всяких там фабриках-хуябриках...
            Ответить
            • Ну вот можно переписать с использованием паттерна проектирования "шаблонный метод" и с обобщенным программированием.
              В некотором смысле тут есть и паттерн "стратегия", потому что логика инкапуслирована в класс.

              Мой вариант тренарника:
              #include <vector>
              #include <iostream>
              
              template <class T>
              class useful_class
              {
              protected:
              	useful_class() = default;
              
              	virtual size_t page() const = 0;
              	virtual const std::vector<T>& total_pages() const = 0;
              public:
              	useful_class(const useful_class<T>& other) = delete;
              	useful_class(useful_class&& other) noexcept = delete;
              	useful_class& operator=(const useful_class& other) = delete;
              	useful_class& operator=(useful_class&& other) noexcept = delete;
              
              	bool next_page_exists() const noexcept
              	{
              		return page() < total_pages().size();
              	}
              
              	operator bool() const noexcept
              	{
              		return this->next_page_exists();
              	}
              
              	virtual ~useful_class() = default;
              };
              
              
              class my_useful_class_impl final : public useful_class<int>
              {
              	const std::vector<int>& m_vec;
              protected:
              
              	size_t page() const override
              	{
              		return 2;
              	}
              
              	const std::vector<int>& total_pages() const override
              	{
              		return this->m_vec;
              	}
              
              public:
              	my_useful_class_impl(const my_useful_class_impl& other) = delete;
              	my_useful_class_impl(my_useful_class_impl&& other) noexcept = delete;
              	my_useful_class_impl& operator=(const my_useful_class_impl& other) = delete;
              	my_useful_class_impl& operator=(my_useful_class_impl&& other) noexcept = delete;
              
              	explicit my_useful_class_impl(const std::vector<int>& vec): m_vec(vec)
              	{
              	}
              
              	~my_useful_class_impl() override = default;
              };
              
              int main() noexcept
              {
              	std::vector<int> foo{};
              	foo.insert(foo.begin(), 1);
              	foo.insert(foo.begin(), 2);
              	// foo.insert(foo.begin(), 3); //Uncomment to make true
              	std::cout << std::boolalpha << my_useful_class_impl{foo};
              	return 0;
              }
              Ответить
              • > useful_class() = default;
                Такие конструкторы лучше делать constexpr T() noexcept (если все инициализаторы членов соответствуют), чтобы можно было безболезненно наследовать constexpr-классы.

                > bool next_page_exists() const noexcept
                > operator bool() const noexcept
                page() и total_pages() не объявлены как noexcept, поэтому лучше noexcept убрать (иначе залётное исключение из page() мгновенно убьёт весь процесс).

                > ~my_useful_class_impl() override = default;
                Это можно не писать, неявные деструкторы классов-наследников виртуальные по умолчанию (если у класса-предка есть виртуальный деструктор).

                > foo.insert(foo.begin(), 1);
                foo.push_back() сначала 2, потом 1?
                std::vector<int> foo = { 1, 2, /* 3 */ /* Uncomment to make true */ }; ?
                Ответить
                • > std::vector<int> foo = { 1, 2, /* 3 */ /* Uncomment to make true */ }; ?

                  std::vector<int> foo { 1, 2, /* 3 */ /* Uncomment to make true */ }; ?
                  Ответить
                • Полина "статический анализатор" Аксёнова:)
                  Спасибо.

                  >constexpr
                  всё время забываю(

                  >е объявлены как noexcept
                  надо бы объявить. Хотя я не уверен на счет гарантий у размера у вектора

                  >неявные деструкторы классов-наследников виртуальные по умолчанию
                  Я не настоящий крестовик, так что мне спокойнее всё писать явно: удалять все ненужные конструкторы и объявлять все нужные деструкторы.. Хотя наверное хря

                  >сначала 2, потом 1?
                  ну это разве важно?:)

                  > std::vector<int> foo = { 1, 2, /* 3 */ /* Uncomment to make true */ }; ?
                  да, с инициализатором расивее, спасибо
                  Ответить
                  • > на счет гарантий у размера у вектора

                    По стандарту noexcept там, не сцы. Да и интуитивно size() -- это просто число или разность джвух указателей. Нечему бросать исключения.
                    Ответить
                    • тогда нужно везде noexcept расставить

                      В следующей версии своего объектно-ориентированного фреймворка для создания тренарников обязательно так сделаю. В платной версии
                      Ответить
                      • > тогда нужно везде noexcept расставить
                        Это полезно, но для базовых классов/интерфейсов noexcept — очень "сильный" модификатор, его нужно ставить с осторожностью. С ним наследники должны в обязательном порядке ловить и обрабатывать, например, std::bad_alloc на каждой аллокации (стандартных контейнеров, std::make_***(), ...), а это далеко не всегда удобно.
                        Ответить
                        • А зачем ловить bad_alloc? Кажется, что если у тебя кончилась память, то уже ничего не поделаешь кроме совсем уж необычных кейсов, когда ты строишь логику в зависимости от доступности свободной памяти?

                          В общем можно просто сдохнуть при bad_alloc?
                          А что будет, если я обману: скажу noexcept, а кину bad_alloc?
                          Какой=то десктруктор может не вызваться?
                          Ответить
                          • > зачем ловить bad_alloc

                            В гугловском кодестайле так и предлагается, насколько я помню. Упало -- да и хуй с ним.

                            Но в общем случае каким-то проектам нужно переживать временное out of memory.
                            Ответить
                            • >переживать временное out of memory.
                              Я это и назвал "строишь логику в зависимости от доступности свободной памяти".

                              Это сильное колдунство кмк:)
                              Ответить
                              • Ну почему колдунство? Вот есть у тебя обработчик каких-то запросов от юзера. Ловишь в нём все исключения. Если память совсем уж не потекла, рано или поздно тяжёлые запросы сдохнут и всё восстановится. Ну какие-то невиновные запросы тоже пострадают, да. Но это не фатально.
                                Ответить
                                • > Вот есть у тебя обработчик каких-то запросов от юзера. Ловишь в нём все исключения.

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

                                  Поля хороший пример привела с вебсервером. Жабаёбы тоже примерно так делают: ловить NPE например вообще-то не нужно обычно, но если ты контейнер сервлетов то можно и поймать, и вернуть 500.
                                  Ответить
                          • > Какой=то десктруктор может не вызваться?

                            Никакой не вызовется, емнип. Будет сразу std::terminate.
                            Ответить
                          • Например, если это (веб-)сервер, то в нём может стоять catch (const std::exception & ex) { send_response(500, ex.what()); }. В обычной ситуации высранный где-то std::bad_alloc просто поднимается вверх по стеку, и пользователь получает простое 500. А вот необработанное исключение в noexcept-методе безусловно и мгновенно убьёт процесс целиком, и пользователь увидит грустное ECONNRESET.
                            Ответить
                            • Да, веб-сервер (и вообще платформа для плагинов, например far, лол) это годно.

                              Но если я не делаю что-то для "внешнего кода", "для сторонних разработчиков" то наверное я не должен ловить bad_alloc .

                              Если конечно я не пытаюсь как-то "переживать временное out of memory", как говорил Борманд
                              Ответить
                              • Чем дальше идёт, тем более бородатым консерватором в плане администрирования (написания кода с точки зрения администрирования?) я становлюсь. Как медведев, блядь

                                Нужно чтобы каждый плагин жил в своем процессе и работал по IPC.
                                Словил сегфолт? Мне похуй.
                                Пытаешься передать структуру с левыми ссылками? Мне похуй, у меня свой address space.
                                Конфликт зависимостей? Мне похуй, вот тебе отдельный процесс, впендюривай туда какие хочешь версии библиотек и никакой хуйни с конфликтами плагинов.
                                Выжрал памяти? Мне похуй, а еще мне issues не будут засирать что это моя платформа видите ли много жрет.
                                Ответить
                                • Ну ты сейчас до микроядра доеберешься же:)

                                  В целом конечно ты прав (и тред такой есть), но IPC не бесплатен. В чужое адресное пространство ходить (не через шаред мемори а через сокеты/пайпы) это МОЖЕТ БЫТЬ медленно.
                                  Ответить
                                  • Да, я понимаю. Но представь как прекрасна жизнь без RCE выполнения чужого кода.

                                    Там еще когда-то language server для иде хотели реализовывать, эх.
                                    Ответить
                                    • Кроме перформанс пинальти есть еще одно лукавство: падение одного питуха (пусть и в своем адресном пространстве) может сделать остальных петухов ненужными.

                                      Ну вот выселил ты клиента СУБД в отдельный процесс и общаешься с ним асинхронными месседжами. Заебись же!

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

                                      В целом же снова посылаю тебя к блеску и нищете микроядер, харда и пр:)
                                      Ответить
                                      • Клиент сам по себе не помер. Клиент это либо часть плагина, и тогда это проблемы плагина, либо неотъемлемая часть основного приложения.

                                        А в целом если основное приложение знает какие у него плагины, то просто перезапускает процесс и не течет
                                        Ответить
                                        • Если перезапуск поможет, то да.

                                          В тред приглашается Снаут с рассказом про акторы в эрланге
                                          Ответить
                                          • А вообще я в целом это больше не про пирформансные приложения, а про всякую хуйню типа configuration manager, где какой-нибудь apt upgrade по пятнадцать минут выполняется и всем похуй. Там-то как раз этого говна с совместимостью выше крыши, ты либо с системд руками работаешь, либо с аптом, потому что у них пересекаются зависимости и типа идите нахуй.

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

                                            Передаю слово: https://www.youtube.com/watch?v=HyiSYHfESX4 (мотайте на 17:55) Там в общих чертах говорится про акторы и let it crash.
                                            Клиент субд в отдельномых процессеах используется сплошь и рядом. Если клиент покрашится, в простейшем случае он тупо утянет за собой процесс, который его использует, через link, web-server, создавший процесс, это задетектит и вернёт 500.
                                            Ответить
                                      • > он взял, да и помер

                                        Ну ребутнётся, делов то. Супервизор же у него какой-то есть. Да и репликацию никто не отменял.
                                        Ответить
                                        • >ребутнётся
                                          Если это поможет. А если он не поднимица обратно?

                                          >репликацию
                                          Это можно, но это нужно делать. Упал питеху, другой поднял его знамя
                                          Ответить
                                          • > А если он не поднимица обратно?

                                            Проблемы пхпшника, нарисовавшего плагин + exponential backoff на попытки поднять
                                            Ответить
                                            • Да вообще проблемы любого гондона, который например место для логов засрал, например
                                              Ответить
                                              • Да, но тут источник гораздо очевиднее, чем в классическом "напихаем говна в дженкинс всмысле 500"
                                                Ответить
                                        • > Супервизор же у него какой-то есть.

                                          О, даешь кодогенерацию на языке программирования «‎systemd service»‎. Серьезно, пуусть качает плагин по имени, засовывает его системд-сервисом в .config/systemd/user/ и вообще ничего не знает про проблемы супервизора. Нужно отключить плагин? Выключил сервис системд да и делов.
                                          Ответить
                                          • Зачем вообще делать дерьмодемона, когда есть inetd?

                                            Кстати, systemd еще и сокет умеет за тебя сделать. Скоро в ядро systemd еще и интеграцию с твиттером прикрутят. Сейчас systemd не работает без dbus, а скоро без аккаунта в твиттере рабоатть не будет
                                            Ответить
                                            • Дак dbus еще и проблему с дискавери решит. Плагин запустился и сразу видит куда ему стучать.
                                              Ответить
                                              • Совершенно верно. Там можно регистрировать интерйфейсы, как в polkit сделано.

                                                Милениалы в конце концов изобретут DCOM. Так им и надо
                                                Ответить
                  • > удалять все ненужные конструкторы
                    Это правильно. Опытные крестовички (ударение по ситуации) знают, что у базового класса обязательно надо удалять дефолтные конструкторы копирования/перемещения, иначе потом кто-нибудь скопирует объект через ссылку на родителя и получит огрызок объекта.

                    > ну это разве важно?:)
                    Не знаю, я не вникала, на кой ляд тебе эта эмуляция push_front(...) через insert(begin(), ...) сдалась, но я в чужие дела не лезу, хочешь вставлять в начало, значит есть зачем.
                    Ответить
                    • Вот почему комитет вместо решения архиважных вопросов, как назвать и какой интерфейс сделать у фунцкии вычисления третьей производной от функции двух аргументов, не сделает функцию clone(), которая будет брать указатель (и аллокатор/memory_resourse при необходимости) и создавать копию реального объекта? Да, это будет использовать RTTI, да, это будет работать только для класов с виртуальными функциями, да, таблица с информацией об классе растолстеет на 8 байт. Но кучу самописных clonable это уберёт.
                      Ответить
                      • Уточните, вы хочете поверхностное или полное копирование?
                        Ответить
                        • Копирование конструктором копирования реального класса объекта.
                          //Предположим, оба класса нормально прописаны и равенство у них транзитивно
                          struct A {/**/};
                          struct B: A {/**/};
                          //...
                          B x;
                          B y(x);
                          assert(x == y); // Если это верно
                          A* x_ptr = &x;
                          A* z_ptr = clone(x_ptr);
                          assert(*dynamic_cast<B*>(b_ptr) == y); // То и это должно выполняться и не кидать исключений.
                          Ответить
                          • Я анскильный, потому не очень понимаю куда именно скопируется x_ptr и где создастся то, на что указывает z_ptr.

                            Алсо, я не понимаю как наследник A может дать или не дать свое согласие на копирование
                            Ответить
                            • > куда именно скопируется x_ptr
                              Куда говорит его хранить аллокатор. Аллокатор по умолчанию в С++ выделяет память оператором new.

                              > на что указывает z_ptr
                              На вновь созданный объект. Фактически это было бы эквивалентно
                              А* z_ptr = new typeid(*x_ptr)(*x_ptr);
                              если бы так можно было делать.

                              Объявить clone можно было бы как
                              template <typename T, typename Alloc = std::allocator<T>>
                              T* clone(T* ptr, Alloc a = Alloc());
                              Ответить
                              • То есть по сути это
                                * узнать через RTTI какой это объект
                                * создать в куче этот объект и вызвать у него копирующий коснтруктор, передав туда A, скащенный в нужный объект?

                                Звучит логично, но не очень понятно что делать, если объект (или один из его предков) копирования не позволяет

                                Алсо, а поинтер на кучу будет какой? Умный, або обычный? In the latter case его нужно явно delete потом?
                                Ответить
                                • > Звучит логично, но не очень понятно что делать, если объект (или один из его предков) копирования не позволяет
                                  В духе остальной стандартной библиотеки — кидать исключение.

                                  > Алсо, а поинтер на кучу будет какой? Умный, або обычный?
                                  В идеале, сделать перегрузки для всех стандартных указателей. Какой засунул — такой и получил. В крайнем случае, полученный сами обернут, чтобы вручную не удалять.
                                  Ответить
                                  • Пнятно. Еще такой же нужен с move семантикой, и будет совсем хорошо
                                    Ответить
                              • Может быть как копирующий new эту фичу оформить?
                                Ответить
                                • Нужен синтаксис. Просто указатель будет путаться с placement new. Зная комитет, скорее всего будем вызывать как new(deep_copy_v, T*)

                                  Хотя всем остальным видам new нужно явно указывать тип. Не подходит.
                                  Ответить
                                  • Ну std::deep_copy и std::shallow_copy -- норм идея так то. Она даже для клона будет полезна если хочется дефолтное поведение для deep copy переопределить.
                                    Ответить
          • Остроумно. А с помощью Hadoop можешь решить?
            Ответить
          • Кстати, в этом есть некоторый флёр рубизма.
            Рубисты любят лямбды и даже по массиву итерируются блоком.

            Правда явно выбирать что и как захватывать вроде бы можно только в крестах (и еще в одном помоечном языке, который я не знаю)
            Ответить
          • Что-то как-то у тебя слишком не функционально.
            auto isPageLessThenTotalPages = [](const auto & page, const Record & record) constexpr -> bool {
                    return static_cast<decltype(record.total_pages)>(page) < record.total_pages;
                };
            
                auto isPageLessThenTotalPagesPredicateFactory = [&isPageLessThenTotalPages](
                    const auto & page, const Record & record
                ) constexpr -> auto {
                    return [&]() constexpr -> bool {
                        return isPageLessThenTotalPages(page, record);
                    };
                };
            
                auto nextPageExistsTrueAssigner = [&genericAssigner, &trueAssigner, &next_page_exists]() constexpr -> void {
                    trueAssigner(genericAssigner, next_page_exists);
                };
            
                auto nextPageExistsFalseAssigner = [&genericAssigner, &falseAssigner, &next_page_exists]() constexpr -> void {
                    falseAssigner(genericAssigner, next_page_exists);
                };
            
                auto lambliaFactory = [&record,
                                       &conditionalInvoke,
                                       &isPageLessThenTotalPagesPredicateFactory,
                                       &nextPageExistsTrueAssigner,
                                       &nextPageExistsFalseAssigner](
                    const auto & page
                ) constexpr -> auto {
                    return [&]() constexpr -> void {
                        conditionalInvoke(isPageLessThenTotalPagesPredicateFactory(page, record),
                                          nextPageExistsTrueAssigner,
                                          nextPageExistsFalseAssigner);
                    };
                };
            
                lambliaFactory(1)();
                std::cout << std::boolalpha << next_page_exists << std::endl;
            
                lambliaFactory(2)();
                std::cout << std::boolalpha << next_page_exists << std::endl;

            Полный код: https://wandbox.org/permlink/vmVy2nsvDAkcUjeI
            Ответить
            • Полина, пошли пить клубличное молочко.
              Ответить
              • guest6 обвиняется в харрасменте.
                Ответить
              • Загадка для детей:

                Пил с Полиной молочко,
                А теперь болит <_ _ _ _>.



                Отгадка:

                ...                                                  
                                                                                                                      мозг, т.к. Полина рассказала что-то про кресты uwu
                Ответить
              • молочко плюс
                Ответить
    • У этого паттерна есть название: boolshit.
      Ответить
      • Да ещё и побочный эффект в тернарнике...
        Ответить
        • Починил
          next_page_exist = (page < records.total_pages ? true : false)
          Ответить
          • Да я просто вспомнил сишный код, где автор юзал тернарник и запятую чтобы не писать иф и скобочки.
            Ответить
            • Напитон похоже:
              page < records.total_pages?
                  next_page_exist = true
              : //else
                  next_page_exist = false
              Ответить
              • Почему ты [email_protected]?
                Ответить
                • Эм, пофиксили же вроде? Или это уже пасхалку запилили по мотивам того бага с клоудфларой?
                  Ответить
                  • Если перезагрузить страничку, то на мгновение, я вижу то самое... Такое мне не по нраву...
                    Ответить
                    • Потому что cloud flare защищает его персональные данные (мыло).
                      Ответить
    • next_page_exists = !true
      Ответить
      • Пятый курс лаба

        @

        if a not == 42: ...

        @

        traceback (most recent call last):...

        @

        недовольно урчиш
        Ответить
    • Переведи на "PHP".
      Ответить

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