Пособие по практике программирования

         

Имена


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


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

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

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

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




npoints, а вот numberO.f Points будет явным перебором.

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



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

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

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

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

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

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

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

? queue. queueCapacity 

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

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

queue.capacity+++;
n=queue.nusers()

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

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

now = date.getTime();
putchar( "\n-);

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

? if (checkoctal(c)) ...

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

 if (isoctal(c)) ...

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

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

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

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

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

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

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

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

? public boolean inTable(Object obj) {
? int j = this.getlndex(ob]);
? return (j == nTable);
? }

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

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

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

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

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



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

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


Содержание раздела