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

слона из мухи

 

 

 

 

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

 

 

 

 

 

243Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

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

Делаем слона из мухи

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

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

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

Собрать и запустить эту программу из одного файла легко – просто вводите compiler main.c,1 и он выплевывает исполняемый модуль, который можно запускать и тестировать. Все просто.

2.Программа растет. Вы делите ее на части и помещаете каждую в от% дельный файл, содержащий определенный функциональный блок. Сборка по%прежнему не вызывает затруднений. Теперь вы просто печатаете compiler main.c func1.c func2.c. Снова на выходе оказыва% ется исполняемая программа, которую вы тестируете, как и рань% ше. Никаких сверхусилий.

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

1Очевидно, compiler нужно заменить той командой, которая запускает ваш

компилятор C; это лишь гипотетический пример.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

244m

 

 

 

 

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

 

 

 

 

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

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

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

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

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

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

мая в результате программа ведет себя некорректно).

 

 

 

 

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

 

 

 

 

 

245Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

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

И тут появляется инструмент, который как раз предназначен для ра% боты в таких ситуациях. Классическим решением является програм% ма командной строки с оригинальным названием make (Feldman 78). Она вместо вас займется всеми промежуточными объектными файла% ми и правилами компиляции и, что главное, учтет зависимости между файлами. Эта программа получает указания в виде make%файлов, со% держащих необходимые правила сборки. Она смотрит на временны]е отметки исходных файлов и проверяет, какие из них изменились с мо% мента последнего запуска make, а потом перекомпилирует только их, а также те, которые от них зависят. Это более интеллектуальная вер% сия сценариев, которые мы писали раньше, специально ориентирован% ная на задачу компиляции и повторной компиляции программного обеспечения.

С течением лет появилось много разновидностей скромной программы make, часто оборудованных милым графическим интерфейсом. GNU Make – один из наиболее широко используемых инструментов (он бес% платный и отличается высокой гибкостью). Если вы пока не посвяще% ны в Культ make, то во врезке «Make: краткий обзор» на стр. 248 при% водится объяснение ее основных функций.

Существует множество других распространенных систем сборки, на% пример SCons, Ant, Nant и Jam. Все они ориентированы на конкрет% ную среду сборки (например, Nant применяется для сборки проектов

.NET) или на определенное свойство (многие пытаются упростить син% таксис make, который весьма вычурен!).

Выполнение сборки

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

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

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

246m

 

 

 

 

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

 

 

 

 

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

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

Сроки и условия

Следующие термины составляют основу терминологии построе% ния программного продукта:

Исходный код

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

Компиляция

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

Сборка

Это не вполне точный термин, который часто используют как синоним компиляции. Компиляция составляет один из эта% пов построения программы, тогда как сборка описывает весь процесс полностью. Термин 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

 

 

 

 

 

247Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Библиотека

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

Машинный код

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

кодом ассемблера.

Некоторые библиотеки ОС низкого уровня и встроенные про% граммы написаны на языке ассемблера, но обычно мы работа% ем на языках высокого уровня, а ассемблер оставляем компи% лятору в качестве его внутреннего механизма.

Компоновка

Редактор связей (linker) соединяет один или несколько объект# ных файлов (а возможно, и библиотек) в конечный исполняе% мый модуль или частично скомпонованную библиотеку кода.

Выполняемый модуль

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

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

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

Считайте систему сборки частью дерева исходного кода и ведите их совме& стно. Они тесно связаны между собой.

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

-

 

 

 

 

 

d

 

F

 

 

 

 

 

 

t

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

to

 

 

 

 

w Click

 

 

 

248m

 

 

 

 

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

 

 

 

 

Make: краткий обзор

Make – одна из наиболее широко применяемых систем сборки в мире программирования. Промчимся вихрем по ее организа% ции и возможностям.

Make управляется make#файлами, которые обычно располагают% ся в каталогах по соседству с исходным кодом, который они со% бирают. Эти make%файлы содержат правила, описывающие сбор% ку приложения. Каждое правило описывает цель (target, про% грамму или промежуточную библиотеку), детали, от которой она зависит, и как ее создавать. Комментариям в файле предше% ствует #. Вот короткий пример, в котором для сборки источника используется гипотетическая программа compiler:

#Первое правило утверждает: ".o!файлы можно собирать

#из .c!файлов, и вот команда для этого."

#$< и $@ ! это специальные символы для файлов источника

#и приемника. Да, синтаксис make бывает загадочным...

%.o: %.c

compiler object $@ $<

#Это правило говорит: "программа myapp собирается из трех файлов .o,

#и вот как компоновать их вместе"

myapp: main.o func1.o func2.o

linker output $@ main.o func1.o func2.o

Это общая идея. Если сохранить текст в файле с именем Makefile и выполнить команду make myapp, произойдет загрузка и синтак% сический анализ этого файла. Так как myapp зависит от несколь% ких .o%файлов, то сначала они будут собраны из соответствую% щих .c%файлов с помощью указанных правил. Затем будет вы% полнена команда редактора связей, которая создаст приложение.

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

OBJECT_FILES=main.o func1.o func2.o myapp: $(OBJECT_FILES)

linker output $@ $(OBJECT_FILES)

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