Яuбy / Говнокод #27327 Ссылка на оригинал

0

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

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

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

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

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

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

        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 семантикой, и будет совсем хорошо
                                  Ответить
                              • Нужен синтаксис. Просто указатель будет путаться с placement new. Зная комитет, скорее всего будем вызывать как new(deep_copy_v, T*)

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

          Правда явно выбирать что и как захватывать вроде бы можно только в крестах (и еще в одном помоечном языке, который я не знаю)
          Ответить
        • Что-то как-то у тебя слишком не функционально.
          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
          Ответить
        • Да я просто вспомнил сишный код, где автор юзал тернарник и запятую чтобы не писать иф и скобочки.
          Ответить
              • Эм, пофиксили же вроде? Или это уже пасхалку запилили по мотивам того бага с клоудфларой?
                Ответить
                • Если перезагрузить страничку, то на мгновение, я вижу то самое... Такое мне не по нраву...
                  Ответить
                  • Потому что cloud flare защищает его персональные данные (мыло).
                    Ответить
    • Пятый курс лаба

      @

      if a not == 42: ...

      @

      traceback (most recent call last):...

      @

      недовольно урчиш
      Ответить
    • На руби вообще заебись

      В MRI давеча джита завезли. Теперь поди и змеюка у него отсасывает
      Ответить

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

Из-за тебя ушел bormand, guest!

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


    8