Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
kernigan_paik.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.91 Mб
Скачать

1.1. Имена

Что в имени? Имя переменной или функции помечает объект и со­держит некоторую информацию о его назначении. Имя должно быть информативным, лаконичным, запоминающимся и, по возможности, произносимым. Многое становится ясным из контекста и области види­мости переменной: чем больше область видимости, тем более информа­тивным должно быть имя.

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

int npending = 0; // текущая длина очереди ввода

Глобальные функции, классы и структуры также должны иметь осмыс­ленные имена, поясняющие их роль в программе.

Для локальных переменных, наоборот, лучше подходят короткие имена; для использования внутри функции вполне сойдет просто n, не­плохо будет смотреться npoints, а вот numberOfPoints будет явным пере­бором.

Обычно используемые локальные переменные по соглашению могут иметь очень короткие имена. Так, употребление i и j для обозначения счетчиков цикла, р и q для указателей, s и t для строк стало настолько привычным, что применение более длинных имен не принесет никакой пользы, а наоборот, может даже навредить. Сравните

? for (theElementlndex = 0; theElementIndex < numberOfElements;

? theElementIndex ++)

? elementArray[theElementIndex] = theElementIndex;

и

for (i = 0; i < nelems; i++)

elem[i] = i;

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

Существует множество соглашений и местных традиций именова­ния. К наиболее распространенным правилам относятся использова­ние для указателей имен, начинающихся или заканчивающихся на р (от pointer, указатель), например nodep, а также заглавных букв в нача­ле имен глобальных переменных и всех заглавных — в именах КОНСТАНТ. Некоторые программистские фирмы придерживаются более радикаль­ных правил, таких как отображение в имени переменной информации об ее типе и способе использования. Например, pch будет означать ука­затель на символьный тип (pointer to char), a strFrom и strTo — строки для ввода и вывода, соответственно. Что же касается собственно напи­сания имен, то использование npending, numPending или num_pending за­висит от личных пристрастий, и принципиальной разницы нет. Главное — соблюдать основные смысловые соглашения; все, что не выходит за их рамки, уже не так важно.

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

Пространства имен (namespaces) в C++ и пакеты (packages) в Java по­зволяют разграничивать области видимости переменных и тем самым помогают сохранить ясность кода без использования чрезмерно длин­ных имен.

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

Вот пример на языке Java, где имена членов класса не только слишком длинны, но и абсолютно непоследовательны:

? class UserQueue {

? int noOfltemsInQ, f rontOfTheQueue, queueCapacity;

? public int noOfUsersInQueue () {...}

? }

Слово "queue" (очередь) используется в названиях как Q, Queue и queue. Однако, поскольку доступ к очереди может быть получен только через переменную типа UserQueue, в именах членов класса упоминание слова "queue" вообще не нужно — все будет понятно из контекста. Так, двойное упоминание очереди

? queue. queueCapacity

избыточно. Класс лучше описать так:

class UserQueue {

int nitems, front, capacity;

public int nusers( ) { . . . }

}

поскольку выражения вроде

queue. capacity++;

n = queue. nusers( );

вполне ясны и понятны. Последняя версия тоже еще не идеальна: терми­ны "items" и "users" обозначают одно и то же, так что для одного понятия следовало бы использовать только один термин.

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

now = date.getTime();

putchar('\n');

Функции, которые возвращают логическое значение (истина или ложь — t rue или false), нужно называть так, чтобы их смысл не вызывал сомнений. Так, из вызова

? if (checkoctal(c)) ...

непонятно, когда будет возвращаться true, а когда false, а вот вызов

if (isoctal(c)) ...

не оставляет сомнений в том, что результат будет истиной, если аргу­мент — восьмеричное число, и ложью — в противном случае.

Будьте точны. Как мы уже решили, имя не только обозначает объект, но и предоставляет читателю некоторую информацию о нем. Неверно подо­бранное имя может стать причиной совершенно таинственных ошибок.

Один из нас написал и не один год распространял макрос, называе­мый isoctal, имеющий некорректную реализацию:

? #define isoctal(c) ((с) >= '0' && (c)<=’8’ )

вместо правильного

#define isoctal(c) ((с) >= '0' && (с) <= '7' )

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

В следующем примере имя и код находятся в полнейшем противо­речии:

? public boolean inTable(Object obj) {

? int j = this.getlndex(obj);

? return (j == nTable);

? }

Функция getlndex возвращает значение от 0 до nTable-1 в случае, если объект найден, и nTable, если объект не найден. Таким образом, возвра­щаемое логическое значение будет прямо противоположно тому, что подразумевается в имени функции. Во время написания кода это, может быть, не страшно, но, если программа будет дорабатываться позднее, да еще другим программистом, подобное неправильное имя наверняка ста­нет причиной затруднений.

Упражнение 1-1

Составьте комментарий, объясняющий принцип выбора имен и зна­чений в следующем примере:

? #define TRUE 0

? #define FALSE 1

?

? if ((ch = getcharO) == EOF)

? not_eof = FALSE;

Упражнение 1-2

Улучшите функцию:

? int smaller(char *s, char *t) {

? if (strcmp(s, t) < 1)

? return 1;

? else

? return 0;

? }

Упражнение 1-3

Прочитайте вслух следующее выражение:

? if ((falloc(SMRHSHSCRTCH, S_IFEXT | 0644, MAXRODDHSH)) < 0)

? .......

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]