Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
###Cpp_лкц1_1.09_11_#дляБАК#29_01_12.doc
Скачиваний:
40
Добавлен:
29.04.2019
Размер:
6.42 Mб
Скачать

Глава 3. Технология создания программ

105

Локальные переменные предпочтительнее глобальных. Если глобальная переменная все же необходима, лучше объявить ее статической, что ограничит область ее действия одним исходным файлом.

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

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

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

Нельзя возвращать из функции ссылку на локальную переменную, потому что она автоматически уничтожается при выходе из функции, которая является ее областью действия. Не рекомендуется возвращать ссылку на переменную, созданную внутри функции в динамической области памяти с помощью функции та 11 ос или операции new, так как это приводит к трудно контролируемым утечкам памяти.

Следует избегать использования в программе чисел в явном виде. Константы должны иметь осмысленные имена, заданные через const или enum (последнее предпочтительнее, так как память под перечисление не выделяется). Символическое имя делает программу более понятной, а кроме того, при необходимости изменить значение константы это можно сделать всего лишь в одном месте программы.

Для записи каждого фрагмента алгоритма необходимо использовать наиболее подходящие средства языка. Любой цикл можно, в принципе, реализовать с помощью операторов goto и i f, но это было бы нелепо, поскольку с помощью операторов цикла те же действия легче читаются, а компилятор генерирует более эффективный код. Ветвление на несколько направлений предпочтительнее реа-лизовывать с помощью оператора switch, а не нескольких if, красивый способ передачи управления одной функции из группы — массив указателей на функции.

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

if (strstr(a. b) > 0 ) { ... }

else if (strstr(a. b) < 0 ) { ... } else if (strstr(a. b) == 0) { ... }

лучше написать

int is_equal = strstr(a. b);

if (is_equal > 0) { ... }

else if (is_equal < 0) { ... }

else { ... }.// здесь is^equal == 0

Если первая ветвь оператора if содержит передачу управления, использовать else нет необходимости:

106

Часть I. Структурное программирование

if (is_equal > 0) { ... break;} if (is_equal < 0) { ... return;} { ... } // здесь is_equal == 0

Бессмысленно использовать проверку на неравенство нулю (или, что еще хуже, на равенство true или fal se):

bool is_busy;

if (is_busy == true) { ... } // плохо! Лучше if (is_busy)

if (is_busy == false) {, ... } // плохо! Лучше if (!is_busy) char s[80];

while (fgets(s) != NULL) { ... } // плохо! Лучше while (fgets(s))

while(a == 0) { ... } // можно while(Ia)

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

В некоторых случаях условная операция лучше условного оператора:

if (z) i = j; else i = k; // лучше так; i = z ? j ; k;

При использовании циклов надо стремиться объединять инициализацию, проверку условия выхода и приращение в одном месте. Рекомендации по выбору наиболее подходящего оператора цикла были приведены на с. 49. При записи итеративных циклов (в которых для проверки условия выхода используются соотношения переменных, формирующихся в теле цикла), необходимо предусматривать аварийный выход но достижении заранее заданного максимального количества итераций.

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

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

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

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