Публикация кода VVVVVV показала, насколько грубо устроены игры внутри

Автор оригинала: Patricia Hernandez
  • Перевод
image

На прошлой неделе создатель Dicey Dungeons Терри Кавана отпраздновал десятую годовщину своей давней игры VVVVVV, by опубликовав её исходный код [перевод на Хабре]. Если объяснять просто, то это значит, что любой человек может теперь посмотреть, как создавалась игра, потому что каждую строку кода можно внимательно изучить.

Такое нечасто случается и поэтому ценность публикации этой информации очень велика. Люди могут учиться по ней или улучшать код. Некоторые отзывы на исходный код VVVVVV были ужасными — исследователи увидели вещи, которые можно было написать лучше. Возможно, Кавана предвидел это — в своём посте, где он объявил о публикации кода, Терри признаёт, что «технически игра VVVVVV не очень хорошо продумана! Даже по стандартам инди-разработчиков-самоучек, код довольно хаотичен».

Существует заблуждение, что написание кода само по себе является изящным и продуманным, ведь в конечном итоге, это своего рода написание логики, не так ли? Не зря ведь это называется компьютерными НАУКАМИ? Но в реальности всё гораздо сложнее. Очень часто истории разработки видеоигр показывают, что поскольку в играх есть так много элементов, от геймдизайна до звука, что часто собираются в единое целое только в последний момент, если вообще когда-нибудь собираются.


«Существует название для игр, в которых код едва связан, имеет глупую архитектуру, в которых ошибки почти невозможно исправить, а костыли громоздятся на велосипеды. Они называются „выпущенные игры“».

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

Почти каждый разработчик, с которым я общался, говорит то же самое.

«Игры — это не обычное ПО, а сложный механизм, для успешного издания которого требуется знание множества дисциплин, и часто для того, чтобы уложиться в срок, приходится идти на жертвы», — написал в письме разработчик игр Джеймс Симпсон. «Я знаю многих разработчиков, из кожи вон лезущих, чтобы сделать свой код идеальным. Этот пример открытого исходного кода показывает, что можно успешно выпустить игру, не достигая такого уровня совершенства».

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


Сегодня видеоигра «VVVVVV» перешла в #OpenSource и кто-то обнаружил в коде конструкцию из нескольких сотен switch. #programming Это одновременно прекрасно и отвратительно.

Зак Гейдж, работавший над такими мобильными играми, как Pocket-Run Pool и Really Bad Chess, разобрал для нас эту печально известную конструкцию из switch, сказав, что «это прекрасный пример того, о чём Терри скорее всего не знал, когда начинал писать игру: сколько катсцен в ней будет, как будет работать главное меню, и сколько странных потенциальных конечных состояний странных режимов может возникнуть».

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

«Вместо того, чтобы сделать шаг назад и упорядочить всё, Терри наверно подумал что-то типа „Да, я собираюсь просто добавлять состояния в огромный оператор switch каждый раз, когда мне понадобится что-то новое“. Это на 100% нормально и по сути необходимо для выпуска игры».

Гейджу очень близко известен такой образ мышления — он рассказал нам, что оглядываясь на разработку игры Ridiculous Fishing, «в буквальном смысле не понимает, как коду удаётся работать, ведь он так плохо написан». Даже другие члены команды не полностью понимают, как работает их игра.

Но знаете что? Ridiculous Fishing всё равно получила несколько наград и заработала на несколько месяцев почти миллион долларов. Очевидно, что разработчики должны устранять ломающие игру баги и всё, что может встать на пути игрока к наслаждению игрой, но, как говорится, лучшее — враг хорошего.

«Всегда будут появляться незапланированные части, и если вернутся назад для упорядочивания кода, то это означает, что ты потеряешь время, которое можно потратить на написание нового кода, добавление новых функций или рисование арта», — говорит Гейдж.

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


Каждый увиденный мной скриншот ужасных недостатков в исходном коде VVVVVV лишь делает меня сильнее.

«Не знаю, что мне сказать по этому поводу?», — написал он в посте о публикации исходного кода. «Я был молод, и мне было интереснее создать что-нибудь на экране, чем реализовать это правильно. Вероятно, самое лучшее в исходном коде VVVVVV — он стал доказательством того, что можно слепить что-нибудь самостоятельно, даже если вы не очень хороший программист».



О том, как разработчики игр решают проблемы при помощи быстрых хаков, можно прочитать в серии переводов «Грязные трюки в коде видеоигр»:

Грязные трюки в коде игр

Разработчики о самых грязных программных трюках в играх

Грязные трюки и оперативка

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

Подробнее
Реклама

Комментарии 92

    +4
    github.com/TerryCavanagh/VVVVVV/blob/master/desktop_version/src/Game.cpp#L622 тот самый switch из 309 элементов.
      +28

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

        +5
        Обычная стейт машина FSA, да и иначе толком не перепишешь.
          –2

          IMO, Finite State Machines — это антипаттерн похуже синглотонов. Он имеет очень узкое применение — анимация и AI, использовать его где либо еще — моветон. За годы работы в геймдеве, я не видел ни одной нормальной реализации FSA которая бы не раздулась в неподдерживоемое спагетти.


          Переписать толком можно легко, есть куча паттернов и подходов, начиная классическими вроде MVC / MVVM (которые отлично подходят для UI-driven и 2d игр, с теми или иными изменениями), и заканчиая Entity Component System и Data Oriented Design.


          Я считаю, что в таких ситуацях гораздо уместнее писать Service-Centric код и Inversion of Control. Вместо монолитной машины состояний, состояние игры описывается набором сервисов. Каждый сервис имеет свое сосотояние отвечает за что-то одно и только одно, например: анимация, диалоги, инвентарь, квесты, прогресс игрока, сохранения, аутентификация итд.
          Сервисы слабо связаны (через интерфейс) и общаются друг с другом по минимуму. Соответственно, ожидания каждого сервиса так же описываются через интерфейс / контракт, например, сервис диалогов может обращаться к сервису интвентаря что бы узнать, имеется ли в наличии предмет, требуемый для выполнения квеста, итд (InventoryService.HasItem(...)).
          Логика каждого сервиса может быть протестирована Unit и Integration тестами.

            +1
            Каждый сервис — своя FSA, остальное — модное словоблудие.

            Единая FSA конечно зло, я не смотрел — так ли это в данной игре.
              –1

              Каждый сервис FSA не сильно отличается от монолитных FSA. Разбивая логику на сервисы, не забывая о принципе единой ответственности и SOLID в целом, вы быстро обнаружите, что FSA вам не нужны.


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

                +4

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

                  0
                  Есть меню вверху экрана, там в зависимости от нескольких флагов/условий могут появляться 4 одинаковых по размеру контент-менюшки. Нужно по совокупности условий скрывать 3 из них и показывать 4-ю. Как вы понятно это сделаете, если не, скажем:

                  let state = ...
                  switch state {
                  case state1:
                    v1.hidden = true
                    v2.hidden = true
                    v3.hidden = false
                    v4.hidden = true
                  case state2:
                    v1.hidden = false
                    v2.hidden = true
                    v3.hidden = true
                    v4.hidden = true
                  ...
                  }
                  
                  
                    +1
                    Так короче и меньше шансов ошибиться, хотя по понятности всё равно не лучший вариант:
                    v1.visible = state == state1;
                    v2.visible = state == state2;
                    v3.visible = state == state3;
                    v4.visible = state == state4;
                    
                      0

                      Состояний 300

                        +2
                        Кодировать состояния в таблицу, таблицу парсить либо в compile time (генератор кода), либо в runtime.
                          0
                          а если не только прятать/показывать надо? Конкретно в этом примере мне надо чтобы на вьюхе №1 показывалась определенная анимация, если это переход с 4 стейта в первый, и т.п., и логики там еще пару строк в каждом кейсе есть.

                          Я нисколько не против таблиц, кстати они тоже конечный автомат, так что мы отошли от изначального вопроса :) Но если есть еще и какая-то кастомная логика кроме .visible, имхо switch — да, самое топорное, но и самое наглядное/поддерживаемое решение
                      +1
                      Хештабшицей статус -> маска, например. Или массивом массок если state это числа в разумных пределах.
                        +1

                        Даже если претят таблицы, то хотя бы использовать этот факт:


                        скрывать 3 из них и показывать 4-ю

                        v1.hidden = v2.hidden = v3.hidden = v4.hidden = true;
                        
                        let state = ...
                        switch state {
                        case state1:
                          v3.hidden = false;
                          break;
                        case state2:
                          v1.hidden = false;
                          break;
                        ...
                        }
                          0
                          можно было бы и так для красоты и краткости, так иногда и делаю, а что если на какие-то вьюшки мне нужно показывать с анимацией, если переход от четвертой к первой, и только этот переход? Да, такая логика у приложения, ничего не поделаешь. И имхо чем кастомней код тем больше ему нужно быть кодом, таблицами все не закодируешь. А старый добрый конечный автомат всегда выручает
                          0

                          Я считаю что вы делаете две потенциальные ошибки.


                          Во-первых, вы строите всю архитектуру на предположении о том, что у вас может одновременно показываться только одна менюшка и это требование никогда не изменится. Но завтра к вам приходит дизайнер / заказчик и просит сделать drag-and-drop между менюшками, и оказывается что во время перетаскивания надо показать обе одновременно. И в такой момент вы понимаете, что весь код придется для этого выкинуть / переписать с нуля, потому что само понятие машины состояний тут неприменимо (раз может быть несколько состояний одновременно).


                          Во-вторых, в самом switch-case, конечно, ничего страшного нет, но как только добавится логика, анимации переключения между меню итд, появятся классы типа State, StateTransition и прочих артефактов спагетти-стейт машин, и проблема #1 станет еще хуже.


                          Как по мне, так хорошо установленные паттерны вроде MVC отлично подойдут здесь. Каждое меню или подменю имеет свою пару Controller — View. Controller отвечает за логику и делает вызовы в сервисы, View — за представление (шаблон меню, анимации). За переключение подменю может отвечать одна функция, которая при разворачивании контент-меню закрывает остальные:


                          // IMenuController.cs:
                          interface IMenuController
                          {
                              bool IsOpen;
                              void Open();
                              void Close();
                          }
                          
                          //  TopMenuController.cs:
                          class TopMenuController : IMenuController, INestedMenuContainer
                          {
                              private IMenuController[] _submenus;
                          
                              public void OpenNestedMenu(int index)
                              {
                                  for (int i=0; i<_submenus.Length; i++)
                                  { 
                                      IMenuController submenu = _submenus[i];
                                      if(i == index && !submenu.IsOpen)
                                      {
                                           submenu.Open();
                                      }
                                      else if(submenu.IsOpen)
                                      {
                                           submenu.Close();
                                      }
                                  }
                              }
                          
                              // ...
                          }

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


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

                          0
                          Допустим, есть шина (rabbitMQ), на которую льются объекты и подписаны обработчики. Каждый обработчик берёт объект со своим state, что-то делает, меняет состояние и выкидывает обратно в шину.
                          Бинд обработчик(и) — состояние лежит во внешнем файле и в любой момент может быть откорректирован, требование ТЗ.
                          Для удаления с шины есть отдельный обработчик, который мониторит неиспользуемые состояния и состояние окончания обработки.
                          И как здесь без конечных автоматов?
                        0
                        использовать его где либо еще — моветон

                        А парсеры?
                          +1

                          Ну, я говорил об играх. Понятное дело, за пределами игр есть ряд узкоспециализированных задач и алгоритмов где FSA применимы. Но для геймплей логики их использовать — это зло.

                            0

                            У меня обратный опыт. Тем не менее, я согласен с тезисом про спагетти — стейт машины надо проектировать осторожно и внимательно. Зато когда она работает — то она работает хорошо.

                            0

                            Явные — плохо. PEG получше.

                          0

                          Бустовские стейтмашины смотрят на этот тезис с недоверием.

                          +4
                          Немного выше зачем-то 2 if-a сделали:
                          void Game::updatestate( Graphics& dwgfx, mapclass& map, entityclass& obj, UtilityClass& help, musicclass& music )
                          {
                              int i;
                              statedelay--;
                              if(statedelay<=0){
                          		  statedelay=0;
                          			glitchrunkludge=false;
                          		}
                              if (statedelay <= 0)
                              {
                                  switch(state)
                                  {
                          Работает, не трожь )
                            +4
                            PVS-Studio на них нет!
                              +2
                              PVS-Studio в данном случае, возможно, выдаст v525.
                                +6

                                Я думаю там уже потирают руки и готовят разбор…

                                  +2
                                  Да, готовят! Сегодня выйдет статья :)
                                  +3
                                  PVS-Studio на них есть :) Мимо такой игры мы пройти не смогли.
                                  Если вам интересно посмотреть, какие ошибки мы там нашли, предлагаю почитать статью:
                                  VVVVVV??? VVVVVV!!!
                                  0
                                  Работает, не трожь


                                  Да. Судя по разному форматированию, это не невнимательная копипаста. Возможно, логика работы программы описывается именно так. Блок с первым условием — валидация/инциализация входных данных. Второй блок — обработка данных. Условия сейчас одинаковые, да.
                                    0
                                    Тут еще возможно, что во время отладки меняли значение statedelay=0 на что то еще, что меняло логику. Или меняли местами statedelay--.
                                  +1
                                  enum? не, не слышал
                                    +1
                                    enum в С не спасает, контроль появился в С++
                                      +3

                                      А в игре как раз C++

                                        +1
                                        Я всего лишь сказал, что
                                        case e_activating_teleporter:
                                        читается лучше, чем
                                        case 4080:
                                        Вы так не считаете?
                                      +4
                                      А за что минус-то «предыдущему оратору»? Перечислить состояния машины состояний в enum'e и делать switch не по magic numbers, а по осмысленным идентификаторам — самый простой и естественный шаг. Который улучшил бы читаемость кода и мало-мальски облегчил бы его поддержку и отладку даже автору.

                                      Хотя понятно, конечно, что C-код игры вторичен, вначале был flash, а в Action/Ecma/JavaScript с enum как-то не особо хорошо.
                                        +4
                                        300 enum значений? С вменяемыми именами?
                                          +4

                                          Так если каждое из них имеет какой-то смысл в механике процесса, почему бы и не быть этим самым "вменяемым именам"? Или речь о том, что имена, отражающие суть, быстро разрастутся до нечитабельной длины?

                                            +1
                                            В redux так и живём, по сути, и ничего, норм ))
                                              +1

                                              А что такого?
                                              https://github.com/php/php-src/blob/9d7e03c325473024e54c864f0379efc1bbf03e72/Zend/zend_vm_opcodes.h#L79
                                              Тут не 300, конечно, только 200, но сути не меняет.

                                            +3
                                            И на что его критики предлагают заменить?
                                              –3

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

                                                0
                                                будет тот же state machine, только на лямбдах, не?
                                                0
                                                В джаве некритичных к производительности приложениях это паттерн Стратегия. Почти уверен, что в играх он неуместен, но настаивать не буду.
                                                0
                                                В играх очень сложно и не нужно разделять все на MVC паттерн — там другая парадигма программирования))) Парадигма которая очень неплохо реализована в Unity3D)))
                                                Из за этого именно такой код и будет в 90% игр)))
                                                  0

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

                                                    0

                                                    В приткладном — свой мир со своими бизнес правилами. Пользователю нельзя давать выстрелить себе в ногу. И не только себе.

                                                  0

                                                  если в игре VVVVVV код на 309 элементов, сколько их может быть в игре AaaaaAAaaaAAAaaAAAAaAAAAA!!! (A Reckless Disregard for Gravity) ?

                                                  +14
                                                  Разработчики игр говнокодят! Вот это поворот!
                                                  Ну вообще все говнокодят, просто разборы говнокода в играх как правило интересны, потому связаны с какой-то фичей в игре. А разбор говнокода в условном notepad не интересен. Вот и вся разница в говнокоде в геймдеве и не в гемйдеве.
                                                    +1

                                                    Кстати говоря, о багах в Блокноте — это тоже может быть интересно. Например, если реверсить код https://habr.com/ru/post/264081/

                                                    +2
                                                    Как там в книге по программированию на Форте было «Если ваше определение не входит в один экран, то имеет смысл разбить его не несколько более мелких определений»
                                                      +14
                                                      «Если ваше определение не входит в один экран»
                                                      --то купите экран побольше!
                                                        +2
                                                        Первые форт-системы ориентировались на работу без ОС, и исходные тексты там редактировались с помощью так называемого блочного редактора. И исходный текст всей системы и «прикладух» вместе с документацией хранился в одной области памяти, разделённой на «экраны» по 1 (одному) килобайту каждый.

                                                        Соотаетственно в начале каждого экрана писалось, что эта часть исходников делала (во многих системах каждому экрану с исходниками соответствовал экран с документацией. Тоже 1 КБ), и загрузка и редактирование происходило поэкранно. Можно было выводить список первых строк экранов-блоков.

                                                        По историческим причинам блочные редакторы всё ещё являются частью некоторых достаточно современных форт-систем. Где под эти самые блоки отводится просто отдельный текстовый (ну, почти) файл. Например см. www.forth.com/starting-forth/3-forth-editor-blocks-buffer (там код адаптированный к коммерческому и ещё, вроде, живому SwiftForth).
                                                          0
                                                          Разбить код на мелкие кусочки — задача не очень сложная.

                                                          Но требуется, видимо, какая-то охренительная конвенция по неймингу, чтобы придумать дохрена осмысленных имен функций и не запутаться в них потом.
                                                          +3
                                                          2021: «Разверните экран»
                                                            +3

                                                            2071: При строительстве подставки под экран был случайно возведён космический лифт.

                                                            0
                                                            При любом разрешении экран (текстовый буфер) имеет размерность 1024 символа. «Вы можете купить машину любого цвета, при условии что этот цвет — черный»
                                                          +7
                                                          Публикация кода одной игры показала как устроены абсолютно все игры. Логика журналиста как всегда безукоризненна.
                                                            0
                                                            Ну надо сказать что во много это так и есть (если что 11 лет профессионально в геймдеве). Я правда не понимаю чего так все возмутились.
                                                            +3
                                                            Тем временем этот код критикуем мы, в телах и головах которых эволюция накапливала технический долг миллионы лет. И надеюсь, что люди будущего будут вечно восхищаться тем, что смогли разгрести этот костыльный ад.
                                                              0
                                                              Ух, скорее бы избавиться от таких костылей, как копчик и мышцы вокруг ушей. А то постоянно непредсказуемые баги с ними вылазят.
                                                                0
                                                                Мышцы вокруг ушей ни чем не мешают.
                                                                Копчик — да, уязвимая штука — легко крашится и потом вся система страдает.
                                                                Но мне кажется рефакторить нужно сначала наиболее критические места, ИМХО:
                                                                1) дублировать/резервировать мышцу для поддержания давления в кровеносной системе.
                                                                2) усилить/укрепить систему монтажа «ЦП» и большинства сенсоров.
                                                                3) разнести в пространстве интерфейсы систем отвода отработки и репродуктивной системы. (ибо не гигиенично).
                                                                :)
                                                                  +2
                                                                  Увести сосуды глаз за сетчатку! КПД глаза в нынешнем виде поистине уныл, осьминоги ржут над нами :(
                                                                    +2
                                                                    А будут продолжать ржать — дадим им мозг, чтобы страдали от бессмысленности существования.
                                                                    0
                                                                    1) дублировать/резервировать мышцу для поддержания давления в кровеносной системе.

                                                                    1.1 Сменить систему кровообращения на магнитную.
                                                                      +1
                                                                      1.1 Сменить систему кровообращения на магнитную.

                                                                      Внешние неодимые магниты — vulnerability detected.

                                                                  +2

                                                                  Не пытайтесь переплюнуть Milfgard. Он описал гораздо больше багов.

                                                                    0
                                                                    Не, нам только в своём форке надо исправлять, чужие баги не нужны.
                                                                  0
                                                                  Когда-то давно я купил себе телефон Nokia 1020 под виндой. Хорошенько протащившись от плиточного интерфейса (до сих пор на андроиде пользую шеллку с плитками, уж больно нравится), решил попробовать что-нибудь написать под эту платформу.
                                                                  Ну а что писать? Конечно игрушку какую-нибудь. Что-нибудь простое и из времен молодости.
                                                                  За два дня(в буквальном смысле за 2 дня) наклепал говнокода и как водится — «х.як-х.як и в продакшин» (в смысле в магазин приложений). Не запаривался никакими игровыми фреймворками, все было сделано на обычном виндовом Canvas'е, без «эффектов» — просто игровые юниты + гравитация.
                                                                  Потом несколько раз обновлял приложение (добавлял новые уровни, предварительно их пройдя локально у себя на телефоне + мелкие доработки, типа вкл/выкл звук и еще что-то там), потом наигрался и забыл/забил.

                                                                  Так вот, к чему это я все? К тому, что код у меня в этой игрулине был примерно такого же уровня — он абсолютно не был продуман, т.к. изначально вообще не было никакого плана разработки. Ни количества уровней, ни списка фич, а общая концепция сводилась к «ща наклепаем и поглядим, как оно будет, а когда-нибудь потом сделаю как надо».
                                                                  Скорее всего автор упомянутой игры пошёл по такому же пути — слепил в коде какую-то мелькнувшую идею, по ходу разработки обвесил ее всякими плюхами и дополнениями, ну а после просто поленился делать рефакторинг (хотя судя по коду, там проще с нуля переписать, чем пытаться привести все это хозяйство к «правильному» виду).
                                                                    +3
                                                                    Поддерживаю. И вообще, не верю в проектирование ПО. Проектирование ПО — это когда ты перекладываешь риски на заказчика, согласовываешь с ним ТЗ/проект (= текущая абстракция), реализуешь, и этот дурак тебе платит за получение продукта, который ему не нужен. Не нужен, так как на первом же прототипе или после первых дней прогона в реальности, он говорит «да, я помню, мы так согласовывали, но вот тут нам нужно поменять это и это, убрать это и добавить это», а в ответ получает «простите, в ТЗ мы вот так прописали — сделаем версию 1.0 как договаривались, оплатите, начнем писать версию 1.1». И это в лучшем случае. В худшем — программисты возмущаются, что за идиот заказчик, не знает, что ему надо. А это так и есть — заранее никто не знает, что ему надо, как будет удобно пользоваться инструментом, которого вообще пока что еще нет.

                                                                    Мир — довольно хаотичен, сложен и переплетен. Окинуть разумом его очень сложно, поэтому, мне кажется, что идеальное ТЗ на что-то сложнее калькулятора — заведомо невозможно. Разработка по принципу добавления кирпичиков, чтобы каждый час труда развивал продукт — невозможна. Ну или раз в тысячу лет рождаются титаны мысли, способные на это. Реальный путь — это осознание неизбежности ошибок как в коде, так и в дизайне. Делаем тяп-ляп, запускаем, видим где криво — переписываем. Потом доводим код до состояния невозможности чтения-понимания (зато — к этому мнению в головах есть понимание задачки «как надо») и уже делаем новую версию на чистовую.

                                                                    Некрасиво? Да. Но эта рабочая схема. Весь мир создан на скотче и синей изоленте. Идея «давайте просто хорошо придумаем как надо и сделаем» — только в голове у юношей бывает, до первого раза, когда они все делали как надо, сами, и выясняется, что когда «придумывал как надо» — придумал фигню какую-то.
                                                                      +3
                                                                      Именно! Я уже как-то описывал один краткий случай из жизни, когда добрую половину ТЗ для довольно сложного продукта спустили в унитаз в самом начале разработки и сэкономили тонну нервов и денег друг другу.
                                                                      А все потому, что мне пришло в голову походить хвостом за инженерами (для которых это ПО разрабатывалось), понаблюдать процесс работы, поспрашивать «а чо это вы тут делаете такое, ааа?».
                                                                      В результате чего уже на второй день стало понятно, что в ТЗ (54 страницы!) описана какая-то лютая херня, к реальной необходимости имеющая довольно посредственное отношение, проще nanoCAD поставить и обучить персонал, чем городить написанное.

                                                                      На выходе получился чудовищный гибрид Paint'a с VIM'ом, но оно работало именно так, как было нужно людям, непосредственно работающим с этим ПО — минимум движений, максимум результата.

                                                                      Да, говна и палок тоже порядочно было, т.к. многое приходилось придумывать и прилеплять по ходу разработки. Отрефакторил конечно самые «ужасные» куски перед продакшином, но! Все это работало (и работает по сей день) как часы, и послушно, как гимназистка. Хотя до «идеального кода» все еще очень далеко, но лично мне важнее именно «шоб работало как надо», а не что-то другое.
                                                                    +5
                                                                    Любое изделие можно хорошо сделать со второго раза. Но на это никогда нет времени.
                                                                      0

                                                                      какая изящная переформулировка фразы «нет ничего более вечного, чем временное»

                                                                        0

                                                                        Есть мнение, что самая опасная вресия продукта это версия 2.0. "Ну уж теперь я всё сделаю по-багатому по-умному." Со всеми вытекающими..

                                                                        +8
                                                                        Один делает, миллионы обсирают. Чел сделал единственно правильным путём. Он сделал игру, в которую прикольно играть, которую любят. Код выполняет машина. Кучи современных разработчиков не имеют своего мнения в принципе и не могут самостоятельно оценить код. И написать код без гайдлайнов и «одобрения сообщества» не могут. Игры это чертовски сложно (первую игру я написал более 15 лет назад, а последние 11 лет я только и делаю что пишу игры профессионально, ежедневно). И пытаться разводить в играх эталоны полированного кода который дорого модифицировать, сложно хакать, но который весь из себя запривачен и построен на миллионе абстракций смысла никакого нет. Я пробовал делать архитектурные изыски, их потом сложнее поддерживать. Я сейчас работаю с игрой релиз которой состоялся 9 лет назад, и она всё ещё активна, она переживает третью смену движка, и поверьте там очень много кода который плохо пахнет. И что теперь, застрелиться? Если работать а не обсуждать, то выясняется что не всё так уж и плохо. А застопорить разработку на месяцы для «архитектурирования» ни к чему хорошему не приведёт. Иначе говоря я считаю что значение понятия «красивый код» переоценено. Неплохо на похожую тему высказался Джоэл habr.com/ru/post/219651 Ну и, конечно, не могу не упомянуть просто идеальную иллюстрацию к тому что бездумное причёсывание кода не всегда нужно habr.com/ru/post/440414
                                                                        Если кратко это резюмировать: не нужно жить в говне, если говно случилось, нужно вытереть, но пытаться в коде совместить впечатление от Лувра и стерильной лаборатории одновременно никакого смысла нет.
                                                                          0

                                                                          У меня была другая ситуация. В начале своего пути становления как программиста я много говнокодил и захлебывался от предварительных оптимизаций, отсутствия системы. В результате не доводил проект не до что до конца, даже до середины. Даже начинал задумываться а мое ли это?


                                                                          Сейчас процент более менее завершенных проектов куда больше :)

                                                                            0
                                                                            Я же не говорю что проектирование, архитектура и всё прочее не нужно. Просто при реализации проекта и задуманной архитектуры неизбежно выползут несостыковки, это нормально, если нельзя быстро в рамках архитектуры сделать хорошо то нужно подставить костыль и продолжать, мониторя то, сколько костылей натыкано и как они себя ведут. Если ломаются — править, а если нет, то пусть стоят. А говорить что в коде не должно быть ни одного костыля — врать себе и другим. В данном случае, если бы чувак вместо релиза сидел бы полировал — ничего бы не получилось.
                                                                          +1
                                                                            0
                                                                            я если честно крайне плохонький кодер, но обычно после получения работающего прототипа он откладывается в сторону и переписывается с нуля — что бы поубирать всю ту «муть» и «гуляние мысли» которые были в процессе прототипирования…
                                                                              –1
                                                                              Одна из лучших игр за последнее время и я сперва очень обрадовался что автор выложил её в open source, потом прочёл лицензию и радость пропала. Короче, товарищ просто дал нам возможность почитать его код :)
                                                                                +1
                                                                                Почему? Вы можете собрать для себя любимого билд с оригинальными ресурсами, куртизанками и преферансом.
                                                                                Плюс можно делать всякие аддоны, тулзы и прочая, но их, как я понял, нельзя будет монетизировать.
                                                                                В остальном да, это весьма ограничивающая лицензия.
                                                                                  –2
                                                                                  Open source (в понимании Open Source Initiative) тем и хорош что каждый может и форк сделать, и подзаработать быть может (почему нет?). А тут ограниченная во всех смыслах лицензия которая годится только что для образования (хотя и тут не факт что его можно полноценно использовать в платных учебных материалах) и статей «как не надо писать код». Я думал автор действительно хотел вложиться в open source как сделала id software в своё время, но нет, парень просто пропиарил себя. Я бы это даже open source не назвал. Всё для чего годится такой код это лепка модификаций его же игры.
                                                                                0
                                                                                Как говорится, «неделя непрерывного программирования спасает от двух часов проектирования». Да, автор молодец, выпустил завершённый продукт, но мне было бы стрёмно выпускать продукт с таким кодом (если только он не был написан под дулом пистолета).
                                                                                Тут уже несколько раз приводился switch на 300 состояний. Попробуйте вспомнить хоть какую-нибудь сущность, представителей которой вы можете описать в количестве 300 штук. Я почти уверен, что в оригинальном коде игры этому состоянию нет названия, потому что автор не попытался его как-то назвать. А значит и не было попытки как-то его декомпозировать.
                                                                                  0

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

                                                                                    0

                                                                                    Апдейт большого размера уже редкость, но вот игры которые перевалили за 80 гигов на харде уже не редкость. И та ки да, 99 процентов файлов из этих 80 гигов это медиа файлы, как картинки с разным разрешением и музыка. Если повезет то музыка в МП3 и можно скопировать на телефончик. Если не повезет, то нужно понять как конвертировать один тип файла в другой.

                                                                                    0
                                                                                    Три года назад я написал плагин для X-Plane. От идеи и первого прототипа до первой публичной версии прошло две недели. С тех пор эта штука попала в топ-5 самых скачиваемых плагинов для X-Plane (250К это очень много для симуляторов) и есть во всех списках «N плагинов X-Plane, которые вам необходимы».
                                                                                    Но ёлки-палки, внутри довольно ужасный код на голом С. Многие вещи, которые я заложил в самом начале, так и остаются в неизменном виде. С тех пор плагин стал делать гораздо больше функций и это тоже добавило некоторого хаоса. Я это потихоньку привожу в порядок, но на самом деле проще всё сжечь и переписать заново.
                                                                                    Это я всё к чему. Если бы я тогда начал продумывать архитектуру, то эта штука скорее всего вообще бы не появилась. Я бы просто утонул в деталях, в начале я вообще не представлял за какую сложную штуку взялся и сколько там нюансов.
                                                                                      0

                                                                                      Ладно игры — работал в одной Fin-Tech конторе, которая делала софт для top-tier investment банков: там был тоже был один мега-фактори с огромным case-switch'eм. В какой-то момент он превысил 65536 строчек кода, и начались проблемы с дебагом в VisualStudio

                                                                                        0
                                                                                        В какой-то момент он превысил 65536 строчек кода, и начались проблемы с дебагом в VisualStudio

                                                                                        Чувствую, пришло время репортить баг в VisualStudio.
                                                                                          0
                                                                                          Представляю ответ. «Перепиши код, даун!»!

                                                                                          У меня есть живой пример — люди в одном проектном институте копипастили код АСУТП, что он перестал влезать в контроллер по памяти (100500 задвижек или что то типа).

                                                                                          Ну я по молодости, примерно так нетолерантно им и ответил
                                                                                            0
                                                                                            Справедливости ради должен отметить, что в промышленной автоматике ресурсов куда меньше, потому они заканчиваются быстрее.
                                                                                            А нарастить ресурсы (ПЗУ, ОЗУ) или невозможно, или очень дорого.
                                                                                        +1
                                                                                        Я в своей игре тоже писал кучу говнокода, и как-то работало, и всем было плевать.

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

                                                                                          Наверное, есть исключения — или долгоиграющие AAA проекты (кхе-кхе, на тебя смотрю, Star Citizen), или всякие MMO/MOBA у которых очень долгий цикл сопровождения. Но да, для проектов поменьше, для инди, выкатить рабочее важнее внутренних красот.

                                                                                            0
                                                                                            У инди просто ограничение на ресурсы еще жестче, чем у крупных студий.

                                                                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                                        Самое читаемое