Как писать повторяемый код

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

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

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

Книги

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

Цитата взята с книги "Человеческий фактор". По опыту проведения собеседований скажу, что это правда. Мы привыкли учиться программированию по статьям из Google и по ответам из именитого сайта StackOverflow. И это пугает. Я сторонник фундаментальных знаний, а их можно получить только читая книги и общаясь с людьми. Итак, от слов к делу.

Список книг

  • Практика программирования / The Practice of Programming. Фундаментальная книга о программировании. В ней описываются основные принципы написания и проектирования программ: алгоритмы и структуры данных, отладка и тестирование и так далее. Это одна из тех книг, которые считаются классикой и соответственно не стареют. Весь код в книге написан на C/C++.
  • Программист-прагматик / The Pragmatic Programmer. Пожалуй, это одна из моих любимых книг по программированию, правда есть одно но - новичкам она покажется сложной, так как зачастую они к этому времени ещё не столкнулись с проблемами из мира разработки ПО, как говорится "пороху ещё не нюхали".  В ней есть мысли на тему прагматичного подхода в разработке ПО: автоматизации процессов и разделению подсистем на независимые модули (достижение ортогональности). Must read!
  • Идеальный код / Beautiful Code. Книга-сборник практических примеров с интересными подходами в программировании. Например, в книге подробно расписано как реализован словарь в Python (dict), написание XML парсера и разбор алгоритма MapReduce.
  • Совершенный код / Code Complete. Без комментариев.

На деле хороших книг намного больше. Эта лишь малая их часть. Читайте много книг, учитесь жадно. Будьте одержимы!

Принципы написания хорошего кода

  • больше функций, меньше классов
  • правильное именование переменных и функций/классов
  • модульность кода
  • одно действие - одна функция
  • функция != процедура
  • расширяемость кода != повторяемость кода
  • наличие тестов
  • самодокументируемый код

Разберём каждый пункт по порядку.

Больше функций, меньше классов

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

Именование переменных, функций, классов

Очень важно давать объектам понятные и логичные названия. Сложно будет спустя длительное время после написания кода разобраться что делает функция под названием get_obj или что хранит в себе переменная xyz.

Модульность кода

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

Одно действие - одна функция

При написании функций или методов необходимо стремиться к философии Unix, где имеется огромное количество утилит, выполняющих строго заданную работу. Разбивайте код на множество функций, если вам кажется, что он выполняет слишком много работы. Не нужно в одном методе делать и генерацию PDF файла и его отправку по электронной почте - разбейте их на две независимых друг от друга функции. У меня есть негласное правило, что 1 функция/метод должна помещаться в видимую область экрана без необходимости делать прокрутку.

Функция != процедура

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

Функция возвращает значение. Процедура меняет состояние (имеет побочный эффект при выполнении). При написании старайтесь выбрать что-то одно. Либо вы возвращаете значение, либо меняете состояние объекта, который передаётся на вход, так код будет предсказуемым и коротким.

Расширяемость кода != повторяемость кода

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

Наличие тестов

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

Самодокументируемый код

Я не призываю отказываться от комментариев в коде, наоборот, их нужно и важно писать (с умом), но также не стоит забывать о том, что код должен быть написан так, чтобы читать его было приятно и легко (правильное именование объектов, четкое логическое разделение на модульные блоки). В Python имеются так называемые docstring, используйте их при описании функций и классов, чтобы облегчить жизнь себе и людям, которые будут читать ваш код.

З.Ы. Пишите код так, будто его в будущем будет читать маньяк, знающий где вы живёте :-)

Полезные ссылки