1. C++ / Говнокод #6021

    +167

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    PopupWindow* GameLocations::getCurrentPopup()
    {
    	if(m_curPopup != nullptr && m_curPopup->needsClose())
    	{
    		m_curPopup->onClose();
    		m_curPopup = nullptr;
    		m_walker->BeginWalk(m_graph->getClosestNode(m_currentLocationId));
    	}
    	return m_curPopup;
    }

    Запостил: Kirinyale, 18 Марта 2011

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

    • И?
      Ответить
      • Вы привыкли к "тривиальным" геттерам с побочными эффектами, влияющими на игровую логику? Сочувствую.
        Ответить
        • Бредом попахивает.

          Задача "геттеров" и "сеттеров" - разделение интерфейса и реализации. А какую реализацию они там внутри себя инкапсулируют - это никого не касается и не интересует. Тут не к чему "привыкать" или "не привыкать". Вам дали "геттер" и сказали что он делает и чего он не делает с точки зрения интерфейса и "влияния на игровую логику" (которого, кстати, из примера не видно). Все остальное вас не касается. Пользуйтесь "геттером" правильно, и все у вас будет хорошо.

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

          А если у вас с этим возникли какие-то проблемы, то давайте более полный контекст. Но я подозреваю, что ваши проблемы вызваны в первую очередь вашими же выдуманными ожиданиями, которые вы почему-то накладываете на "геттеры".
          Ответить
          • 7-я строчка примера означает, что если мы спросили "открыта ли сейчас какая-нибудь локация", а она как раз недавно закрылась, то наш персонаж внезапно начнёт куда-то идти (неважно, куда именно). Зачем? Кто разрешил? Почему ходьба начинается в совершенно постороннем геттере? Где причинно-следственная связь и в чём здесь заключается абстрактный реализационный паттерн? "Ленивые вычисления" не предлагать. Если бы дело было лишь в отложенном закрытии окна, это ещё можно было бы с натяжкой назвать нормальным. Хотя, вообще говоря, этим следует заниматься в совсем другом месте (например, в пофреймовом update владельца окна), потому что никто, строго говоря, не гарантирует, что геттер обязательно будет вызван вскоре после того, как окно захотело себя закрыть.

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

            А практика, кстати, показывает, что проекты с подобными "архитектурными решениями" впоследствии частенько приходится полностью или почти полностью переписывать совершенно новой команде в сжатые сроки после того, как изначальные авторы, "правильно пользующиеся" своим собственным творчеством, успешно их завалят, потратив при этом втрое больше времени, чем было реально нужно.
            Ответить
            • Я не понял, какая еще "локация"? Вы обладаете каким-то сокровенным дополнительным знанием о данном коде? Прекрасно. В следующий раз позаботьтесь о том, чтобы это знание было включено в исходное сообщение. Телепатов тут нет.

              Что я вижу в этом коде - это GUI-шный элемент popup, т.е. popup window, который может быть закрыт внешним воздействием, т.е. юзером. В данном случае обрабатывается именно такая ситуация: юзер уже закрыл popup, т.е. с экрана этот popup уже исчез, а его соответствующий внутренний объект типа `PopupWindow` еще живет в памяти. Когда реальный popup на экране уже закрыт, соответствующий "мертвый" объект `PopupWindow` помечается признаком 'needsClose()'. Соответственно код, при первой возможности, должен убивать такие внутренние объекты. Это просто синхронная форма garbage collection. Обычный, повседневный реализационный паттерн, придраться в котором абсолютно не к чему.

              Вы тут своим примером с будильником пытаетесь утверждать, что garbage collection должен быть строго асинхронным, как будильник, а синхронный - это, якобы, говнокод. Это, простите, полный бред. Должно быть именно наоборот. Не надо совать аиснхронные решения туда, где они ни на фиг не нужны. Просто не надо проводить аналогии между garbage collection и будильниками - это диаметрально противоположные вещи.

              В данном примере возникают вопросы лишь по поводу `m_walker->BeginWalk(m_graph->getClosestNode(m_currentLocationId))` . Что это такое - я не знаю. По местоположению и логике вызова я могу лишь с потолка предположить, что это какая-то форма нотификации каких-то subscribers о том, что произошел garbage collection (хотя имена к такой интерпретации не предрасполагают). А вы нам рассказываете, что это, оказывается, какой-то "персонаж внезапно начинает куда то идти"? А где это в исходном сообщении? Почему вы только сейчас вдруг решили нам об этом рассказать?
              Ответить
              • Если вам из исходного сообщения сходу ясно, что такое PopupWindow и его needsClose(), значит, английский вы знаете. Тогда почему же смысл (хотя бы примерный) конструкции "walker->BeginWalk" вам непонятен?

                Если бы это было хотя бы приблизительно тем, что можно предположить по местоположению и логике вызова, имена там были бы совершенно другие. А этого фрагмента здесь бы не было вообще.
                Ответить
                • Потому что `PopupWindow` и, в частности, `Window` - термины достаточно специфичные, с устоявшимися значениями. Более того, мое предположение о значаниях этих терминов тут же подтверждается использованным автором кода реализационным паттерном - синхронный garbage collection оконного объекта после того, как само окно уже закрылось. Это известная проблема с известными решениями.

                  `Walker` и иже с ними - термин без устоявшегося значения (по краней мере в моей области деятельности) и никаких дополнительных намеков на его значение в коде я не вижу. Поэтому брать предположеня об этой строчке кода я могу только с потолка.
                  Ответить
                  • Тоесть вы согласны с тем, что Walker это бог его знает что такое, в строчке "m_walker->BeginWalk(m_graph->getClosestNode(m_currentLocationId)); " не упомянается "m_curPopup" или нечто явно имеющее к нему отношение, и вы не можете сделать предположение о том, что этот код уместен.
                    Не следует ли из этого, что код неуместен, и его надо рефакторить быстро, решительно, дабы не смешивать разные процессы или привести именование к норме?
                    Ответить
                    • Нет, из этого не следует, что данный код неуместен. Из этого следует, что я не знаю уместен он или нет. А дальше каждый думает в меру своей испорченности. Я вот привык придерживаться "презумпции уместности" и по умолчанию полагать, что код таки уместен.
                      Ответить
    • Лучше объясните мне зачем тут ret_value, когда можно сразу возвращать null_ptr !? Или заделаться void'ом?
      Ответить
      • Это откуда такие выводы следуют? Если 'm_curPopup' на входе не равен null и признак 'needsClose()' не выставлен, то функция возвращает совсем не null, а именно текущее значение 'm_curPopup'.
        Ответить
    • Геттер без const'а.... Да здравствуют грабли!
      Ответить
      • Эти ребята, судя по всему их коду, вообще ещё не в курсе, что это ключевое слово можно использовать для чего-то, кроме объявления глобальных констант.
        Ответить

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