Проблема понимания существующего кода, или Как делать иногда [не] надо

от автора

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


ссылка на оригинал статьи https://habr.com/ru/articles/774856/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *