Код-ревью это когда кто-то написал программу, а кто-то другой просматривает код программы и делает замечания – мол, вот тут хорошо, а вот тут плохо.
Совершенно случайно я узнал о существовании в Ютубе какого-то программиста под прозвищем Pirate Software. А узнал потому, что вокруг него разгорелся скандал. Дескать, он много лет прикидывался гуру, якобы работал в Blizzard, разработал собственную игру под названием HeartBound, и вдруг оказалось, что он и программировать-то не умеет, и игра у него вышла плохая.
Я ни разу не смотрел ни одного его видео, мне хватило тех вонючих волн, которые разошлись вокруг него. Чуть ли не десятки разных каналов практически одновременно выпустили ролики с разоблачениями Pirate Software и его игры. Оттоптались по полной программе (а куда они смотрели несколько лет и ничего не видели? Непонятно.)
И вот я открыл одно из таких видео, где разбирают код игры. И там типа, смотрите, он использует магические константы для чего-то там! Ужасно!
Что такое магические константы
В самом общем случае программа может иметь какие-то отличающиеся друг от друга состояния, параметры, статусы или типы данных, которые надо обрабатывать по-разному. Чтобы как-то обозначить эти сущности, мы можем просто их пронумеровать и затем использовать числа:
Нумерацию мы можем выбрать любого вида, руководствуясь какими-то собственными соображениями:
Эти числа что-то означают, но что именно, надо просто знать. В таком случае они называются магическими, потому что работают как заклинания.
Использование магических констант в коде – плохая практика, потому что совершенно непонятно, что они обозначают. Нужно откуда-то узнать их сокровенный смысл и потом постоянно держать его в голове.
Самый простой шаг к улучшению данного кода это использование не числовых, а мнемонических констант, например, заданных с помощью перечисляемого типа:
Так сразу становится понятно, что где происходит, и кроме того, упрощает переделку значений констант в случае необходимости.
Получается, правильно ругают?
Да, можно ругать код за использование магических констант, но есть нюанс. Я озвучу его немного позже.
Общее мнение таково, что код надо писать так, как будто после тебя его будет кто-то читать. Следовательно, надо писать такой код, чтобы он был понятен другим.
К примеру, вы приходите работать в "молодой дружный коллектив", или участвуете в каком-то опенсорсном проекте.
Очевидно, там будет общая кодовая база, куда вносят вклад, может быть, десятки человек, да в принципе достаточно и всего двух, чтобы поссориться. У этой базы должен быть общий стиль, общие архитектурные принципы. И главная задача это чтобы после того, как вы уволились и на ваше место пришёл новый человек, он мог бы разобраться в коде.
И вот вы, к примеру, пишете тестовое задание, чтобы устроиться в такое место, или уже работаете там и отправляете свой первый коммит в репозиторий. Но сначала его проверит мудрый сеньор. А может быть, вы и есть тот мудрый сеньор, и проверяете код новичка.
Нужно свыкнуться с фактом, что ни одно код-ревью никогда не будет на 100% беспристрастным и объективным. У каждого программиста есть уникальный опыт программирования и сложившиеся привычки, которые будут на него влиять.
Этот опыт может включать что угодно. Смотря где, над чем, и на каких языках он работал, что ему понравилось, а что нет, зачесалась ли у него левая пятка или нет. Всё это повлияет.
Феномен разных языков
Достаточно взглянуть на синтаксис и методические рекомендации для разных языков. В Python, Rust, Java, C#, Kotlin, Go есть функции. Функция это функция, у неё всегда один смысл. Но почему в разных языках она пишется то function, то fn, то def, то func, то fun, то вообще никак? Ведь кто-то придумывал очередной язык, и что-то заставляло его сделать не так, как было раньше.
Или вот почему в одних языках принято методы называть вот так: add_value(), а в некоторых вот так: addValue()? А вот в C# решили быть совсем не как все и сделать вот так: AddValue().
В чём смысл? Делает ли это язык лучше, быстрее, понятнее? С точки зрения его создателей – да. А так нет, конечно. Просто очередной язык с какой-то своей религией. Просто вот так кому-то захотелось. На основании какого-то прошлого опыта, прежних ошибок груза, который у каждого был свой.
Никто вас не знает
Поэтому и сеньор, который будет смотреть ваш код, будет это делать исключительно так, как ему нравится и как он привык. У него уже комплекс гуру. Он уже давно тут работает, ему хорошо и стабильно платят, у него корпоративные обеды и жизнь вообще удалась. И вот он приходит с обеда, сыто порыгивая котлеткой и посасывая электронную сигарету, и садится делать ревью кода, намётанным глазом отмечая огрехи.
Конечно, бывает откровенно плохой код. С откровенными ошибками и откровенно неээфективными решениями. Тут спора нет. Плохо значит плохо.
Но часто это просто код, не хороший и не плохой, и в любой момент можно придумать любое требование, которое в нём будет или не будет выполняться.
Никто реально не знает, почему вы написали именно так, а не иначе. Вы переварили это в своей голове, но процесс был скрыт от других. Может быть, вы специально использовали какую-то конструкцию, потому что у вас были какие-то конкретные соображения на этот счёт, но эти соображения никому не интересны. Вас отсеют просто по внешним признакам.
Как-то на одном собеседовании мне дали задание: написать симулятор очереди у кассы, где разные персонажи обслуживаются по-разному (задерживаются, пропускают ходы и т.д.). Я написал. Оно работало.
Мне же дали отказ с формулировками, что "оно не масштабируемо". Что было весьма спорно – а может, вы просто не знаете, как его масштабировать? Но в любом случае, о необходимости масштабирования в задании не было ни слова. Я считал, что это задание на знание алгоритма обслуживания очередей, и реализовал сам алгоритм.
Завернул его какой-то конкретный человек, у которого в этот момент чесалась левая пятка.
После этого я некоторое время ходил какой-то виноватый. Вроде и старался, а оказался плохим программистом – не масштабируется, видите ли. Не был достаточно дальновидным и мудрым. Но потом понял, что никакой вины у меня нет и код я написал хороший. Пусть обходятся без меня.
Был и другой случай с тестовым заданием, где вместо того чтобы обращать внимание на недостатки, внимание обращали на достоинства, и это гораздо более позитивное и справедливое отношение.
Но в целом, я не про найм. А про то, что любое код-ревью по большей части субъективно и местечково (обусловлено конкретным местом работы и религиозным фанатизмом проверяющего), если речь не о явных грехах.
И перейдём наконец к главному. Если любое код-ревью субъективно, то код-ревью, направленное на разоблачение известного ютубера, будет ещё более субъективным. Ведь это повод выложить целый ролик, который наберёт кучу просмотров.
Тут я хочу ещё раз повторить, что не знаю, кто этот известный ютубер, и справедливо ли его ругают. Может, всё на 100% справедливо и он полностью заслуживает той волны ненависти, которая его накрыла. Но как я ранее говорил, есть нюанс. И он озвучивается так:
Какое ваше собачье дело?
Почему-то за мантрами "код будет кто-то поддерживать" забывают о том, что бывает такой код, который принадлежит только автору и больше никому. И поддерживать его будет только сам автор, и больше никто. Да и автор скорее всего не будет, он напишет его просто один раз и всё.
И даже если обосновывать тем, что код будет выкладываться в общий доступ, и его будет смотреть множество людей, всегда есть код, который никуда не выкладывается и никому не показывается. А если и выкладывается, то выкладывается как есть, и живите с этим.
Иначе говоря, если автор пишет свою игру в одиночку и никого не просит ему помогать, то кому какое дело до того, КАК он её пишет?
Игра есть? Есть. Она работает? Работает. Какие вообще претензии? Код вам не нравится? Магические константы используются, говорите? Ну да, используются, а вам-то какое дело?
Может быть, он ХОЧЕТ их использовать? Может, это для вас плохо, а для него нет, и он прекрасно в этих константах разбирается? Не приходило такое в голову?
И наконец, самый обескураживающий вопрос: обозреватели, а где ваши игры-то, написанные вами? Как это нет?
Я нисколько не защищаю Pirate Software, скорее всего он действительно негодяй, прохвост и жулик, просто противно видеть эту массовую травлю и шакалий вой "ну всё, ему конец!" Целая куча (не шучу, целая куча) C++ и прочих ютуб-гуру бросилась разбирать его игру и его код, не имея за душой ничего, что можно показать взамен.
У меня есть один старый друг, и когда-то он написал на Паскале игру "Стартрек", ну вы знаете, ремейк той самой текстовой про клингонов.
Сказать объективно (и совершенно не в упрёк ему), программировал он слабо. При просмотре листинга программы у меня волосы вставали дыбом и руки сами тянулись всё исправить. Код был просто ужасный.
Примерно в то же время я тоже писал свою версию такой игры. Так как я считал себя крутым, то писал сразу на ассемблере.
Знаете, в чём была разница между его игрой и моей игрой?
Его игра была закончена, а моя нет.
Кто в результате оказался лучший программист? Конечно, он.
Теперь представим ситуацию, что его уже готовую игру вдруг понадобилось поддерживать. И допустим, пришлось мне.
Ай-яй, что же делать, ведь плохой код трудно поддерживать! Наверняка там были и магические константы и прочие ужасные вещи. Но нет, я разобрался в этом коде элементарно. Поддерживать его, в случае необходимости, не составило бы труда. Этот код был плохой, потому что был наивный. А наивный код это вполне себе понятный и предсказуемый код.
Такие вот дела.