Что Такое Красивый Код И Как Научиться Его Писать

Меня зовут Маша, я автор курс С++ в Мастерской Яндекса.

Все вопросы, задачи курса, его тексты и описания решений — все это наша команда.

И сегодня я хочу поговорить о красоте кода.

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

Но сами правила и подход к пониманию красоты кода актуальны для любого языка.

Если совсем просто, то можно выделить три уровня красоты кода:

  1. Визуальный.

    Все дело в соглашениях по кодированию, правильных переменных, дизайне и т. д.

  2. Восприятие кода.

    О чувствах, которые испытывают люди при работе с вашим кодом.

  3. Продуманная архитектура.

    Это также важно и также относится конкретно к красоте кода.

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

Нет смысла оценивать нерабочий код с точки зрения красоты.

Теперь рассмотрим каждый пункт отдельно.



Что такое красивый код и как научиться его писать



Визуальная красота кода

Итак, о красоте.

Здесь нужно исходить из того, что вы как программист работаете не в вакууме; вы не какая-то единая боевая единица в замкнутом контуре.

На работе и в командах у вас есть коллеги.

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

Чтобы избежать субъективизма и вкусовщины в этом вопросе, ИТ-компании создают конвенции кодирования — стандарт форматирования кода.

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

В хорошем смысле этого слова.

Если не соблюдать эти правила, то получится, что одна функция в коде будет написана в одном стиле, а вторая в другом.

Это будет просто трудно читать.

Это как с книгой.

Представьте себе, что вы читаете книгу с хорошим содержанием, но половина ее страницы набрана шрифтом Times new roman 14, а половина — комиксом sans 16, тоже с хаотичным курсивом и несовпадающими заглавными буквами.

Кажется, прочитать можно, смысл не потерян.

То же самое и с кодом.

Это будет работать.

Но осадок останется.

Поэтому стандарты дизайна определяют, что именно (и почему) считается красивым кодом с точки зрения его дизайна в конкретной компании.

Есть руководства по стилю, которые гиганты пишут для себя.

Часто они выкладываются открыто, например, руководство по стилю от Google есть на Github. Вы можете взять его за основу и, если разделите его положения, использовать для создания своих.

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



Восприятие кода и его архитектура

Помните, что код должен быть хорошо организован.

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

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

И это не чисто визуальная проблема — ее будет сложнее понимать, модифицировать и поддерживать.

Кстати, о соглашениях по кодированию в этом ключе.

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

Или опытный наставник поможет вам исправить мелкие недочёты и сделать код красивее в процессе ревью.

Отчасти из-за невозможности четко регламентировать все и вся в отрасли возник феномен так называемого «вонючего кода», кода пахнет. Когда вроде бы перед тобой код, и даже он соответствует всем правилам компании, но что-то в нем все равно не так.

Чтобы избежать этого, полезно провести рефакторинг.

Примеры вонючего кода Начнем с совершенно безумной функции, нарушающей все возможные законы красоты.

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

  
  
  
  
  
   

// The function CalcElements counts how many elements is equal to arg int CalcNumOfVariousElements(const vector<int>& v, int condition) { int i = 0; int count = 0; vector<int>& tmp_v = const_cast <vector<int>&>(v); while (i != 10) { if (v[i] != condition) { tmp_v[i] = condition; count++; //ProcceedElementsCheck(v[i]); } i++; } return count; }

Этот код полностью соответствует соглашению о кодировании.

Но у него есть множество проблем, которые заставляют опытного программиста «почуять» что-то неладное.

  • Комментарий над функцией явно устарел.

    Такие комментарии сбивают с толку и могут даже быть опасными.

    На них нельзя положиться.

  • Имя функции не соответствует тому, что происходит в функции.

  • Переменная типа int названа словом «условие», что выглядит сомнительно с логической точки зрения.

  • В названии функции указано, что она должна подсчитывать элементы.

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

    Но внутри функции убирается константность и изменяются элементы контейнера! Пользователь вряд ли этого ожидает, а вызов такой функции потенциально небезопасен.

  • Магическое число 10, о котором никто ничего не знает, и вероятно в тот момент, когда его нужно будет изменить, о нем никто не вспомнит, и в программе появится ошибка.

  • Неактивный код (закомментированный вызов ProcceedElementsCheck) затрудняет чтение и навигацию по коду проекта.

    Есть ощущение прочтения черновика.

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

Следующие примеры будут менее очевидными.



Sphere makeSphere(double x, double y, double z, double radius, Color color);

Отличная функция, но у нее всего 5 аргументов.

Его вызов может выглядеть так:

Sphere sphere = makeSphere(CalcX(1, 2), other_sphere.GetY(), CalcZ(3, 2), 0.3241, SearchForColor(list_of_colors));

Чем больше аргументов, тем сложнее сконцентрироваться на том, какой параметр к чему относится.

Выполнив вызов такой функции до конца, вы чувствуете, что разгрузили машину.

Это тоже нелегко читать.

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



bool IsOKPressed(Screen scr) { for (int i = 0; i < scr.GetBtnList().

size(); ++i) { if (BUTTON_OK == scr.GetBtnList()[i].

GetType() && scr.GetBtnList()[i].

IsPressed()) { ShowOKScreen(); return true; } } return false; }

С этим примером в целом все хорошо, за исключением того, что у функции IsOKPressed есть побочный эффект. Если была нажата кнопка «ОК», эта функция отобразит соответствующий экран.

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

Еще один небольшой пример, который можно улучшить:

void CopyItemList(ItemList item_list1, ItemList item_list2) { for (int i = 0; i < item_list1.Size(); ++i) { item_list2[i] = item_list1[i]; } }

Эта функция выглядела бы намного лучше, если бы переменные были названы источником и назначением.

Нумерация переменных не дает никакой информации о том, какую функциональность они будут выполнять.

То же самое можно сказать и о таких префиксах, как «Данные», «Информация» или «Подробности».

Разница между классами ClientData, ClientInfo и ClientDetails не будет ясна никому, кроме создателя этих классов.

Когда младший программист немного подучился и чувствует себя уверенно, он рискует начать думать, что такой код он точно никогда не напишет. Эффект Даннинга-Крюгера как раз об этом.

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

do { //search for next record (can be before or after last record) while ((result = GetRecord(searchDirection == 1? lastIndex++: lastIndex--, Rec)) != false && Rec->field.InTime == 0); } while(loopIndex--);

Этот код работает. Он даже соответствует соглашению о кодировании внутри компании, в которой он был написан.

Но запах этого кода явно требует рефакторинга.

В некоторых особо запущенных случаях проще написать еще раз, чем пытаться понять, что хотел сказать автор.

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

Допустим, вы написали какой-то код. Прошло полгода, за это время вы успели поучаствовать в ряде проектов и написать, честно говоря, не одну сотню строк нового кода.

Стоит ли вам потратить время на то, чтобы оглянуться назад, просмотреть свой старый код и провести его рефакторинг? Ответ прост – обязательно.

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

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

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

В-третьих, вы избавите старый код от того самого запаха.

Поговорим еще немного о продуманности архитектуры.

Я имею в виду, насколько хорошо ваш код спроектирован с архитектурной точки зрения.

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

Просто потому, что его архитектура плохо продумана.

Красивый код — это код, который легко поддерживать.

О SOLID и других важных аспектах красоты кода рекомендую прочитать в книге Роберта Мартина «Чистый код».



Почему подростку нужно красиво писать?

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

Вы просто привыкнете красиво писать и будете воспринимать это как самый простой и подсознательный акт кодирования.

Конечно, начать красиво писать можно и в среднем, и в старшем возрасте.

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

Но как показывает практика, все сложнее.

Плюс не все люди готовы менять свои привычки.

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

Это также может быть полезно для юниора во время собеседования.

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

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

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



Что такое красивый код и как научиться его писать

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

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



Красота в динамике

Критерии красоты кода не могут быть высечены в камне и показаны новичкам в отрасли как истина в последней инстанции.

Эта концепция меняется со временем.

То, как люди программировали и писали код всего 10–20 лет назад, и то, как они делают это сегодня, — это очень разные вещи.

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

Открытый исходный код здесь оказывает неоценимую помощь — просто откройте последний популярный проект, который вас интересует, и посмотрите, как он создается.

На что.

Почему именно? Задавайте вопросы, оставляйте комментарии.

Не стесняйтесь открывать свои собственные проекты для сообщества и получать отзывы о них.

Это отличный стимул и возможность совершенствоваться.



Контрольный список

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

1. Следуйте правилам кодирования Даже если вы работаете не в компании, а фрилансере.

Даже если ты только учишься.

Именно на этом этапе закладывается привычка красиво писать.

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

IDE успешно автоматизируют эту рутину — изучите процесс: вы сэкономите время и освоите инструмент. 3. Пусть ваш код говорит сам за себя Сделайте это очевидным.

Коллега должен посмотреть код и понять, как все работает, даже если вы не оставили ни одного комментария.

Четкие имена переменных, классов, методов.

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

4. Изучите и следуйте принципам SOLID. Чтобы ваш код не рассыпался в прах, когда коллеги попытаются внести в него изменения.

5. Если можете, отправьте свой код на проверку кода.

Пожалуйста, обратите пристальное внимание на правки и комментарии, которые оставляются для вас.

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

6. Оставьте время на рефакторинг И, что немаловажно, после рефакторинга, когда ваш код уже стал новым и красивым, запустите тесты еще раз.

Есть вероятность, что код стал красивым, но что-то перестало работать.

И будет лучше, если вы заметите это на тесте.

Не коллеги по работе.

Или даже пользователь вашего сервиса на производстве.

7. Читайте код новых проектов с открытым исходным кодом.

Помогает вам оставаться в курсе новых практик и подходов.



Полезные книги и ресурсы

Роберт Мартин «Чистый код» (есть еще про SOLID)[ бумажная книга ] [ электронная книга ] Мартин Фаулер «Рефакторинг «Улучшение существующего кода»» [ бумажная книга ] Отличный ресурс по рефакторингу - refactoring.guru/ru/refactoring Инструменты автоматизации: Плагин Beautifier для различных IDE clang-формат Руководство по стилю Google C++ Теги: #Карьера в ИТ-индустрии #программирование #Образовательный процесс в ИТ #автоматизация #рефакторинг #Идеальный код #солид #Мастерская Яндекса #ревью кода #комментарии #Роберт Мартин #красивый код #Мартин Фаулер
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.