CHAP5 (1018805)

Файл №1018805 CHAP5 (Сборник литературы - С и С++)CHAP5 (1018805)2017-07-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла

Глава

5

Правила обычного программирования

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

50. Не путайте привычность с читаемостью.

(Или синдром "настоящего программиста, который может программировать на любом языке как на ФОРТРАНе"). Многие люди пытаются злоупотреблять препроцессором для того, чтобы придать С большее сходство с каким-нибудь другим языком программирования. Например:

#define begin {

#define end }

while ( ... )

begin

// ...

end

Эта практика ничего не дает, кроме того, что ваш код становится нечитаемым для кого-нибудь, кто не знает того языка, который вы стараетесь имитировать. Для программиста на С код станет менее читаемым, не более того.

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

typedef const char *LPCSTR;

LPCSTR str;

Подобные вещи вызывают проблемы с сопровождением, потому что кто-то, не знакомый с вашими соглашениями, будет должен просматривать typedef, чтобы разобраться, что происходит на самом деле. Дополнительная путаница возникает в С++, потому что читатель может интерпретировать происходящее, как определение объекта С++ из класса LPCSTR. Большинству программистов на С++ не придет в голову, что LPCSTR является указателем. Объявления С очень легко читаются программистами на С. (Кстати, не путайте вышеупомянутое с разумной практикой определения типа word в виде 16-битового числа со знаком для преодоления проблемы переносимости, присущей типу int, размер которого не определен в ANSI С и С++).

К тому же, многие программисты избегают условной операции (?:) просто потому, что она им кажется непонятной. Тем не менее, это условное выражение может существенно упростить ваш код и, следственно, сделать его лучше читаемым. Я думаю, что:

printf("%s", str ? str : "<пусто>");

гораздо элегантнее, чем:

if ( str == NULL )

printf( "<пусто>" );

else

printf( "%s", str );

Вы к тому же экономите на двух вызовах printf(). Мне также часто приходится видеть неправильное использование операций ++ и --. Весь смысл автоинкремента или автодекремента заключается в соединении этих операций с другими. Вместо:

while ( *p )

{

putchar ( *p );

++p;

}

или:

for ( ; *p ; ++p )

putchar ( *p );

используйте:

while ( *p )

putchar ( *p++ );

Этот код вполне читаем для компетентного программиста на языке С, даже если ему нет эквивалентной операции в ФОРТРАНе или Паскале.

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

struct tree_node

{

struct tree_node *lftchld;

};

#define left_child(x) ((x)->lftchld)

//...

traverse( tree_node *root )

{

if ( left_child(root) )

traverse( left_child( root ) );

// ...

}

Программист намеренно сделал определение структуры труднее читаемым для того, чтобы избежать конфликта имен между полем и совершенно необходимым макросом, и все из-за того, что ему не нравился внешний вид оператора ->. Для него было бы гораздо лучшим выходом просто назвать поле left_child и совсем избавиться от макроса.

Если вы действительно думаете, что программа должна внешне выглядеть как на Паскале, чтобы быть читаемой, то вы должны программировать на Паскале, а не на С или С++.

51. Функция должна делать только одно дело.

Это обычно не очень удачная мысль - записывать то, что должна делать функция, через ее аргументы. Это должно делать имя функции. Например:

UpdateAllViews( CView *sender, long lhint, CObject *phint )

{

// sender

lhint

phint

// NULL

xx

xx

Начальное обновление, вызываемое из обрамляющего окна

// Cview* //

//

0

CRect*

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

// Cview*

//

//

1

CRect*

Сообщение, посылаемое объектом CView* ("sender" - передатчик). phint сохраняет для CView* обрамляющее окно его клиента.

// ...

}

Вам нужны вместо этого три функции: initial_update(), update_embedded_object() и update_view(). Верным ключом для понимания того, что здесь что-то не так, является туманная природа имен аргументов. Функции не должны передаваться "намеки". Ей должны даваться указания.

52. Иметь слишком много уровней абстракции или инкапсуляции так же плохо, как и слишком мало.

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

struct tree_node;

struct child_ptr

{

unsigned is_thread;

struct tree_node *child;

};

struct tree_node

{

struct child_ptr left,

right;

};

tree_node *p;

if ( !p->left.am_a_thread )

p = p->left.child;

Следующий код лучше читается, потому что в нем меньше точек, и легче сопровождается, так как в нем нужно отлаживать на одно определение меньше:

struct tree_node

{

struct tree_node *left_child;

unsigned left_is_thread : 1;

struct tree_node *right_child;

unsigned right_is_thread : 1;

};

if ( !p->left_is_thread )

p = p->left_child;

53. Функция должна вызываться более одного раза, но...

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

Тем не менее, иногда выделение кода в функции меньшего размера существенно улучшает читаемость этого кода по причине устранения беспорядка. Однако эта практика - создание абстракции для части кода в виде имени функции - добавляет идентификаторы в область глобальных имен, и эта возросшая общая сложность является определенным минусом. Если я использую функцию этим способом - как абстракцию -, то обычно обяъвляю ее одновременно статической, чтобы к ней нельзя было получить доступ снаружи текущего файла, и встроенной, чтобы ее вызов не приводил к накладным расходам. Не доводите процесс функционального абстрагирования до крайности. Мне доводилось видеть отличные программы, доведенные абстрагированием до полностью нечитаемого состояния такой степени, что нет ни одной функции длиннее, чем 5 или 6 строк. Получающаяся программа работает также значительно медленнее, чем необходимо, и ее исходный текст в 5 раз длиннее, чем нужно.

53.1. Код, используемый более одного раза, должен быть помещен в функцию.

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

54. Функция должна иметь лишь одну точку входа.

Это правило применимо лишь к программам на С. Вообще, множество переходов goto к одной точке выхода лучше, чем много операторов return. Этим способом вы можете поместить точку прерывания у единственной точки выхода, вместо того чтобы возиться с несколькими прерываниями. Например:

f()

{

int возвращаемое_значение = ОШИБКА;

if ( некое_условие )

{

// ...

возвращаемое_значение = НЕЧТО;

goto выход;

}

else

{ // ...

возвращаемое_значение = НЕЧТО_ЕЩЕ;

goto выход;

}

exit:

return возвращаемое_значение;

}

Этот метод не срабатывает в С++, потому что функции конструктора вызываются неявно в качестве части объявления; объявление часто скрывает вызов функции. Если вы пропускаете объявление, то вы пропускаете и вызов конструктора. Например, в следующей программе деструктор для x вызовется, а конструктор нет:

foo()

{

if ( некое_условие )

goto выход;

некий_класс x; // Конструктор не вызывается. (Оператор goto

// перескакивает через него.)

// ...

выход:

// Здесь вызывается деструктор для x при выходе x из

} // области видимости.

Вследствие этой проблемы лучше всего совсем избегать переходов goto в программах на С++.

54.1. Всегда предусматривайте возврат значения из блока внешнего уровня.

Иногда, когда подпрограммы короткие, не стоит стараться обеспечить единственную точку выхода. (По моему мнению, правило "избегай запутанности" перекрывает любое другое правило, с которыми оно входит в конфликт). В этой ситуации всегда старайтесь убедиться, что из подпрограммы нет таких путей, которые не проходят через оператор return. Не так:

if ( a )

{

// ...

return делай_что_нужно();

}

else

{

// ...

return ОШИБКА;

}

а так:

if ( a )

{

// ...

return делай_что_нужно();

}

// ...

return ОШИБКА;

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

55. Избегайте дублирования усилий.

Следующий фрагмент демонстрирует эту проблему:

if ( strcmp(a, b) < 0 )

{

}

else if ( strcmp(a, b) > 0 )

{

}

else if ( strcmp(a, b) == 0 )

{

}

Вызов strcmp() в С связан с немалыми накладными расходами (как в Паскале и других языках программирования). Вам значительно лучше сделать так:

int cmp = strcmp(a, b);

if ( cmp < 0 )

{

}

else if ( cmp > 0 )

{

}

else // остается случай cmp == 0

{

}

56. Не портьте область глобальных имен.

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

  • Локальная переменная всегда более предпочтительна, чем член класса.

  • Член класса всегда более предпочтителен, чем статическая глобальная переменная.

  • Статическая глобальная переменная всегда более предпочтительна, чем настоящая глобальная переменная.

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

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

Характеристики

Тип файла
Документ
Размер
87,5 Kb
Тип материала
Высшее учебное заведение

Тип файла документ

Документы такого типа открываются такими программами, как Microsoft Office Word на компьютерах Windows, Apple Pages на компьютерах Mac, Open Office - бесплатная альтернатива на различных платформах, в том числе Linux. Наиболее простым и современным решением будут Google документы, так как открываются онлайн без скачивания прямо в браузере на любой платформе. Существуют российские качественные аналоги, например от Яндекса.

Будьте внимательны на мобильных устройствах, так как там используются упрощённый функционал даже в официальном приложении от Microsoft, поэтому для просмотра скачивайте PDF-версию. А если нужно редактировать файл, то используйте оригинальный файл.

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

Список файлов книги

С и С++ - сборник литературы
C++ Бархатный путь - Марченко А
cpp_001.shtml
cpp_002.shtml
cpp_003.shtml
cpp_004.shtml
cpp_005.shtml
cpp_006.shtml
cpp_007.shtml
cpp_008.shtml
cpp_009.shtml
cpp_010.shtml
cpp_011.shtml
cpp_012.shtml
cpp_013.shtml
cpp_014.shtml
cpp_015.shtml
cpp_016.shtml
cpp_017.shtml
cpp_018.shtml
cpp_019.shtml
cpp_020.shtml
cpp_021.shtml
cpp_022.shtml
cpp_023.shtml
cpp_024.shtml
cpp_025.shtml
cpp_026.shtml
cpp_027.shtml
cpp_030.shtml
cpp_034.shtml
Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7027
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее