Чистый код. Создание, анализ и рефакторинг - страница 14

Шрифт
Интервал

стр.

Имя переменной, функции или класса должно отвечать на все главные вопросы. Оно должно сообщить, почему эта переменная (и т.д.) существует, что она делает и как используется. Если имя требует дополнительных комментариев, значит, оно не передает намерений программиста.

>int d; // Прошедшее время

Имя d не передает ровным счетом ничего. Оно не ассоциируется ни с временными интервалами, ни с днями. Его следует заменить другим именем, которое указывает, что именно измеряется и в каких единицах:

>int elapsedTimeInDays;

>int daysSinceCreation;

>int daysSinceModification;

>int fileAgeInDays;

Содержательные имена существенно упрощают понимание и модификацию кода. Например, что делает следующий фрагмент?

>public List getThem() {

>  List list1 = new ArrayList();

>  for (int[] x : theList)

>    if (x[0] == 4)

>      list1.add(x);

>  return list1;

>}

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

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

1. Какие данные хранятся в theList?

2. Чем так важен элемент theList с нулевым индексом?

3. Какой особый смысл имеет значение 4?

4. Как будет использоваться возвращаемый список?

Ответы на все эти вопросы не следуют из примера, хотя и могли бы. Допустим, мы работаем над игрой «Сапер». Игровое поле представлено в виде списка ячеек с именем theList. Переименуем его в gameBoard.

Каждая ячейка игрового поля представлена простым массивом. Далее выясняется, что в элементе с нулевым индексом хранится код состояния, а код 4 означает «флажок установлен». Даже простое присваивание имен всем этим концепциям существенно улучшает код:

>public List getFlaggedCells() {

>  List flaggedCells = new ArrayList();

>  for (int[] cell : gameBoard)

>    if (cell[STATUS_VALUE] == FLAGGED)

>      flaggedCells.add(cell);

>  return flaggedCells;

>}

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

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

>public List getFlaggedCells() {

>  List flaggedCells = new ArrayList();

>  for (Cell cell : gameBoard)

>    if (cell.isFlagged())

>      flaggedCells.add(cell);

>  return flaggedCells;

>}

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

Избегайте дезинформации

Программисты должны избегать ложных ассоциаций, затемняющих смысл кода. Не используйте слова со скрытыми значениями, отличными от предполагаемого. Например, переменным не стоит присваивать имена hp, aix, and sco, потому что они ассоциируются с платформами и разновидностями Unix. Даже если в переменной хранится длина гипотенузы и имя hp кажется хорошим сокращением, оно может ввести в заблуждение читателя кода.

Не обозначайте группу учетных записей именем accountList, если только она действительно не хранится в списке (List). Слово «список» имеет для программиста вполне конкретный смысл. Если записи хранятся не в List, а в другом контейнере, это может привести к ложным выводам[4]. В этом примере лучше подойдет имя accountGroup, bunchOfAccounts и даже просто accounts.

Остерегайтесь малозаметных различий в именах. Сколько времени понадобится, чтобы заметить незначительное различие в XYZControllerForEfficientHandlingOfStrings в одном модуле и XYZControllerForEfficientStorageOfStrings где-то в другом месте? Эти имена выглядят устрашающе похожими.


стр.

Похожие книги