Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Питер_Гудлиф_Ремесло_программиста_Практика_написания_хорошего_кода.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

4. Литературоведение

 

 

 

 

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

 

 

 

 

 

599Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

Для опытного мастера выбор хороших имен становится привычным, и ему не нужно для этого обращаться «за помощью» к стандартам. Ав% торы стандартов часто утверждают, что их стандарты помогут в выбо% ре имен менее опытным программистам. Однако эти стандарты оказы% ваются, как правило, не столь полезными – прегрешения неопытных программистов не ограничиваются плохим выбором имен. Качество их работы необходимо проверять с помощью рецензирования.

3.Какое самое неудачное имя встретилось вам в последнее время? Были ли случаи, когда имена вводили вас в заблуждение? Как бы вы изме нили их, чтобы избежать подобных проблем в будущем?

Когда оно вам встретилось – при официальном рецензировании чьей%то работы или при сопровождении старого, забытого кода?1 Лучше всего, когда плохие имена обнаруживаются и корректируются сразу после своего появления (вы еще помните, как правильно назвать этот объ% ект). И сил при этом тратится меньше всего. Разбираться с именами спустя несколько месяцев бывает гораздо труднее.

4.Приходится ли вам портировать код с одной платформы на другую? Как это повлияло на ваш выбор имен файлов, других объектов и общей структуры кода?

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

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

Глава 4. Литературоведение

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

1.Группировка взаимосвязанного кода делает более заметными эти свя зи. Как можно осуществить это группирование? Какие методы доку ментируют эти связи наиболее заметным образом?

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

1Очевидно, что если это ваш код, в нем не может быть никаких проблем!

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

600m

 

 

 

 

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

 

 

 

 

имен C++/C#, пакете Java, исходном файле или библиотеке кода. Мо% жете ли вы предложить другие способы?

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

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

Число «ноль» обладает магическими свойствами во многих контекс% тах; в коде C оно применяется в качестве значения нулевого указателя и начального значения в большинстве циклов. Чем можно заменить 0 ?

Общая константа с именем ZERO ничуть не лучше, чем просто 0; ма% гия сохраняется. Из имени не следует, чем является нуль на самом деле – значением нулевого указателя или значением инициализа% ции цикла? Этот подход не достигает цели.

Разные имена для всех нулевых констант вызывают большие не% удобства из%за необходимости многочисленных вариаций на тему for (int i = SOME_ZERO_START_VALUE; i < SOME_END_VALUE; ++i). Ника% кой новой информации эти имена все равно не несут.

Над именами нулевых констант нужно хорошенько подумать. Очевид% ный вариант – что%то вроде NO_BANANAS, что означает нулевое количест# во бананов. Однако префикс NO_ можно спутать с сокращением для числа (например, NUM_).

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

Есть много способов использования контекста для целей документиро% вания. Пусть у нас есть класс Cat. Его члены%функции не обязательно называть setCatName, setCatColor и т. д.; часть cat неявно следует из контекста класса.

У многих английских слов есть несколько значений. Надо полагать, что переменная count (подсчет) в функции поиска будет содержать иную информацию, нежели одноименная в базе данных вампиров (граф). Ближе к реальности: переменная name в классе Cat явно будет хранить кличку кошки, тогда как та же переменная в классе Employee будет, скорее всего, хранить имя человека, его фамилию и обращение. Имя переменной одно, контексты разные. Как можно чаще используй% те контекст при условии, что он очевиден.

4.Можно ли реально рассчитывать на то, что человек, впервые видящий некоторый самодокументируемый код, сможет в нем полностью разо

браться?

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

4. Литературоведение

 

 

 

 

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

 

 

 

 

 

601Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Да, это наша цель, и она достижима. Однако читателю все равно по% требуются обзорная и проектная документация, описывающая систе% му в целом, ее работу и структуру. Если эти данные оказываются в комментариях к коду, то место для них выбрано неудачно (или это очень маленькая система).

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

5.Если код действительно самодокументируемый, какой объем дополни тельной информации необходим?

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

Для документирования конструкции отдельного раздела кода доста% точно хороших литературных комментариев, и тогда другая докумен% тация не нужна.

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

Это реальность промышленного производства программ. Бессовест% ный программист может воспользоваться тем, что никто кроме него не разбирается в коде, чтобы закрепить за собой рабочее место. Написав код, который никто не может разгадать, вы гарантируете себе заня% тость до конца жизни (или до конца существования компании – в за% висимости от того, что случится раньше). Недостаток такого решения в том, что до конца дней придется возиться со своей грязной стряпней.

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

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

7.Эту простую C функцию пузырьковой сортировки можно усовершен ствовать. Что именно в ней нехорошо? Напишите улучшенный, само документируемый вариант.

void bsrt(int a[], int n)

{

for (int i = 0; i < n 1; i++)

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

602m

 

 

 

 

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

 

 

 

 

for (int j = n 1; j > i; j ) if (a[j 1] > a[j])

{

int tmp = a[j 1]; a[j 1] = a[j]; a[j] = tmp;

}

}

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

Интерфейс функции совершенно неясен. Имя функции малопонятно, а имена параметров бессмысленны. Хотелось бы также увидеть ком% ментарий с документацией API, но в своем переработанном варианте я его опущу.

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

void swap(int *first, int *second)

{

int temp = *first; *first = *second; *second = temp;

}

void bubblesort(int items[], int size)

{

for (int pos1 = 0; pos1 < size 1; pos1++)

for (int pos2 = size 1; pos2 > pos1; pos2 ) if (items[pos2 1] > items[pos2])

swap(&items[pos2 1], &items[pos2]);

}

Это приличный C%код, хотя неплохо было бы его немного модифициро% вать. В зависимости от ваших пристрастий могут появиться фигурные скобки вокруг тела цикла. Ради эффективности можно было бы сде% лать из swap макрос. Тем не менее это не самая толковая оптимизация; явно следует выбрать более эффективный алгоритм сортировки.

В C++ я бы сделал swap встроенной, а параметры передавал по ссылке (что отражает тот факт, что они будут изменены). Самое лучшее – вос% пользоваться средством std::swap, предоставляемым библиотеками языка.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Главаm

4. Литературоведение

 

 

 

 

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

 

 

 

 

 

603Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

8.Работа со средствами документирования кода обнаруживает ряд инте ресных проблем. Выскажите свое мнение по следующим вопросам:

a.Следует ли при проверке документации проверять также и код, сравнивая с комментариями в файлах исходного кода, или прове рять спецификации, сравнивая со сгенерированной документа цией?

b.Где следует документировать протоколы и прочие не относящиеся к API вопросы?

c.Документируете ли вы закрытые/внутренние функции? Если это код C/C++, где поместить такую документацию – в файле заголов ка или в файле реализации?

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

По этому вопросу я думаю следующее:

a.Проверьте сгенерированные спецификации. Не обращайте слиш% ком много внимания на расположение комментариев в исходном файле. Вы рецензируете содержимое, а не код.

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

c.Задокументируйте все внутренние функции, которые этого требу% ют. Не обязательно писать подробную документацию по всем за% крытым частям. Эти документы, если они достаточно велики, сле% дует перенести в файл реализации, чтобы открытый интерфейс вы% глядел аккуратно и просто.

d.То и другое! Примените инструмент несколько раз, чтобы создать один крупный документ и документы для каждой подсистемы.

9.Если вы работаете с кодом, в котором отсутствует грамотная докумен тация, и вам необходимо внести изменения или добавить новые мето ды или функции, что правильнее – снабдить их грамотными коммен тариями или оставить недокументированными?

Мастер стремится документировать и автоматически испытывает по% требность написать блок комментариев. Если для кода существует от% дельный документ%спецификация, то ваша документация должна вой% ти в него наравне со всем прочим. Либо можно начать добавлять лите% ратурные комментарии. Следите, однако, за тем, чтобы автор не по% чувствовал себя обиженным!

10. Можно ли написать самодокументируемый код на языке ассемблера?

Можно попытаться, но это будет нелегко. Код ассемблера не очень вы% разителен; вы программируете не на уровне смысла, а на уровне «глу# пый процессор, делай так!». Код будет состоять в основном из блоков