Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Питер_Гудлиф_Ремесло_программиста_Практика_написания_хорошего_кода.pdf
Скачиваний:
16
Добавлен:
19.04.2024
Размер:
9.23 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

2. Тонкий расчет

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

585Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

a.Насколько легко делать это систематически? Не забываете ли вы о необходимости проверки ошибок?

b.Можно ли каким то образом облегчить себе написание защитного кода, более скрупулезно проверяющего ошибки?

Это противоестественно для любого человека; ждать худшего от своего тщательно отшлифованного нового кода – противоречит инстинктам программиста. Всяких неприятностей вы ждете только от тех, кто бу% дет работать с вашим кодом. Им же далеко до вашей добросовестности!

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

Глава 2. Тонкий расчет

Вопросы для размышления

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

Обычно лучше всего оставить «исторический» код в том виде, какой он есть, даже если он уродлив и с ним трудно работать. Я стал бы пере% форматировать его только при абсолютной уверенности, что никто из первоначальных авторов никогда не вернется к этому коду.

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

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

2.Распространена система, при которой исходный текст располагается в фиксированном количестве колонок. Каковы ее преимущества и не достатки? Есть ли в ней смысл?

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

586m

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Ответы и обсуждениеClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Данный вопрос, как и другие вопросы представления, не имеет одно% значного ответа; в значительной мере это дело личного вкуса.

Я предпочитаю разбивать свой код так, чтобы он умещался на экране с 80 колонками. Я всегда так делал, поэтому тут важную роль играет привычка. Я не имею ничего против тех, кто любит длинные строки, но мне кажется, что с длинными строками труднее работать. Я на% страиваю свой редактор так, чтобы он переносил длинные строки, а не показывал горизонтальную полосу прокрутки (горизонтальная про% крутка неудобна). В таких условиях длинные строки обычно портят весь эффект отступов.

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

На практике в C++ образуются очень длинные строки. Это более мно% гословный язык, чем C; он приводит к вызову членов%функций объек% тов, на которые ссылаются другие объекты с помощью контейнеров% шаблонов… Существуют способы управиться с обилием появляющих% ся при этом длинных строк, один из которых – сохранение промежу% точных ссылок во временных переменных.

3.В какой мере следует детализировать стандарт кодирования?

a.Насколько строго следует придерживаться выбранного стиля? Ка кие наказания могут быть за уклонение от него?

b.Допустим, что стандарт оказывается непомерно мелочным и огра ничительным. Каковы могут быть последствия?

За отклонение от любого стандарта кодирования следует отрубать все шесть ног.

Правильный ответ весьма зависит от того, насколько всеобъемлющ стандарт кодирования и какова принятая у вас культура кодирова% ния. Обычно есть более серьезные проблемы, чем не там поставленная скобка, но по поводу скобок проще предъявлять претензии. Я видел много стандартов, которые были настолько ограничительными и пара% лизующими, что несчастные программисты просто напрочь игнориро% вали их. Чтобы приносить пользу и быть принятым, стандарт кодиро% вания должен оставлять некоторое место для маневра, при этом жела% тельно привести лучший практический подход в качестве примера.

4.Если создается новый стиль представления, какое количество объек тов или ситуаций следует регламентировать? Какие дополнительные правила представления следует установить? Перечислите их.

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

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

2. Тонкий расчет

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

587Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

Поля кода

Левый край кода определяется количеством пробелов для отступа. Часто встречаются отступы в два или четыре пробела, хотя некото% рые программисты дипломатично выбирают три. Чем меньше от% ступ, тем реже вы будете залезать на правое поле, но при этом соз% дается впечатление тесноты и труднее различать уровни вложенно% сти. Большие отступы выглядят более отчетливо, но при этом быст% ро кончается место в строке.

Что использовать для отступов – пробелы или табуляцию – давний спор, в котором не один программист потерял здоровье. Пробелы лучше переносимы; в любом редакторе они выглядят одинаково. При показе кода пропорциональным шрифтом1 табуляция обеспе% чивает лучшее выравнивание.

Ширина страницы определяет форматирование правого края кода. Можно ограничить строки фиксированным количеством колонок или никак не ограничивать их, что потребует горизонтальной про% крутки окна. Фиксированная ширина обычно устанавливается в ко% личестве 79 или 80 символов. Это сложилось исторически; 80 симво% лов – стандартная ширина терминала, но последнюю колонку не всегда можно использовать для отображения.

Существуют варианты выравнивания некоторых конструкций. На каком уровне помещать public:, private: и protected: в объявлении класса? Где ставить метки case в операторах switch? Как формати% ровать метки оператора goto, которым вы никогда не пользуетесь?2

Пробелы и разделение

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

1Чаще встречается в напечатанном коде, чем в редакторе исходного текста.

2Потому что в нынешние просвещенные времена, разумеется, ни один про% граммист высокого класса не станет пользоваться этими goto. См. раздел

«Структурное программирование» на стр. 531.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

588m

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

.

 

 

 

 

 

.c

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-xcha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

Ответы и обсуждениеClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

такого стиля. Горизонтальная табуляция может выглядеть пример% но так:

int cat = 1; int dog = 2;

char *mouse = "small and furry";

Пробельные символы могут появляться практически всюду, и есть много способов выделения пустым пространством отдельных пред% ложений кода. Полезно выделять пробелами операторы, например: hamster = "cute". Это примерно то же, что выделение пробелами слов на письме. Альтернативный вариант – hamster="ugly" – выгля% дит слишком плотно.

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

feedLion(mouse) feedLion( hamster ) feedLion (motherInLaw)

Последний вариант многим не нравится: в математическом выра% жении не должно быть пробела после имени функции.

Следует ли придерживаться того же правила с ключевыми слова% ми? Как выглядит while(lionIsAsleep)? Скученно. Ключевые слова не функции; они больше похожи на слова, поэтому чаще всего их отделяют пробелами.

Если код оказывается слишком длинным для одной строки, его нужно разбить на части, но где его разбивать – тоже вопрос. Естест% венно разбить там, где это логично, но что для одного логика, то для другого – безумие. Обычно строки переносят в районе оператора, но делать ли это до или после него, т. е. оставлять оператор в конце строки или начинать с него новую, – дело вкуса.

Переменные

Классический пример раздоров в C/C++ – размещение звездочки в объявлении указателя (так называемые «звездные войны»). Мо% жете выбрать один из трех вариантов:

int *mole; int* badger; int * toad;

В первых двух «указательность» ассоциируется с переменной и ти% пом соответственно. Ассоциация с типом не проходит в таких пред% ложениях, как int* weasel, ferret;. Третий вариант – разумная про% межуточная позиция, но она не столь распространена.

В некоторых стандартах C/C++ требуется, чтобы все константы пи% сались прописными буквами для лучшей их видимости. Другие утверждают, что прописными буквами следует писать только име%

на макросов препроцессора.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

2. Тонкий расчет

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

Строки кода

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

589Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Форматирование определяет, что именно находится в каждой строке; часто требуется, чтобы каждое предложение (statement) ко% да занимало отдельную строку, что отчетливо выделяет его.

Это приводит к проблеме побочных эффектов в предложениях; до% пустим ли код типа index[count++] = 2 или присваивание в if?

В некоторых стилях представления код располагается на одной строке с открывающей скобкой:

for (...) { ostrich++; buryHead(ostrich);

}

Конструкции

Всегда ли ставить фигурные скобки, даже если в них находится все% го один оператор? Можно опускать скобки, если код располагается на той же строке, например:

if (weAreAllDoomed) startPanicking();

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

Насколько важно выделять особые случаи? В некоторых стандар% тах требуется, чтобы все переходы вниз в вариантах оператора switch помечались комментариями. Аналогично во избежание пу# таницы в циклах нужно помечать отсутствие операций, иначе сле% дующий маленький цикл без тела, который находит конец строки C str, может смутить неопытного читателя:

char *end;

for (end = str; *end; ++end);

Где помещать встраиваемые методы C++ – внутри объявления класса, вне его (сразу после) или в отдельном файле?

Файлы

Одно из главных решений – как разбить проект на файлы и какую информацию в них поместить. Нужно ли каждый класс или функ% цию помещать в отдельный файл? Или файлы должны быть более мелкими или крупными, например отдельный файл для библиоте% ки или раздела кода? Как быть, если есть много маленьких взаимо% связанных классов? Хорошо ли иметь множество маленьких взаи% мосвязанных классов?1

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

1Для Java ответ ясен: имя класса обязано соответствовать имени файла.