Кресты / Говнокод #9356 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
#if defined( HPUX_11_31 )
#define BDYNAMIC_CAST( CLASS, OBJECT )  (( CLASS ) ( OBJECT ))
#else
#define BDYNAMIC_CAST( CLASS, OBJECT )  (dynamic_cast< CLASS >(( OBJECT )))
#endif

чуть кофе не похлебнулся.

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

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

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

  • а какая была причина? в хпух 11.31 чего то не хватает для работы dynamic_cast? типа rtti выключено или что?
    Ответить
    • да хер их знает что они там делали и чего им там не хватало.

      это из кода библиотеки, судя по которой, многим авторам там просто мозгов не хватает.

      я бы из того же места еще больше говна напостил, но я знаю что народ здесь на тонкости С++ не падкий. и говно там монументального характера.
      Ответить
  • > половина наших С++ профисианалов
    плюсану
    лично видел и переделывал говнокод вида
    class derived: public base {...};
    derived d;
    base * f() { return dynamic_cast<base *>(&d); }


    но вообще, что dynamic_cast, что const_cast - костыли, демонстрирующие неудачные архитектурные решения (либо незнание модификатора mutable)
    Ответить
    • container_type<value_type>::const_iterator iter = container.cbegin();
      while(iter!=container.cend())
          if(condition(*iter))
              do_something(const_cast<value_type&>(*iter++));
      Ответить
      • я не уловил. так а смысл тогда в контексте данный контейнер const делать? или это по религиозным (ака: стайл гайд) соображениям все констами обвешано?
        Ответить
        • Экстракт бреда, увиденного где-то и когда-то. Смысл уже потерян давно, но чует мой пушистый зад, что это больше религия, чем стиль.
          Ответить
      • по моему самое что ни на есть очередное доказательство "неудачные архитектурные решения"
        раз пользуют const_iterator, значит container константный, и нет возможности взять iterator
        но при этом пытаются засунуть value_type & значение в do_something - вывод - либо чудо-программист, писавший do_something не видит разницы между & и const &, либо всё-таки видит, и подсовывать константные вещи в него совсем не следует
        Ответить
    • mutable обычно тоже костыль. А в целом что каст что mutable делает одно и тоже.
      Ответить
      • class some {
        public:
            value_type get() const {  // const method here
                boost::mutex::scoped_lock lk(mutex_);
                // much shorter and clear than 
                // boost::mutex::scoped_lock lk(const_cast<boost::mutex &>(mutex_));
                return value_;
            }
            // ...
        private:
            boost::mutex mutable mutex_;  // always mutable 
            // ...
        };
        Ответить
        • как по мне, констность многих методов (как и объектов в контеске) есть говно. правильная констность во большинстве случаев и нужна только для того что бы создать временный объект как входной параметр при вызове метода (который по стандарту должен быть `const whatevertype &`).

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

          я честно говоря уже давно не напрягаюсь расставлением констов - потому что слишком часто потом приходится еще раз напрягатся и их убирать. (та же херня с protected/private.)

          в твоем случае мутабл мутекса, я бы точно это делал без конста. я бы еще и get() назвал get_with_lock() - что бы в глаза прыгало что локи вовлечены.

          ЗЫ оригинальный юз-кейс мутабла это внутренний кэш, который может менятся при вызове констного гет()а. ну да почти аналогично твоему примеру.
          Ответить
          • ну раз даже ты используешь whatever const & при передаче аргумента, то ты должен понимать, что ни к каким иным методам whatever, кроме как константным, ты обратиться не сможешь

            ну и "часто напрягаться и их убирать" - это подозрительно как то, очень
            если мы хотим почитать состояние объекта, а не пописать его состояние => нет проблем сразу его объявлять const, т.е. если метод с именем get_*, то практически наверняка он обязан быть константным

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

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

            > get() / get_with_lock() - что бы в глаза прыгало что локи вовлечены
            иногда нужно как раз чтобы не прыгало - чтобы внутренняя реализация не мозолила ничего, и пользователю этого метода не важно что происходит внутри
            Ответить
            • я вообщем согласен.

              > это действительно странно, ошибка проектирования?

              проектирование зависит от поставленых требований. даже после 2-3 лет в эксплуатации, требования меняются. это и влечет за собой что спроектированое нужно перепроектировать без полного переписывания софта.

              то что прежде считалось константным и/или "деталями реализации" потом часто становится именно тем местом где и начинается разработка новых фич.

              > ну раз даже ты используешь whatever const & при передаче аргумента

              я говорил о том что этот конст там по стандарту стоит - временные объекты ты ни как по другому не передашь. в роли этих временных объектов почти никогда не встретишь центральные/важные объекты программы - потому что они относительно тяжелые - только мелочевку, которую по дешевке можно плодить на стеке в неограниченых количествах.

              а если уж реч идет про центральные/важные объекты программы, то вот как раз тут я всей этой фигней с констами/прайвит/протектед и не страдаю.


              из недавних примеров. чудаки замутили новый модуль. дезайн - пальчики оближешь: все красиво/етц, абстрактные интерфейсы имеющие смысл, консты где надо, протектед/прайвит и все прочее. все грамотно. но. пол года спустя понадобилось добавить статистику утилизации/лайф-сайкла объектов - и вот тут веселуха началась: что бы красивый дизайн "не портить," все было обвешено где только можно френдами и const_cast'ами и даже кто-то про мутабл вспомнил в паре мест. а как по мне - в жопу дезайн который теперь больше не подходит: в паре десятков мест убрать консты и прайвиты/протектеды, и спокойно инкрементить счетчики/вычитывать статистику из внутреннего представления. потому что это внутренее представление уже не есть личное дело класса: оно уже наружу выставлено статистикой.

              вообщем, я с тобой не не согласен. мы просто про те же самые вещи с разных точек зрения говорим. 🙂
              Ответить
              • > private/protected не страдаю
                и снова я в смущениях

                не буду лезть в чужую кухню или тем более чему то поучать
                наверное, самое первое приходящее на ум для лайф-сайкла объекта - class some: public virtual stat, ... { ... } не подошло
                Ответить
                • то что я хотел сказать. народ часто слишком сильно зацикливается на дизайне, а потом все что в дизайн не подходит, но реализовывать надо, делается через Ж - потому что "в дизайн не подходит ну и фиг с ним."

                  дизайн он как вера - в "религия против идеи" (если кто кино Догма помнит): идею поменять легко, поменять религию намно сложнее.
                  Ответить
                  • <много текста>

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

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

                    безусловно, у исходников на любом языке и при любой парадигме есть свой жизненный цикл, и плох тот программист, который смотрит на свой код 5 летней давности и не видит в нем плохих мест
                    я и сам много проектов на C89 делал, доводилось - в той же процедурной парадигме у долгоживущего проекта, регулярно раз в квартал обрастающего всё новыми фичами, наступает момент, когда статических и глобальных переменных уже настолько много, что безумно хочется треть проекта переделать с чистого листа - так что костыли случаются при любой парадигме
                    Ответить
                  • и твои затирания private/protected/const - всё те же костыли, безусловно костыли, которые иногда продлевают жизнь негодной структуре, а иногда являются свидетельством того, что программист не осилил годную структуру, снес пару несущих стенок и пристроил ненужный деревянный сарай

                    сам же жалуешься, что ваши С++ профессионалы не осилили динамик-каст/конст-каст, может это как раз и второй случай

                    я не знаю насколько там у вас всё многопоточненько, я бы никогда не рискнул грязными пальцами залезть в приватные члены объекта и прочитать оттуда неконсистентные данные, я бы спросил у этого объекта - а скопируй ка мне, милок, атомарно всю ту инфу, которая мне нужна

                    и если бы в изначальном дизайне этих счетчиков не было бы совсем - я бы их вообще вынес в отдельную сущность stat - наследованием или параметром - пусть объект самостоятельно модифицирует то, что ему нужно и когда ему нужно, а я потом этот stat почитаю атомарненько методом get() const

                    > идею поменять легко - раз уж взялись за гуж ООП, так осиливайте

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

                        вот такая вот она жизнь
                        Ответить
                        • да.

                          на самом деле бесит, то как оно у меня сейчас на фирме.

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

                          я (в суппорте) переделать на нормально не могу, потому что в С++ программах это влечет за сабой перекомпиляцию всего проекта с последующим гигантским размером нового патч левела.

                          по крайней мере у меня в суппорте есть свобода мелкими порциями это делать. в R&D им (официальным языком) просто не дают бюджета на это. и им самим дефекты себе открывать запрещено. нет дефекта - не можешь вчекинть - всего хорошего.
                          Ответить
                          • я вообще если честно слабо представляю, как на ООП в С++ можно сделать хороший продукт, способный обновляться "частично" - разве что сообщаться между модулями голыми интерфейсами (привет, СОМ?), модули делать высокогранулярными - практически один класс = один модуль, тотально положить хер на шаблоны (иначе не взлетит) - ну и в итоге получить вместо C++ дай бог уютную джаффку, но скорее с попоболью вселенского масштаба

                            ну еще, наверное, вариант побитового diff .dll/.exe между версиями

                            как хорошо, что каждый наш софт не занимает N гигов и обновляется в автоматическом режиме по принципу "о, апдейт!" -> "удаляем всё старое нахер" -> "ставим новую версию нахер"
                            Ответить
                            • > ставим новую версию нахер
                              Инсталляция новой версии продукта на хер успешно завершена!
                              Ответить
                              • кстати милый микрософт сильно напряг в свое время со своей невозможностью в msi устанавливать предыдущую версию того же продукта
                                казалось бы, кому какое дело - удали старое никому не нужное да установи что просят, скотина бездушная
                                приходится в екзешник оборачивать, который сам ищет, стоппит, удаляет, чистит, запускает msi
                                Ответить
          • Констаность, разумеется, нужна.

            "Напрягаться и убирать" - это не проблема констанности, а проблема автора кода, который не понял, какая идея константности была реализована (т.е. логическая, физическая, или что-то посередине), поленился в этом разобраться и вместо этого просто сносит все нафиг. Это просто банальная лень, на какое-то "говно" в константности.
            Ответить
  • Простите, что? Если там не самом деле нужен был 'const_cast', что ваш код не мог компилировться в принципе - 'dynamic_cast' не покрывает функциональности 'const_cast', т.е. для сноса константности использован быть не может. Если у вас 'dynamic_cast' работал в роли 'const_cast', то эт означает, что у вас - кривой компилятор. Ну а с кривым компилятором иногда и не так извращаться приходится...
    Ответить
    • это я слегка переупростил то что там код делает. там где этот дефайн больше всего используется (и для этого модуля этот #if вводили), код преимущественно выглядит приблизительно так:

      const ClassIntf *a;
      ClassImpl b = *BDYNAMIC_CAST( ClassImpl *, a );


      ну да модуль не мой. к счастью.
      Ответить

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

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

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


    8