Главная

Что значит чистый код.

Рассказывай захватывающие истории с помощью хорошего кода.

Поделиться:
 

23+

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

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

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

Начнем.

Понятные названия переменных

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

Простое правило, которого нужно придерживаться при именовании переменных, состоит в трех вопросах:
❶ Зачем эта переменная вообще объявлена?
❷ Что она делает?
❸ Как она используется в коде?

Вот еще несколько дополнительных моментов, которые следует учитывать:

● Определение разницы между переменными не должно занимать много времени и усилий. Пример плохо названых переменных:

● Аккуратно используйте такие символы, как 1(один)l (L нижнего регистра)O(o верхнего регистра) и 0 (ноль).

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

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

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

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

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

Понятные функции

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

Функция:

❶ должна иметь строго определенный функционал.
❷ должна следовать принципу единой ответственности.(single responsibility principle)
❸ не должна изменяться, когда появляется новая задача. (должна следовать принципу open-closed).
(Если вы не слышали о двух упомянутых выше принципах, прочитайте о них здесь.)

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

Тело функции

● Функция должна либо что-то делать, либо возвращать что-то, но не одновременно. Либо она изменяет состояние объекта, либо она возвращает некоторую информацию об объекте. Выполнение всего сразу приведет к путанице в будущем.
● Функции должны быть небольшими. Это означает, что тело функции не должно превышать 20-ти строк кода.
● Отступы в функции не должны превышать более одного или двух уровней по сравнению с родительской строкой. Такой подход облегчает чтение и понимание.

Вот пример плохих отступов:

Блоки внутри ifelsewhile и т. д. должны быть длиной в одну строку. Если это длинная условная конструкция, то следует провести рефакторинг и сделать так, чтобы функция возвращала либо true, либо false.
+ длинное описательное имя функции лучше короткого, но непонятного имени.

Аргументы функции

Идеальное число: идеальное число аргументов, которое должна иметь функция, равно нулю. Если это невозможно, то рекомендуется использовать не более одного, двух или максимум трех (хотя последнего следует избегать). Более трех аргументов допускается только в очень особых случаях.
Зачем? Много аргументов неэффективно еще и с точки зрения тестирования. Представьте себе, как трудно писать тесты для всех комбинаций аргументов.
Проблема: если нет аргументов — все просто. Один аргумент — это не так уж сложно. Два аргумента — тут уже сложнее. Больше двух аргументов — тестирование становиться утомительным процессом. Этого можно избежать, если писать функции, которые принимают минимальное число аргументов.

Никогда не передавайте флаги: передача флагов (true / false) в качестве аргумента — ужасная практика. Таким образом вы нарушаете SRP(The Single Responsibility Principle) , поскольку ваша функция ведет себя различным образом в зависимости от переданного ей аргумента.

Но что тогда делать? Используйте объекты в качестве аргумента: объединение нескольких аргументов в один класс может показаться читерством, но на самом деле это не так. Когда имеется несколько аргументов, которые необходимо передать в функцию, они, вероятно, каким-то образом связаны друг с другом. Хорошей практикой является инкапсуляция этих полей в один класс.

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

Подход 1:

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

Подход 2:

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

Обработка Ошибок/Исключений

Функции обработки ошибок должны делать только это и не более.

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

Networking class:

UI class:

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

Улучшенный networking class:

Улучшенный UI class:

Даже если количество исключений увеличится, нужно будет просто выбросить исключения из networking class — и добавить больше блоков catch в класс UI class.
Кстати, такой подход также следует принципу openclosed.

Совет: если вы делаете несколько действий в блоках try / catch, разбивайте их на функции, чтобы ваш код выглядел более чистым и читабельным. Не захламляйте блок try/catch.

Заключение

Хороший программист — это писатель и он смотрит на свою программу, как на историю. Он выбирает подходящие конструкции своего языка программирования, чтобы более ярко рассказать историю, выраженную в программном коде. Функции — это глаголы языка, а классы/переменные — существительные. Искусство программирования заключается в том, чтобы правильно использовать данные инструменты, чтобы как можно лучше рассказать некую историю.
Спасибо!

23+