eFusion 22 ноября 2019
1
5744

Бессмертные best practices в программировании на любом языке

Твоя обязанность как программиста – экономить время, ресурсы и деньги руководства. Мы решили поделиться с миром важными принципами чистого кода. Поехали!

Основные принципы

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

  • Осмысленные имена. Если имя объекта не соответствует его функционалу и назначению, то его следует переименовать во что-то подходящее. Если это невозможно – значит, что-то не так с функционалом, и код должен быть отрефакторен.
  • Повторное использование и гибкость. Различные модули приложения должны легко повторно использоваться в контексте одного проекта или легко переноситься в другой проект.
  • Единая ответственность. Любая сущность должна отвечать за один и только один функционал. Само собой, что все должно быть красиво и лаконично описано.
  • Простота. Код должен быть таким, чтобы через некоторое время, открыв его, ты смог понять суть. Постоянно просматривай свой код, как в первый раз.
  • Code review. Весь код каждого члена команды проходит через строгий анализ (в идеале, командный) и QA-тестирование до тех пор, пока не разрешатся все спорные моменты или пока они не будут покрыты TODO-комментариями.
  • Дальновидность и ошибки. Пиши свой код со взглядом в будущее, чтобы избежать дорогостоящих ошибок и багов, вызванных позже в процессе разработки.
  • Обслуживаемость. Это чуть ли не важнейший атрибут хорошего кода. Твоя писанина рано или поздно будет переписана/дописана, так что нет необходимости усложнять этот процесс.
  • "Магические числа" должны быть помещены в константы.
  • Функции и аргументы. Функция не должна принимать большое количество аргументов. Если аргументов слишком много, это может указывать на необходимость еще одной функции.
  • Код должен быть покрыт тестами. Если ты начал рефакторинг или реализацию новых фич, а тестами покрыт не весь код, есть большая вероятность появления ошибки, которая даст о себе знать впоследствии.
  • Защита от потенциальных уязвимостей. Особое внимание следует уделять уязвимостям кода, особенно когда он написан без учета его безопасности.

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

Функции

  • Избегай передачи boolean в функцию. Это намек на то, что код выполняет несколько действий, а это нехорошо.
  • Функции должны или делать что-то или отвечать на что-то, а не одновременно обе задачи. Это гарантирует, что со временем не вылезут скрытые побочные эффекты. Например, функция isPresent() должна возвращать только bool и ничего более не выполнять.
  • Для обработки исключений и для возврата кодов ошибок используй только блоки try-catch. Хорошо бы вообще вынести все в отдельный метод. Не смешивай данный код с остальным – это усложняет его читабельность.
  • Остерегайся выходных аргументов. Функция должна (если должна) изменить состояние своего объекта-родителя.
  • Код всегда должен быть разделен пустой строкой, чтобы объединить логические блоки вместе.
  • Реализация функции всегда должна следовать за ее вызовом.
  • Не возвращай значение null.

Объекты и структуры данных

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

Исключения

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

Комментарии

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

Организация кода

  • Каждый блок кода должен нести смысловую нагрузку. Эти блоки должны быть отделены друг от друга пустыми строками.
  • Локальные переменные должны быть объявлены как можно ближе к их использованию.
  • Переменные экземпляра должны быть объявлены в верхней части класса, так как в хорошо спроектированном классе они будут использоваться несколькими методами.
  • Если одна функция вызывает другую, вызывающая должна быть выше вызываемой (если это возможно). Это придает программе естественный поток.
  • Попробуй следовать "принципу наименьшего удивления" – любая функция или класс должен реализовывать поведение, которое было бы ожидаемым для другого программиста.

Тесты

Существует пять принципов тестирования – F.I.R.S.T (или Б.Н.П.С.С.). Расшифровывается это так:

  • Fast (Быстрота): тесты должны выполняться быстро, иначе их никто не будет запускать.
  • Independent (Независимость): тесты не должны зависеть друг от друга. Один тест не должен создавать условия для следующего. Ты должен иметь возможность запускать каждый тест независимо и в любом порядке.
  • Repeatable (Повторяемость): тесты должны быть повторяемыми в любой среде – в продакшене, в среде QA и на ноуте в метро без сети.
  • Self-Validating (Самопроверка): тесты должны иметь вывод типа boolean. Либо они проходят, либо терпят неудачу. Для того чтобы узнать результаты, не нужно лезть в файлик журнала.
  • Timely (Своевременность): тесты должны быть написаны своевременно.

Проектирование

  • KISS: Keep It Simple Stupid. Избегай ненужной сложности. Вопрос, который нужно задать в процессе кодинга: "Можно ли это написать проще?"
  • DRY: Don't Repeat Yourself. Результатом работы этого принципа является отсутствие необходимости внесения изменений в другие, логически не связанные элементы, при изменении единственного элемента системы.
  • YAGNI: You Aren't Gonna Need It. Суть принципа – отказ от создания избыточного функционала, в котором на данный момент нет необходимости.
  • Композиция лучше наследования. Сложный для понимания принцип, но все же. Классы должны достигать полиморфного поведения и повторного использования кода путем их композиции (путем содержания экземпляров других классов, реализующих желаемую функциональность), а не наследования от базового или родительского класса.
  • Удобочитаемость. Вопрос уже поднимался выше, но следует повториться. При работе над проектом (особенно в команде), всегда отдавай предпочтение читабельности над лаконичностью. Нет смысла иметь сжатый код, если его не понимают.

Литература

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

Если у тебя есть личные best practices – поделись в комментариях


РУБРИКИ В СТАТЬЕ

Комментарии 1

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

BUG