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

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

Основные правила

Нам, конечно, не нужны такие имена, как:

  • var number = 5;
  • var a = 42;
  • var abc = «Джон»;
  • и т.д

Эти имена бессмысленны, они не представляют для нас никакой ценности. Взгляните на этот код:

actvUsr(String text) {
   User usr = rpstry.find(text);
   usr.actv();
}

У нас есть метод actvUsr, который ожидает в качестве параметра текст String. Затем мы вызываем rpstry.find и находим пользователя по «тексту». Затем мы вызываем метод usr.actv ().

Фуу. Какой беспорядок. Имена даже трудно произносить. Если вы впервые увидите этот код, держу пари, вам будет сложно его понять. Даже если вы не впервые это увидите, будет сложно. Это ужасно. И этот фрагмент - всего 2 строки кода. Представьте, что было 20.

Если я хочу понять, что делает этот метод, мне нужно пойти и посмотреть, что такое «rpstry». Затем мне нужно перейти к методу find и посмотреть, какой параметр называется «text». Затем мне нужно перейти к методу actv () и посмотреть, что он делает. Мне нужно сделать так много работы, чтобы я мог понять 2 строчки кода, это безумие. Ладно, вы, вероятно, не увидите такого беспорядка, но я хотел высказать свою точку зрения. Если ваши имена паршивые, ваш код будет трудно читать.

Давайте проведем рефакторинг.

«actv» означает активировать, так что назовите это так. Таких сокращений делать не нужно, зачастую они непонятные. Этот стиль сокращения пришел из старых времен, когда у нас были очень маленькие воспоминания (размером в килобайты), поэтому каждый бит имел значение. Но сейчас не то время, память стоит дешево, а время разработчиков дорого. Поэтому вам нужно максимально упростить разработчикам понимание вашего кода.

Далее идет другая бессмысленная аббревиатура «usr». Это даже не сильно сокращает слово, просто затрудняет чтение. Поэтому мы переименуем его в user.

текст - это идентификатор пользователя.

rpstry - репозиторий. Вы можете переименовать его в репозиторий или репо, и то, и другое нормально и понятно.

Метод поиска назван нормально, но мы все еще не знаем, что находим. В данном случае это по id. Так что давайте переименуем его по своему усмотрению - findById.

И вот конечный результат:

activateUser(String id) {
   User user = repo.findById(id)
   user.activate();
}

Так лучше.

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

Также нужно обращать внимание на контекст. См. Следующий пример:

class UserService {
   public User getUserById(String id) {
      // TODO: implement
   }
}

У нас есть класс UserService. Внутри у нас есть метод getUserById. Давайте посмотрим, как мы будем вызывать этот метод снаружи:

UserService userService = new UserService();
userService.getUserById("USER_ID");

Обратите внимание на вызывающую линию: userService.getUserById. Это немного избыточно, правда? Если мы вызываем userService, мы знаем контекст и знаем, что будем работать с пользователями. Итак, вполне нормально вызвать метод просто getById:

class UserService {
   public User getById(String id) {
      // getting the user
   }
}
UserService userService = new UserService();
userService.getById("USER_ID");

Так-то лучше. Это не так уж и много, но уменьшает избыточность и делает код чище.

Как лучше писать имена классов

В названии класса должно быть существительное. Примеры для этого:

  • Велосипед
  • Человек
  • Планировщик
  • UserService

… И конечно:

  • HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor (это из реального проекта, вы можете погуглить)

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

Избегайте шумных слов вроде:

  • Процессор
  • Данные
  • Информация
  • Утилиты
  • и Т. Д.

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

Правило объема

Область действия означает - сколько раз и как далеко вы используете функцию, переменную или класс. Например, если у нас есть частный метод, который используется только один раз - это небольшая область. Если у вас есть частный метод, который используется 3 раза - это больший объем. Если у нас есть общедоступный метод, который используется 10 раз в разных классах, у нас большой объем. И так далее. Вы уловили идею.

Правило состоит в следующем: имя класса должно быть длинным, когда его область видимости мала, и коротким, когда его область видимости большая.

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

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

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

Как лучше писать имена методов

Названия методов должны быть глаголами. Примеры имен методов:

  • getName
  • fetchId
  • ускорение
  • ломать
  • вземиКолаПоМарка

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

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

class Account {
   public boolean isEmpty() { 
      // TODO: implement
   }
}

У нас есть класс Account с методом isEmpty. Когда мы используем этот метод в операторе if, он будет выглядеть так:

Account account = new Account();
if(accout.isEmpty()) {
   throw new Exception();
}

Обратите внимание, как легко читать оператор if:

Если учетная запись пуста, генерировать новое исключение.

Есть известная цитата Грэди Буча: Чистый код прост и понятен. «Чистый код читается как хорошо написанная проза. Чистый код никогда не заслоняет намерения дизайнера, а скорее полон четких абстракций и простых линий контроля ».

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

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

Например, класс File (из стандартной библиотеки Java):

Файл имеет открытый метод. Представьте, что вместо open он назывался openFileAndThrowIfNotFound:

Представьте, что вы вызываете этот класс по всему вашему коду. Это ужасно. Поскольку область действия функции open в классе File велика, имя маленькое. Гораздо проще просто вызвать File.open ().

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

Как лучше писать имена переменных

Часто имена переменных содержат объекты, то, что существует. Вот почему они должны быть существительными. Примеры имен переменных:

  • Пользователь
  • процессор
  • isExepted
  • commentList
  • и Т. Д.

логические переменные должны быть предикатами. Например:

  • isPlayable
  • shouldBeDeleted
  • заблокированы
  • и Т. Д.

Они должны хорошо читаться, когда помещаются в оператор if. См. Следующий пример:

if(isEmpty) {
   throw new Exception();
}

Вы слышали о «венгерских обозначениях»? Это соглашение об именах 80-х. Эта нотация описывает префиксы кодирования для разных типов переменных. Например:

  • b для логического - bBusy
  • ch для char - chInitial
  • c для подсчета предметов - cApples
  • f для числа с плавающей запятой - fBusy
  • fn для имени функции - fnSave
  • и Т. Д.

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

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

Например:

public void example() {
   int m; // this is the month of the year
   // implementation
   // implementation
   // implementation
   // implementation
   // implementation 
   // implementation
   // implementation
   // implementation
   // implementation
  [DO SOMETHING WITH m]
}

Посмотрите на вторую строку. Это не нормально. Да, если вы читаете эту строку, вы узнаете, что такое m, из-за комментария, но если вы посмотрите на его использование в строке 12 - вы не узнаете, что это такое. Вам следует найти объявление m и посмотреть, что это такое. Это простой пример, но представьте, что в методе есть 5 таких переменных. Это затруднит чтение кода. Вот почему вам следует сделать переменную более описательной:

public void example() {
   int month;   
   // implementation
   // implementation
   // implementation
   // implementation
   // implementation 
   // implementation
   // implementation
   // implementation
   // implementation
  [DO SOMETHING WITH month]
}

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

И, конечно же, у нас также есть правило области действия:

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

Правило здесь другое, потому что объем переменной, как правило, невелик (внутри метода). Если область видимости мала, в описательном имени нет необходимости, так как очень легко увидеть, что означает переменная. Давайте посмотрим на пример:

public FreelancePaidEmployer save() { 
   FreelancePaidEmployer freelancePaidEmployer = getEmployer();
   save(freelancePaidEmployer);
   return freelancePaidEmployer;
}

В этом случае переменная freelancePaidEmployer имеет очень маленькую область действия. И нам не нужно описательное имя для переменной, так как очень легко увидеть, что означает переменная и откуда она взялась. Позвольте рефакторингу:

public FreelancePaidEmployer save() {
   FreelancePaidEmployer e = getEmployer();  
   save(e); 
   return e;
}

Так-то лучше. Вы можете сделать их более наглядными, если хотите, но я не вижу в этом необходимости.

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

Давайте посмотрим на более абстрактный пример:

public void method() {
   int m; // this is the month of the year
   [USING THE VARIABLE HERE]
   // business logic
   // business logic
   // business logic
   // business logic
   [USING THE VARIABLE HERE]
   // business logic
   // business logic
   // business logic
   [USING THE VARIABLE HERE]
   [USING THE VARIABLE HERE]
   // business logic
   // business logic 
   // business logic
   // business logic
   // business logic
   [USING THE VARIABLE HERE]
}

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

public void method() {
    int month;
    [USING THE VARIABLE HERE]
    // business logic
    // business logic
    // business logic
    // business logic
    [USING THE VARIABLE HERE]
    // business logic
    // business logic
    // business logic
    [USING THE VARIABLE HERE]
    [USING THE VARIABLE HERE]
    // business logic
    // business logic
    // business logic
    // business logic
    // business logic
    [USING THE VARIABLE HERE]
}

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

Еще один совет - объявлять переменные как можно ближе к использованию переменной. Не делайте этого:

public void method() {
   var variable = new Variable();
   // business logic
   // business logic
   // business logic
   // business logic
   // business logic
   [USING THE VARIABLE HERE]
}

Здесь мы увеличиваем область видимости переменной, и в этом нет необходимости. Поскольку область видимости больше, нам нужно написать более длинное и информативное имя. И это не имеет смысла. Вы можете просто объявить переменную чуть выше ее использования. Как так:

public void method() {
   // business logic
   // business logic
   // business logic
   // business logic
   var variable = new Variable();
   [USING THE VARIABLE HERE]
}

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

Прежде чем вы уйдете - наш удивительный курс чистого кода

Если вам понравилась эта статья, вам понравится наш курс:

  • 39 лекций
  • 1,5 часа контента
  • Работа над реальным проектом, который проверит ваши знания
  • 27 загружаемых ресурсов
  • 30-дневная гарантия возврата денег

Вы можете записаться на курс здесь - Практика программного обеспечения и написание чистого кода