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

 

 

 

258m

 

 

 

 

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

 

 

 

 

 

Глава 10. Код, который построил ДжекClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

Конфигурация сборки

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

Унаследованы из среды

Заданы в командной строке make

Явно определены внутри make%файла

Переменные конфигурации обычно используются следующим образом:

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

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

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

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

Значения по умолчанию можно устанавливать в make%файле. Это ре% шает две задачи: документирование возможных вариантов и возмож# ность опускать значения параметров конфигурации.

Рекурсивное применение make

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

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

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Отпустиm

меня…

 

 

 

 

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

 

 

 

 

 

259Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

Рекурсия make помогает разделить пакет на компоненты и собирать их раздельно, но при этом вносит некоторые проблемы. Она выполня% ется медленнее (так как запускает много дочерних процессов для обхо% да подкаталогов), и, поскольку каждая дочерняя make видит только свою часть всего дерева, сведения о зависимостях могут оказаться не% верными. Будьте осторожны, столкнувшись с рекурсивной make – предпочтительней нерекурсивные системы сборки. (Подробнее об этом см. ответ на вопрос 7 этой главы на стр. 628.)

Отпусти меня…

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

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

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

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

особым образом, обычно с помощью тегов или меток в системе кон%

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

260m

 

 

 

 

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

 

 

 

 

 

Глава 10. Код, который построил ДжекClick

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

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

Дерево познания (исходного кода)

Весь код находится в дереве исходного кода: файловой структу% ре, хранящей каталоги и файлы с исходным кодом. Структура этого дерева определяет простоту работы с кодом. В аккуратно организованной иерархии гораздо легче разобраться, чем в бес% порядочной куче файлов. Располагая исходные файлы в виде оп% ределенной структуры, мы можем облегчить себе разработку. Эта древовидная структура тесно связана с системой сборки, по% тому что система сборки физически является частью дерева ис% ходного кода (поэтому слова «дерево сборки» и «дерево исходно% го кода» означают одно и то же). Модификация одного требует вмешательства в другое.

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

Библиотеки

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

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

Отпустиm

меня…

 

 

 

 

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

 

 

 

 

 

261Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Приложения

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

Код сторонних разработчиков

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

Прочие данные

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

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

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

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

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

сборки. Эти записки тоже нужно сохранить. Обычно в записке опи%