Текст к видео "Code review (код ревью) и чистый код" на канале YouTube
Всем привет. Тему сегодняшнего видео мне подсказал зритель в комментариях к одном из видео. Code review и рефакторинг кода. Данные темы популярны на собеседованиях.
Задание сводится к тому, что вашему вниманию предлагается некоторый код и вам необходимо его улучшить, проверить, сделать code review и указать недостатки. Я и сам
практикую такие задания на собеседованиях, где я выступаю в качестве рекрутера.
Данные задания можно поделить на 2 класса – плохие и хорошие. К плохим заданиям с code review я отношу все задания такого типа, где проверяется знание каких-либо библиотек,
сигнатур методов и синтаксиса на память. Эти задания не имеют смысла, потому что если вы ошибетесь в синтаксисе в процессе работы, то ваша среда разработки, например Visual
Studio, вам обязательно об этом сообщит. То есть нет необходимости помнить точное название метода и какие аргументы он принимает – будет достаточно знать, что существует
такой метод и что в результате его работы мы можем получить определенные данные. Возможно у вас своя точка зрения на этот вопрос, будут рад её узнать в комментариях и поддержать
дискуссию на эту тему.
К хорошим заданиям с code review я отношу все остальные задания, не связанные со знанием синтаксиса наизусть. Я не могу сказать за остальных рекрутеров, но я лично на здании
code review обращаю внимание как мыслит и что важно в коде для человека, который данное code review проводит. То есть на что кандидат обращает внимание, а что упускает из виду.
Оба эти момента могут сказать многое о способностях кандидата, его навыках и отношению к работе, точнее о его культуре работы.
Перед созданием данного видео я долго думал, как лучше это сделать. Первой и самой простой идеей было показать моё задание на code review, но по понятным причинам я не могу это
сделать. Второй идеей было взять свой старый код и вместе с вами его рефакторизовать попутно обращая внимание на все его недостатки. Неплохо, но это подготовит вас только к тем
ошибкам, которые я допустил в прошлом, а мы говорим о задании code review вообще, более глобально. Поэтому возникла третья идея. Прежде чем говорить о code review конкретного
кода, давайте разберемся, что можно назвать хорошим кодом и если мы будем понимать, какой код является хорошим, то нам будет легче искать ошибки и недостатки во время code review
на собеседовании или в повседневной жизни программиста.
Во время подготовки данного видео я очень интенсивно использовал книгу Роберта Мартина «Чистый код». Естественно, я её уже несколько раз прочитал. Перечитываю её я для того, чтобы
не забывать, как хороший и чистый код должен выглядеть. Ссылки на данную книгу будут в описании к данному видео.
Каждый из нас может определить, насколько чист и хорош наш код задав себе 4 вопроса:
Можно ли мой код протестировать? Написал ли я соответствующие юнит – тесты чтобы это проверить? Я еще не рассматривал юнит – тестирование на моём канале, но после выпуска
такого видео в будущем вы будет в состоянии ответить на данный вопрос.
Будет ли мой код понятен другим программистам? Поймут ли они мой замысел и мои намерения, когда они увидят то, что я создал? Так сложил, что в компаниях с Вашим кодом будут
работать также и другие программисты, чем легче им будет понять то, что вы написали, тем более качественней будет их работа.
Пойму ли я сам то, что я написал несколько месяцев назад? Иногда так бывает, что автор кода сам не может понять, что он сделал. Обычно это плохой знак, который свидетельствует
о низком качестве кода.
Можно легко изменить мой код, попутно не испортив что-нибудь? На этот вопрос порой тяжело ответить, но если вы будет следовать принципам «чистого кода» и принципам SOLID,
то скорей всего ответ на этот вопрос будет «Да, можно легко изменить и ничего при этом не испортить».
Далее я представлю несколько правил связанные с объектно-ориентированным программированием, паттернами проектирования и принципами SOLID:
Композиция всегда лучше, чем наследование. Почему? Потому что класс, который состоит из компонентов легче протестировать, создав мок-объекты определенных компонентов.
О мок-объектах или объектах – имитациях мы поговорим в видео посвященному юнит-тестам. Каждый отдельный компонент сам по себе должен легко поддаваться тестированию.
Необходимо использовать компоненты, которые слабо связаны между собой, то есть использовать интерфейсы и абстрактные классы. Почему? Потому что если между компонентами
существует слабая связь, то шансы, что ваши изменения в одном компоненте испортят что-то в другом компоненте минимальны.
Необходимо делать так, чтобы ваш код зависел от абстракций, а не от конкретных реализаций. Почему? Потому что абстракции легче заменить, то есть код легче изменить. И к
тому же это соблюдение принципа D SOLID – инверсии зависимости.
Чем класс меньше, тем лучше. Почему? Принцип S SOLID. У каждого класса должна быть одна ответственность. Если класс достаточно большой, то скорей всего принцип S нарушен.
Чем меньше интерфейс, тем лучше. Почему? Принцип I SOLID, то есть принцип разделения интерфейсов. Если интерфейс достаточно большой, то скорей всего для него тяжело написать
отдельную имплементацию. В этом случае польза от использования данного интерфейса невелика. То есть возникает вопрос почему мы должны использовать интерфейс, который тяжело
реализовать?
Чем меньше части кода (классы, методы), тем легче их понять.
До этого момента мы говорили о качественном коде обобщенно. Теперь пришло время посмотреть на конкретные элементы кода и научиться отличать хороший код от не очень хорошего.
Таких элементов будет 6.
Правильное использование названий
названия переменных и классов должным быть такими, чтобы их можно было легко прочитать. Сравните “sqrTri” и “squareOfTriangle”. Естественно, второй название прочитать легче.
стоит избегать использования «магических цифр», то есть названий в стиле “label1”, “label2”, “label3”…
не используйте тип переменной в названии переменной, например «RatioString». Здесь слово «String» избыточно. Если Вы используете для работы с кодом среду разработки, а не приложение Блокнот, то вы всегда будете в состоянии определить какой тип имеет переменная или объект, без дополнительных указаний в названии переменной.
названия объектов и классов должны быть существительными. Желательно на языке, который понимают все программисты, которые работают с кодом. Как правило это английский.
названия методов и функций должны быть глаголами
чем короче название, тем лучше, но всё равно надо постараться чтобы имя было описательным
Замечания к функциям и методам
метод должен решать только одну задачу, и он должен делать это идеально;
название метода должно быть описательным.
чем меньше число аргументов метода, тем лучше; идеально число аргументов метода – 0, например DoSomething();
использование блоков try / catch. Обработка исключений — это отдельная операция и она должна быть отдельна от основной части кода. Если мы используем блок try / catch в
теле метода, то первым словом в теле метода должно быть слово try и последними выражениями в теле метода должны быть выражения catch / finally. Не должно быть блоков try / catch
где-то в середине тела метода.
Комментарии
Хорошие комментарии (вообще хорошим комментарием является тот комментарий, который никогда не был написан). Всё-таки иногда комментарии необходимо написать и на это у вас
есть определенный список причин:
юридические комментарии в начале кода приложения о правах и лицензиях – сейчас такие комментарии практически не используются – функцию такого комментария принял текстовый
файл с текстом лицензии. Но если вы все-таки работаете с очень старым кодом, то такой тип комментария может быть только в одном указанном ранее месте.
общие информационные комментарии в начале кода приложения. Опять-таки, как и юридические комментарии, данный тип комментария признак старого кода. В современных приложениях
эта информация указывается в файлах readme.
комментарии, которые объясняют выбор данного технического решения – например вы можете написать в комментарии, что для работы с базой данных вы выбрали технологию ADO.Net,
потому что на тот момент в вашей команде мало кто знал фреймворк Entity Framework.
комментарии, которые предупреждают о последствиях – например, вы можете указать, что если будет что-то удалено из кода, то возможно перестанет работать какая-то услуга или
определенная функциональность будет работать неправильно.
комментарии ToDo, то есть комментарий «сделать в будущем» - если вы видите что-то в коде, что требует улучшения, но в данный момент, у вас на это нет времени, то можете
оставить этот комментарий на будущее. Существуют приложения, например ReSharper, которые могут найти все такие комментарии в коде и на их основании создать список заданий
комментарии к публичным методам, которые используются в API – если Вашей библиотекой кто-то пользуются, то было бы неплохо этому кому-то объяснить как использовать вашу
библиотеку.
Плохие комментарии – если вы видите такой комментарий, то сразу его удаляйте без оглядки:
комментарии, которые не вносят ничего нового, например комментарий «Это метод Add»
повторение одних и тех же комментариев в различных частях кода
комментарии, которые не имеют смысла или вообще могут натолкнуть на неправильное понимание кода
не пишите комментарий, когда есть возможность написать короткий метод или добавить свойств с описательным названием
вообще комментирования кода – это плохая привычка. Удаляйте комментарии, если считаете, что они не вносят ничего нового. Если кому-то будет нужен удаленный комментарий,
он сможет найти его в истории изменений файла.
помните, что всё комментарии, когда-то станут не актуальными, то есть кто-то изменит код, но оставит без изменений комментарий который относится к данному коду. Если вам
все-таки не удалось избежать добавления комментарий, добавьте к нему дату, чтобы сразу было понятно через несколько лет на сколько данный комментарий стар.
не пишите слишком длинные комментарии. Их и так никто не будет читать, а даже если и прочитают, то не факт, что читатель поймёт прочитанное.
4.Исключения
всегда необходимо выбрасывать исключение, а не код ошибки
необходимо помнить о правильной обработке исключений в методах
никогда не возвращайте в методах значение null, используйте паттерн «Пустой объект» или паттерн «Объект по умолчанию». Например, возврат пустой коллекции лучше, чем
возврат null или возврат пустой строки всегда лучше возврата null.
Никогда не передавайте в качестве аргумента значение null. Если вы написали метод для которого аргументом по умолчанию является величина null, то стоит сделать рефактор
этого кода и избавиться от таких аргументов.
не пишите ваш код в защитной манере, то есть проверяя всё и всея, если только вы не должны это делать, например при работе со старым кодом. Если вы не будете принимать
и возвращать значения null, то вы избавите себя от необходимости постоянных проверок на null объектов в вашем коде
5.Юнит тесты – о них я сниму отдельное видео, ну а пока очень-очень коротко пару слов на эту тему:
их необходимо писать
они должны быть маленькими
необходимо использовать подход AAA: arrange, act, assert.
необходимо использовать подход ACID: atomicity, consistency, isolation, durability.
одна проверка на один тест или по крайне мере несколько проверок должны касаться одной определенной функциональности
6.Классы
должны быть маленькими
принцип S – единственная ответственность
зависимость от абстракций, то есть возможность использования внедрения зависимостей
Сегодня мы познакомились с сухой теорией о том, что может называться чистым кодом. Если вы знаете, что такое чистый код, то увидев код, который требует поправок, вы сразу
поймёте, что необходимо изменить. В следующем видео я напишу код, который будет нарушать всё то, о чём я сказал ранее. Мы вместе исправим этот код, а кроме того, в следующем
видео я оставлю пример кода, который необходимо исправить с точки зрения чистого кода. Для вас это будет своего рода домашним заданием. Поэтому если вы не подписаны, то
рекомендую подписаться, чтобы не пропустить это видео. Ну а пока мне пора заканчивать. Если данное виде показалось вам интересным, то благодарю за лайк и комментарий. Спасибо
за внимание и до новых встреч.