На первый взгляд все хорошо — имена функций выглядят разумно. В самом деле, во многих приложениях они точно соответствуют выполняемым операциям. А если для установления связи используется не коммутируемое подключение, а какой-то другой механизм? Например, модемы могут связываться на физическом уровне (как кабельные модемы, обеспечивающие доступ к Интернету во многих домах). А может быть, связь устанавливается посредством отправки номера порта коммутатору через интерфейс USB. Разумеется, концепция телефонных номеров в таких случаях относится к неверному уровню абстракции. Более правильная стратегия выбора имен в таких сценариях может выглядеть так:
public interface Modem {
boolean connect(String connectionLocator);
boolean disconnect();
boolean send(char c);
char recv();
String getConnectedLocator();
}
Теперь имена функций никак не ассоциируются с телефонными номерами. Они могут использоваться как для подключения по телефонной линии, так и для любой другой стратегии подключения.
N3: По возможности используйте стандартную номенклатуру
Имена проще понять, если они основаны на существующих конвенциях или стандартных обозначениях. Например, при использовании паттерна ДЕКОРАТОР можно включить в имена декорирующих классов слово Decorator. Например, имя AutoHangupModemDecorator может быть присвоено классу, который дополняет класс Modem возможностью автоматического разрыва связи в конце сеанса.
Паттерны составляют лишь одну разновидность стандартов. Например, в языке Java функции, преобразующие объекты в строковые представления, часто называются toString. Лучше следовать подобным стандартным конвенциям, чем изобретать их заново.
Группы часто разрабатывают собственные стандартные системы имен для конкретного проекта. Эрик Эванс (Eric Evans) называет их
N4: Недвусмысленные имена
Выбирайте имена, которые максимально недвусмысленно передают назначение функции или переменной. Рассмотрим пример из FitNesse:
private String doRename() throws Exception
{
if(refactorReferences)
renameReferences();
renamePage();
pathToRename.removeNameFromEnd();
pathToRename.addNameToEnd(newName);
return PathParser.render(pathToRename);
}
Имя функции получилось слишком общим и расплывчатым; оно ничего не говорит о том, что делает функция. Ситуацию усугубляет тот факт, что в функции с именем doRename находится функция renamePage! Что можно сказать о различиях между этими функциями по их именам? Ничего.
Функцию было бы правильнее назвать renamePageAndOptionallyAllReferences. На первый взгляд имя кажется слишком длинным, но функция вызывается только из одной точки модуля, поэтому ее документирующая ценность перевешивает длину.
N5: Используйте длинные имена для длинных областей видимости
Длина имени должна соответствовать длине его области видимости. Переменным с крошечной областью видимости можно присваивать очень короткие имена, но у переменных с большей областью видимости имена должны быть длинными.
Если область видимости переменной составляет всего пять строк, то переменной можно присвоить имя i или j. Возьмем следующий фрагмент из старой стандартной игры «Bowling»:
private void rollMany(int n, int pins)
{
for (int i=0; i
g.roll(pins);
}
Смысл переменной i абсолютно очевиден. Какое-нибудь раздражающее имя вида rollCount только затемнило бы смысл этого тривиального кода. С другой стороны, смысл коротких имен переменных и функций рассеивается на длинных дистанциях. Таким образом, чем длиннее область видимости имени, тем более длинным и точным должно быть ее имя.
N6: Избегайте кодирования
Информация о типе или области видимости не должна кодироваться в именах. Префиксы вида m_ или f бессмысленны в современных средах. Кроме того, информация о проекте и/или подсистеме (например, префикс vis_ для подсистемы визуализации) также отвлекает читателя и является избыточной. Современные среды разработки позволяют получить всю необходимую информацию без уродования имен. Поддерживайте чистоту в своих именах, не загрязняйте их венгерской записью.
N7: Имена должны описывать побочные эффекты