Я столкнулся с тем, что я иногда не понимаю код, с которым мне приходится работать. И это сильно сказывается на моей производительности и на качестве конечного результата. Неделю назад я прочитал статью Плохо девелопмент за авторством @dalerank(Сергей Кушниренко), в которой описывается проблема молодых специалистов, которые упрощая себе работу пользовались готовыми решениями, а не писали код с нуля. Моя статья не об этой статье и не ответ к ней. В самой статье Сергея Кушниренко была ссылка на другую статью — You should refuse to develop what you don’t understand. И вот эта статья меня несколько озадачила. Я задумался о проблеме понимания того, с чем я работаю. О ней я бы хотел написать, но и некоторые тезисы из статьи Сергея Кушниренко я тоже затрону.

ВНИМАНИЕ! Дальше вас ждет душная простыня текста без юмора.

Вводная

Так сложилось, что сейчас я работаю в игровой индустрии, и занимаюсь поддержкой игрового движка. Ранее я написал статью о том, как я попал в gamedev. Ссылку указываю, чтобы не повторят здесь всю предысторию. Статья скучная, душная и длинная, поэтому предупреждаю. И, собственно, мне [не] повезло работать с очень неудобным кодом. «Не повезло», так как задачи, которые мне ставят я иногда не могу выполнить в срок, а «повезло» потому, что я фактически набиваю руку на этом плохом коде. Я делаю заметки, учусь ошибкам, оставляю комментарии в коде — тому, как делать не надо. Стоит так же ещё упомянуть, что документация, которая доступна настолько мизерно описывает внутреннюю структура движка, что можно сказать, что и не описывает ничего в принципе. Об этом я напишу ещё раз ниже.

Простой пример, чтобы понимать глубину проблемы в движке. В пользовательской части движка есть объект Sprite, который представляет собой плоскую картинку, натянутую на конечного размера прямоугольник. Есть несколько свойств у этого объекта, для примера я возьму position (ака позиция, ака положение). В коде описан класс Sprite, и свойство positionэто приватное поле этого класса. Доступ к значениям поля выполнен через методы. Но методов не два, как могло бы показаться. Логично же иметь геттер и сеттер приватного поля. Но не в описываемом движке. Геттов/сеттеров по сути 6 штук, по два (получить текущее значение, записать новое) на каждую разновидность. На самом деле их больше, это связано с проблемой, которую в этой статье я наверное не буду затрагивать, поэтому для статьи их только 6. Так как движок написан на C++, то повсеместно используется любимая многими особенность языка — полиморфизм. И класс Sprite является производным от базового класса Object — классика. И, собственно, поле position и его геттеры/сеттеры находятся в базовом классе, и не переопределены в классе Sprite. А ещё для того, чтобы спрайты могли зависеть друг от друга, они имеют поля родителей и детей. Это нужно, чтобы один спрайт двигался за другим как единый объект на экране. И всё, что управляет зависимостями родителей и детей, тоже находится в базовом классе.

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

Один из методов-геттеров getPosition, получает именно те данные, которые находятся в поле position без каких-либо изменений. Банально return position. Его антоним — метод-сеттер setPosition, по логике, должен так же просто устанавливать в поле position новое значение, но он устанавливает значение в поле трансформации и нужный флаг трансформации. И после чего на текущем витке игрового цикла эта трансформация применяется объекту. Это происходит там, где уже нет различий объектов из-за полиморфизма — обезличенное применение трансформации в отдельном цикле. И вроде как это не должно быть проблемой. Но там же происходит проверка на наличие родителей. И если родитель имеет определенный флаг трансформации, а также значение в поле трансформации, то будет сделан перерасчёт для всех детей, и в поле position будет записано другое значение, не то, которое предполагается. И знать об этой особенности, не зная движка, невозможно. Поле и флаг трансформации, как я понял, применялись для изменения положения объектов с самого начала. Но в какой-то период времени стало понятно, что нужно устанавливать позицию четко в то место, что нужно. И для этого был добавлен второй набор геттер/сеттер — getGlobalPosition/setGlobalPosition. И именно setGlobalPosition устанавливает точное значение положения объекта на экране, там, где объект должен быть по задумке разработчика. А getGlobalPosition получает тот же кусок данных, что и простой getPosition. Только и здесь есть нюанс. Эти геттер/сеттер берут и меняют значение не у объекта, через который вызываются, а у объекта родителя, который сам смотрит в своего родителя, и так далее по иерархии. То есть визуально объект ставится туда, куда нужно, но получается это путём установки такого же значения у всех его родителей рекурсивно по иерархии. И только третий набор геттер/сеттер — getMainPosition/setMainPosition работают непосредственно с текущим объектом. Но и здесь не обошлось без «веселья». Потому что, всё ещё есть поля трансформации. И getMainPosition учитывает возможную трансформацию, точнее только то значение, которое было добавлено до вызова геттера. Что с одной стороны логично, но с другой неочевидно. Сеттер setMainPosition устанавливает значение в поле position напрямую.

Вот с таким набором кода столкнулся я, получив новую задачу, связанную с определением положения определённого предмета и последующую обработку этого положения. Сложность задачи была в том, что всё описанное выше я узнал не из документации, а собственными тестами и экспериментами, при этом сам предмет не был объектом класса Sprite. Он был отдельным классом, который так же, как и класс Sprite наследовался от базового класса Object, а класс Sprite был одним из полей предмета. То есть логика и визуал разделены. А это, если рассуждать логически, означало наличие иерархии родитель→ребёнок. Но в коде такой иерархии не было. Из-за чего положение предмета и его визуального представления в виде спрайта никак не было связано. Это была ещё одна [не] «весёлая» история. Но она уже не относится к теме статьи.

Пример с полем position объекта Sprite не единственный. Таких примеров в движке, с которым я сейчас работаю, найдётся сотни, если не тысячи. Я лишь выделил тот, который смог описать коротко и понятно, в угоду мыслям этой статьи. Так-то можно было бы накинуть ещё примеров, чтобы текст статьи стал ещё длиннее и бесполезнее. Но я хочу уже перейти к самой статье.

Новобранец и Код

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

А что если исполнитель не понимает что происходит с кодовой базой? Вы можете возразить, ведь есть процесс онбординга, есть такой конструкт, как документация. Это то, что должно помочь исполнителям понять то с чем они будут работать. И вы будете правы. Но и здесь есть нюансы. Даже не так. А что если не было онбординга, и документация отсутствует? Мне [не] посчастливилось поработать в компаниях, где в одной у меня не было онбординга и документации, а в другой не было только документации, а онбординг был, но не тот, который бы дал мне понять, что не так с кодом, с которым я буду работать.

Ошибочно считать, что онбординг это только знакомство с командой и внутренними процессами в компании. Онбординг это ещё и знакомство с тем, с чем будет работать ново-нанятый. Со всеми особенностями кодовой базы, и не в последнюю очередь с её проблемами. Бэклог в этом плане вещь очень хорошая, но оно не совсем то, что нужно. По сути нужна документация не только на то, что хорошо работает. Но и на то, что работает плохо. То есть нужно что-то типа раздела troubleshooting (ака траблшутинг, ака известные проблемы). И вопрос такой. А много ли где документируют проблемы их кодовой базы? Когда я столкнулся с проблемой, описанной выше про класс Sprite, я не мог взять на себя ответственность задокументировать эту проблему, так как она очень обширная, и требует времени для описания всех особенностей. Это не было включено в срок исполнения задачи. А ведь даже с моего описания проблема выглядит серьёзной. И если бы я взялся за документацию к ней, то я бы мог не выполнить свою задачу к сроку. Всё что я сделал, на очередном стендапе (ака stand-up, ака созвон команды) я описал проблему и попросил внести в бэклог написание документации для этой проблемы. Не нужно быть с тремя высшими образованиями, чтобы понять, что задача получила наименьший приоритет и минимальную важность. Что означает, что задачу можно забыть, так как беклог ломится от более важных и срочных задач.

Автор статьи You should refuse to develop what you don’t understand, Джонатан Боккара, делает акцент на то, что программист должен знать, что он пишет. Как на уровне своих собственных навыков, как программиста (называя это уровень понимания №0), так и на уровне кодовой базы, с которой придётся работать (уровень понимания №1 и №2). И вот здесь начинается моё брюзжание. Собственные навыки программиста я разделяю на два типа: знания стека технологий, и опыт решения проблем. И сейчас для себя выделяю «опыт решения проблем» более важным навыком, чем знание стека. Потому что именно опыт решения проблем требуется при приёме на работу. А знание стека — это энциклопедическое зазубривания терминов используемых технологий. Эти знания тоже важны. Но никто не умрёт, если не знать какие-то термины, а наличие свободного (пока ещё) интернета и доступной информации по любому вопросу, может помочь «нагуглить» значение нужного термина. А вот опыт решения проблем приходит только в процессе решения проблем. И, как раз, наличие соответствующей «проблемной» документации в кодовой базе поможет быстрее решать проблемы, или же не столкнуться с ними. И здесь я сделаю, возможно неправильный вывод, но мне он кажется логичным. Если у программиста есть опыт решения проблем в определённой области, то у него есть знания о технологиях этой области. Знания могут быть не полными, но подтянуть их можно и довольно легко, если программист этого захочет, или если работодатель поставит ему такую задачу. Программист же постоянно учится. Это типа общепринятый тезис.

Сергей Кушниренко в статье Плохо девелопмент, как я понял статью, делает акцент на том, что его подчинённые обращались к ChatGPT (или гуглили) для того, чтобы найти решения по их задачам. И эти решения они использовали. Мой тезис в том, что у них не было опыта в решении проблемы, которая была обозначена в их задачах, здесь, как мне кажется, полностью раскрывается. Я сам не буду отрицать, что я сам не пойду гуглить решения, если я его не знаю (но ChatGPT я не пользуюсь, я старомоден). В этом же и суть — найти решение. Тут возникает другая проблема — сроки выполнения задачи. Я об этом писал в комментариях к статье, и здесь повторю вопрос. А были ли правильно рассчитаны сроки выполнения, с учётом опыта подчинённых? Этот риторические вопросы адресованы не вам, Сергей. Я по сути не в курсе ситуации, так как основываюсь только на тексте статьи. Но было ли у них время на самообучение? Было ли у них время получить опыт? Я не учитываю то, что у них может быть не было желания получать опыт. Влияния этого отрицать нельзя. Но для понимания проблемы моей статьи я опускаю этот вопрос и считаю, что желание у них было. Это я к тому, что для получения соответствующего опыта тоже нужно время. Когда я шёл в разработку игр, и меня был опыт разработки игрового движка. Я самостоятельно разрабатывал один такой. И набивал шишки, читая статьи, и применяя вычитанное на практике. Потом стал изучать код других движков, чтобы увидеть различия, или подчерпнуть интересные решения. То есть на момент поиска новой работы я уже имел опыт копания в кишках игровых движков. Поэтому мне было легче вникать в некоторые проблемы движка на текущей работе, так как по опыту понимал, что какие-то решения имеют не те результаты, которые должны быть.

Старожила и Код

Если посмотреть со стороны опытного программиста, то для него проблем в коде может и не быть. Он прошёл все пять этапов принятия. Его опыт говорит за него. Но может быть так, что именно такой опытный спец стал причиной текущих проблем в кодовой базе. Что он своим «авторитетом» отсекает более правильные решения. Пример для языка C++, из комментариев к статье одного блога (не указываю ссылки, так как их потерял, можете считать примеры выдуманными). Типа зачем напрягаться и делать сложные шаблоны, когда можно банальными макросами предпроцессора отсекать лишний код. Или пример для ряда других языков программирования (встречал здесь на Хабре). Зачем выстраивать сложные фабричные методы, когда можно банальным if else наглядно показать работу переключений, и, если надо — не долго переписать. Эти комментаторы позиционируют себя, как сеньоры. Выводы по их комментариям я оставлю вам, читателям. Я себя сеньором не позиционирую. И возможно поэтому я не понимаю их. Не познал ещё дзен. Но сейчас не об этом. Я о том, что проблема может исходить от более опытного, так как он применяет тот способ решения проблемы, к которому привык. Он же знает, как работает им написанный код. И потому принимает решение оставить всё, как есть. Менеджмент может неправильно воспринимать проблему, оставляя всё как есть, ссылаясь на его опыт и авторитет. А потом такой специалист может уйти, и тогда весь технологической долг, который этот специалист долгие годы копил (держал на себе) выльется на того, кто впервые видит кодовую базу. И это будет БОЛЬ. Под это даже целый термин определили — Фактор автобуса. В статье на Википедии про Фактора автобуса, описаны способы решения проблемы.

Цитата из статьи в Википедии (чуть изменена трактовка первой строки):

Существует несколько способов решения проблемы:

  • Уменьшение сложности;

  • Управление знаниями проекта:

    • Фиксация знаний, в том числе документирование всех процессов и поддержка документации в актуальном состоянии;

    • Использование перекрёстного обучения и других методик управления знаниями.

Вышло как-то коротко здесь. Но проблема на самом деле такая. Можно сказать, банальная. Чрезмерная самоуверенность и немного эгоцентризма. Нужно понимать, что помимо сеньоров в компании могут работать и невсезнающие специалисты, что говорить о ново-принятых. Для этого и нужна документация. Хорошо, когда применяются более очевидные решения в реализации кода, где будут использованы приёмы «против дурака». То есть, чтобы можно было сделать реализацию только одним способом и больше никак. Rust ведь за это любят, что он на уровне языка реализует приёмы «против дурака» (только не подумайте, что я топлю за Rust, там своих закидонов хватает).

Я лично сталкивался с тем, что специалистам уровнем выше меня просто плевать на документацию. Нет даже комментариев в коде. Ах да, чуть не забыл про комментарии в коде. Про них можно добавить. Что новым веяньем программисткой моды среди сеньоров является отказ от написания комментариев в коде. Об этом говорят уже давно, лет десять как уже (для программистов десять лет, это только период закрытой альфы). Об отказе от комментариев даже на Хабре писали специалисты из Яндекс. Комментировать код нужно, не весь, конечно, но в первую очередь тот, который выполняется неочевидно. Я стараюсь оставлять комментарии там, где я сам понимаю, что я не смогу сходу разобраться в коде, где явно будут проблемы с понимаем в будущем.

Вместо вывода

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

На этом всё. Спасибо за внимание

Комментарии (16)


  1. onets
    18.11.2023 19:56
    +9

    Это же про гейм дев?

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

    А код то в целом понятен. Каждый блок делает одну законченную вещь. Понятные входные/выходные данные. Без дублирования. Но из-за сложности процесса - тот или иной блок участвует в разных местах.

    И, знаете, с недавних пор я стал не любить отсутствие дублирования - потому что когда вижуал студия подсвечивает 5 reference над методом - это означает вплоть до 5! потенциальных комбинаций, которые мне предстоит раскопать, чтобы выяснить почему этикетки не печатаются. И только один приведет к победе ????

    Короче линейный лапшекод с дублированием - порой самый понятный код ????


    1. questor
      18.11.2023 19:56
      +6

      Мало того: после раскопать ты потом задумаешься какой метод починки применить так, чтобы починить у этого конкретного клиента и не поломать у всех остальных, про которых ничего вообще не знаешь. И повезло тебе, если дело обойдётся простеньким IF'чиком (дай бог, если ты всего лишь пятый кто ставит там IF, а не двадцать пятый!) и то стоит молиться, чтобы у остальных ничего не упало. А, ну да - хорошо если всё это покрыто тестами и надо всего лишь починить неработающие и добавить новые.


    1. AnimeSlave Автор
      18.11.2023 19:56

      В сфере бизнес приложений поверх понимания кода есть еще один уровень - это понимание бизнес процесса.

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

      ...линейный лапшекод...

      Я на этом месте чуть-чуть сломался, лапшекод линейным быть не может, потому-то он и лапшекод.


      1. onets
        18.11.2023 19:56
        +2

        Я в тот момент представлял себе спагетти в упаковках на полках магазинов ????


        1. MiyuHogosha
          18.11.2023 19:56

          это готовая библиотека компонентов и решений. Вроде MasterSCADA для АСУТП. Имеет право на существонание, часто вообще исключает прграммиста (только новый логический или визуальный элемент написать разве что). Но, это ограниченная сфера использования и интероперабельности.


    1. Ilya00657
      18.11.2023 19:56
      -1

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

      IMHO, различные комбинации – это следствие недостаточной атомарности функций.


  1. questor
    18.11.2023 19:56
    +5

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

    Но есть у меня и другой опыт, прямо противоположный и дело в том, что там тоже не всё гладко. Например, проект на 99% покрытый тестами (я не шучу), подробная документация сделанная аналитиками и грамотный онбординг от простых задач к сложным, с погружением в разные аспекты и нюансы. Нет проблем? Есть. Например, искать в огромной документации - это боль и отдельное искусство.

    Но в целом статья толковая, заслуженный плюс.


  1. Kreastr
    18.11.2023 19:56

    Суровая реальность. Сложные проекты сложны не смотря на документацию и тестовое покрытие. И дообучение (онбординг) сениора, разучившегося учиться занимает несколько месяцев.

    KISS


    1. AnimeSlave Автор
      18.11.2023 19:56

      Сложные проекты сложны не смотря на документацию и тестовое покрытие.

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


  1. ErshoffPeter
    18.11.2023 19:56

    А это вы ещё не сталкивались, похоже, с Data Driven programming - когда именно совокупность, корректно, полнота и так далее входных данных определяют поведение программы. Причём эти данные и их состояние - это целиком на совести юзверей, не очень или совсем неграмотных в этом вопросе. Вот тогда приходится предусматривать самые разнообразные обходные решения и метаалгоритмы по приведение входных данных к единому знаменателю.


  1. FadeToBlack
    18.11.2023 19:56
    +1

    Добро пожаловать в реальный мир! Сколько бы умных дяденков, изучивших перед написанием кода 20-30 опенсорс движков в свое время, ни программировали бы свои движки, стараясь сделать все правильно, сколько крутых движков уже готовых ни было бы доступно, суть разработки одна - взять и сделать все неправильно, а потом, истязая себя, жить с этим и страдать каждый день. И бесполезно говорить начальству "давайте не будем так, ладно?". Раньше я интересовался вакансиями по разработке движков, но пройдя несколько собеседований, ни одна компания не смогла ответить на вопрос, а зачем им, собственно, собственный движок? Как я потом понял, что они страдают от этого, и постоянно приходится кого-то нанимать на эту грязную работу.


    1. AnimeSlave Автор
      18.11.2023 19:56
      +4

      ...а зачем им, собственно, собственный движок?

      Я отвечу даже, если вам интересен ответ. Для других читателей.

      Решение о разработке своего движка в компании принимается по определённым причинам. Одна из основных причин — чтобы не зависеть от других разработчиков. То есть чтобы новые фитчи в движке появлялись, или исправлялись ошибки, не тогда, когда захочет компания-разработчик движка, а сразу, как появляется задача в бэклоге. Ещё одна причина — чтобы не было сюрпризом, что теперь что-то не работает, или работает не так. Недавняя ситуации с Unity яркий тому пример. Руководство Unity в одностороннем порядке поменяла механизм монетизации, по которому стоимость лицензии движка вырастала динамически (и в некоторых случаях существенно), и сделать точный расчёт финансовых затрат уже было бы нельзя. Ряд разработчиков, использующих Unity заявили, что, если новая монетизация начнёт работу, то они просто обанкротятся. Сообщество разработчиков начало бойкотировать Unity. Кто-то начал переход на другие движки. Кто-то стал заниматься разработкой своего собственного


  1. nivorbud
    18.11.2023 19:56
    +2

    Не вижу ничего необычного. Особенно если это касается нешаблонных новых проектов. Часто заранее не известно, каким именно будет новый проект, во что выльется, как пойдет и пойдет ли вообще. У заказчика есть общая концепция, идеи, но нет конкретики. Можно, конечно, целый год составлять ТЗ, утопая в бесконечных согласованиях и спорах о деталях и архитектуре проекта... А можно быстро "на коленке" запустить хоть в каком-то виде проект, ввязаться в драку, и сразу смотреть, что из этого выходит, анализируя реальную информацию, реальные грабли. Да, лапшекод. Да, костыли. Но уже имеется рабочий проект и уже имеется информация для анализа - для принятия решений, куда двигаться дальше. Не предположительно, а осознанно.

    Но как водится, дальше вступает в силу принцип: работает - не трогай...

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

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

    Еще момент. Надо учитывать, когда разрабатывался проект, в каком окружении. Если кто-то сейчас глянет на мой проект на джанго 15-летней давности, то он ужаснется, будет негодовать, рвать и метать... Но... надо просто откатиться на 15 лет назад и увидеть, что джанго тогда была еще в альфаверсии, 90% батареек и в помине не было...

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


    1. AnimeSlave Автор
      18.11.2023 19:56

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

      Вы правильно описываете суть «проекта на коленке». В бизнес терминологии это MVP, и в MVP нет ничего плохого. Совсем. Я неоднократно делал MVP. Потому что я сам понимаю важность на практике увидеть результат. Возможно еще это связано с визуализацией результата, типа увидеть глазами хотя бы цифры в отчёте. Проблемы начинаются в тот момент, когда менеджмент отказывается переписывать MVP на нормальную архитектуру. Но и здесь по опыту не все так плохо. Даже не смотря на плохой код, есть способы и методы этот код привести в надлежащий вид. Проблема в этот момент связана с тем, что на MVP обычно не разрабатывают полноценную документацию. Документация есть, но обычно не на код, а проектная. И тем более нет документации на уже имеющиеся проблемы. И потому, когда приходит новый разработчик, которого наняли на волне увеличения численности команды разработчиков, так как проект вышел в полноценную работу, то новый разработчик долго входит в понимание кода. И я лично как раз на этой стадии. Есть места в кодовой базе на текущем месте работы, которые я понимаю, так как уже «прошёл» их. А есть те, которые меня повергают в ступор, так как я не вижу логики в них. Будто результат нейросетки. Всё как бы работает, но при попытке что-то изменить - ломается. И ломается вообще в другом месте, как раз там, где ломаться по логике не должно


      1. nivorbud
        18.11.2023 19:56

        Да, здесь наверно проблема недопонимания подводных камней со стороны заказчика и разного рода менеджеров. Их отчасти понять можно: вот ведь всё работает, даже лучше, чем ожидалось, глаза горят, начинают сыпаться предложения о расширении по разным направлениям, короче все полны энтузиазмом... В итоге сложно обьяснить, что текущий вариант быстро запиленного кода надо рассматривать, как экспериментальный и надо будет притормозить и выделить достаточно времени для серьезного рефакторинга. И лучше это сделать на ранних этапах, пока сервис еще не сильно нагружен, клиентская база небольшая. Но зачастую, чувствую, всё это пропускают мимо ушей, хотя внешне соглашаются...


  1. nervoushammer
    18.11.2023 19:56
    +1

    Например, искать в огромной документации - это боль и отдельное искусство.

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