Книга посвящена важному аспекту программирования, недостаточно освещенному
в литературе - чтению и анализу программного кода на языках высокого уровня
с целью доработки, извлечения готовых технических решений или изучения
новых методов.
Даются ценные рекомендации по улучшению стиля программирования. Изложение
проиллюстрировано большим количеством примеров, взятых из больших
программных проектов с открытым кодом, находящихся на прилагаемом
компакт-диске.
Книга предназначена для повышения квалификации программистов. Может быть
полезна студентам и преподавателям соответствующих специальностей, а также
начинающим программистам.
Мы - программисты. Наша работа (а часто и наша страсть) состоит в том, чтобы писать программы для самых разных целей. Пользователи получают от нас совсем не гектары графиков, тонны описаний и стопки проектной документации выше человеческого роста. Все это - лишь средство для воплощения замысла в конечный продукт. А самим конечным продуктом является программа.
Именно написанию программ нас и учат. Раз уж работа состоит в том, чтобы написать программный код, значит, надо учиться писать программный код. Этому посвящены предметы университетской программы, а на курсах повышения квалификации мы еще и осваиваем новые библиотеки и интерфейсы. И именно в этом состоит величайшая проблема индустрии программирования. Потому что основной способ научиться писать хороший код - это читать побольше кода. Высококачественного и низкокачественного, на ассемблере и языках высокого уровня, написанного много лет назад за тысячи километров от вас и позавчера вами самими. Если этого не делать, то постоянно приходится заново изобретать велосипед, повторяя как успехи, так и ошибки прошлого.
Интересно, многие ли выдающиеся писатели никогда не читали романов, написанных их предшественниками? А сколько художников не трудились анализировать манеру письма великих живописцев? Как много хирургов в свое время не наблюдали за операциями более опытных коллег? Существуют ли на свете командиры экипажей пассажирских авиалайнеров, никогда не сидевшие в кресле второго пилота и не наблюдавшие, как нужно выполнять взлет и посадку?
Но именно так, согласно общепринятой практике, приходится работать программистам. Им неизменно говорят: ''На этой неделе наша задача - написать то-то и то-то''. Программиста учат азбуке - синтаксису языка и построению элементарных конструкций, а потом требуют, чтобы он написал программу, эквивалентную по качеству роману хорошего писателя.
По иронии судьбы, именно сейчас наступило самое благодатное время для чтения кода. Благодаря огромному вкладу всемирного сообщества авторов открытого кода по глобальным компьютерным сетям рассеяны гигабайты исходного кода, который осталось только взять и прочитать. Выберите любой язык, и вы найдете сколько угодно программ на нем. Выберите проблему, и вы обнаружите огромное количество ее решений. На любом уровне - от микропрограммирования до высокоуровневых функций и объектов - в настоящее время стал доступен огромный объем исходного кода.
Читать и анализировать код очень интересно. Лично я это обожаю. Я ищу в читаемом мною коде удачные решения, хитрые трюки, ошибки и ловушки. Иногда попадаются настоящие жемчужины, пусть и небольшие. До сих пор помню испытанное мною удовольствие, когда я случайно обнаружил программу преобразования из двоичной записи в восьмеричную на языке ассемблера для машины PDP-11, выполняющую вывод до шести восьмеричных цифр в одном цикле без счетчика.
Иногда я читаю код как литературное произведение - нечто вроде романа, купленного в аэропорту перед долгим перелетом. Меня развлекает удачно выстроенный сюжет и неожиданные авторские решения. Прекрасным примером чего-то подобного может служит программа gpic Джеймса Кларка (James Clark), которая входит в состав его GNU-пакета grof f. В ней с помощью исключительно компактной и элегантной структуры реализуется очень сложная задача - построение декларативного аппаратно-независимого языка для рисования графических изображений. Чтение этого кода подвигло меня на попытку структурировать свой собственный код столь же изящно.
Бывает, что я читаю код с более критических позиций. Этот процесс более медленный, поскольку нужно постоянно задавать себе вопросы типа ''Почему это написано именно так?'' или ''Какие соображения побудили автора выбрать именно этот способ?'' Иногда такой режим чтения кода вызван необходимостью найти в нем ошибку. Тогда я ищу конструкции и ключевые места, которые могут дать подсказку. Например, если автор плохо защитил совместно используемую структуру данных в одной части кода, можно заподозрить, что это случилось и в другой, и таким образом найти источник проблемы. Обнаруженные несоответствия могут служить проверкой и моего собственного уровня понимания. Часто я принимаю какой-то фрагмент кода за проблематичный или неграмотный, но при более тщательном анализе оказывается, что он написан искусно и безошибочно. Тогда я сам учусь чему-то новому.
Фактически чтение и анализ кода представляют собой один из эффективных путей устранения ошибок и недоработок в программах. Роберт Гласе (Robert Glass), один из рецензентов этой книги, сказал: ''Путем грамотного просмотра исходного кода в программном продукте можно устранить более 90% ошибок еще до первого тестирования''. В той же статье он ссылается на результаты одного исследования, которые гласят: ''Если читать программу, сконцентрировавшись на качестве ее исходного кода, можно найти на 90% ошибок больше, чем если сосредоточиться на выполняемых ею операциях''. Интересно, что анализируя фрагменты кода, используемые в этой книге, я обнаружил пару ошибок и несколько сомнительных программных конструкций. Причем эти фрагменты взяты из программ, работающих на десятках тысяч рабочих мест по всему миру. Ни одна из ошибок не имеет критического характера, но сам факт доказывает, что всегда есть куда расти. Навыки чтения и анализа кода приносят непосредственную практическую пользу. Возможно, читатель уже и сам это понял, если когда-нибудь читал код своих коллег, которые такими навыками не обладают.
К тому же существует еще и техническая поддержка программ - младшая и нелюбимая сестра их разработки. Точной статистики здесь нет, но большинство исследователей сходятся в том, что примерно половину времени, выделенного на поддержку, приходится проводить за чтением написанного кода: добавлять новые функциональные возможности, исправлять ошибки, интегрировать в новые среды и т.п. Здесь уже навыки чтения и анализа кода приобретают критическое значение. Предположим, есть программа из 100 000 строк кода, содержащая ошибку, и у вас ровно час на исправление этой ошибки. С чего начать? Как узнать, что делает тот код, который находится перед глазами? Как заранее оценить влияние изменения в программе, которое вы собираетесь внести?
В силу всего сказанного и многого другого мне нравится эта книга. В ее основе лежит четкий практический подход. Вместо абстрактных академических рассуждений здесь говорится о конкретном коде. В книге анализируются сотни фрагментов кода, рассказывается о хитроумных приемах, ловушках и (что наиболее важно) стандартных подходах. Код рассматривается в контексте его рабочей среды - как она влияет на него при взаимодействии. Говорится и о программных средствах, применяемых в деле анализа кода, - от стандартных типа grep или find до наиболее экзотических. Подчеркиваются важность разработки таких средств и цель их создания: писать программы, чтобы анализировать существующие программы. Поскольку книга насквозь пронизана практицизмом, весь рассмотренный в ней код удобно организован и помещен на прилагаемый компакт-диск.
Эта книга обязательна для изучения студентами, имеющими отношение к программированию, и должна стоять на полке каждого программиста-практика. Если все сообщество разработчиков программ будет уделять больше внимания чтению и анализу кода, то мы сэкономим много времени и труда, а также снизим денежные затраты в нашей индустрии. Кроме того, мы еще и получим море удовольствия от этой работы.
Чтение и анализ кода - это повседневное занятие любого специалиста в области компьютерного программирования. Однако его практически никогда не преподают как учебный предмет и не рассматривают как строгий метод при разработке программ.
Возможно, первоначальной причиной такого плачевного положения дел была недостаточность или практическое отсутствие реального и высококачественного программного кода, открытого для общего доступа. Фирмы-разработчики чаще всего защищают исходный код как свою коммерческую тайну и очень редко позволяют посторонним читать, комментировать, экспериментировать и активно изучать такой код. В тех немногих случаях, когда исходный код важных коммерчески защищенных приложений выходил из-под контроля разработчиков и становился общедоступным, он немедленно вызывал бурю интереса и ряд творческих разработок на его основе. Например, целое поколение программистов училось по книге Джона Лайонза Комментарии к операционной системе UNIX (John Lions, Commentary on the Unix Operating System), в которой приведен весь исходный код ядра операционной системы UNIX в ее шестом издании с пояснениями автора. Первоначально книга Лайонза была написана под эгидой и на деньги корпорации AT&T для использования в учебном курсе по этой операционной системе и не предназначалась для распространения среди широкой общественности. Тем не менее нелегальные фотокопии этой книги вместе с копиями ее копий вращались в среде программистов годами.
В последние несколько лет популярность программ с открытым кодом возросла, и теперь мы располагаем огромным объемом исходных текстов, которые можно свободно читать и анализировать. В настоящее время доступны в форме с открытым исходным кодом такие популярнейшие программные продукты, как Web-сервер Apache, интерпретатор языка Perl, операционная система GNU/Linux, сервер доменных имен BIND, почтовый агент sendmail. Поэтому мне посчастливилось иметь под рукой достаточно программ с открытым кодом, чтобы написать эту книгу сразу и как ''букварь'' и как ''хрестоматию'' по анализу программного кода. Моя цель состоит в том, чтобы дать читателю достаточно знаний и вооружить его средствами для чтения кода, написанного другими программистами. Используя практические примеры, взятые из реально работающих программ с открытым кодом, я постарался охватить все основные принципы и концепции, относящиеся к анализируемому коду: программные конструкции, типы данных, структуры данных, управление программой, организацию проекта, стандарты, документирование, архитектуры. В этой же серии книг я постараюсь рассмотреть особенности организации интерфейсов и приложений, интернационализацию и переносимость, библиотеки общего пользования и операционные системы, код низкого уровня, декларативные и доменные языки, языки разработки сценариев, смешанные языковые системы.
Насколько мне известно, в этой книге чтение и анализ программного кода впервые рассматриваются как самостоятельный вид деятельности программиста, ценный сам по себе. Первый блин- всегда комом, поэтому недоработки неизбежны. Какая-то часть материала могла быть изложена лучше, кое-что пропущено, неизбежны и ошибки. Я твердо убежден, что анализ кода необходимо систематически преподавать и использовать как строгий метод для повышения квалификации программиста. Поэтому надеюсь, что книга подстегнет интерес к анализу кода в университетских кругах. Соответствующие курсы и предметы, возможно, будут включены в учебные планы по компьютерным специальностям, и через несколько лет наши студенты будут так же успешно учиться программировать на примере проектов с открытым кодом, как студенты филологических специальностей изучают языки по произведениям великих писателей.
Многие примеры кода в этой книге взяты из исходного текста дистрибутива NetBSD. Это бесплатно распространяемая, очень хорошо переносимая UNIX-подобная операционная система, доступная в настоящее время для целого ряда аппаратных платформ от 64-разрядных машин AlphaServer до портативных и карманных компьютеров. Четкая структура и высокопрофессиональная реализация делают эту систему прекрасным выбором как для производственно-прикладных, так и для научно-исследовательских компьютерных систем. Я выбрал систему NetBSD среди целого ряда столь же достойных и не менее популярных UNIX-подобных систем (GNU/Linux, FreeBSD, OpenBSD) по той причине, что ключевыми требованиями при ее создании были строгость, выразительность и хорошая организация кода. Поэтому примеры из нее особенно удачны. Как говорят разработчики системы, некоторые программные продукты, похоже, сделаны по принципу ''раз работает - значит, написано правильно''. В то же время в проекте NetBSD используется принцип ''пока не написано правильно - в работу не пускать''. Кроме того, и некоторые другие принципы построения системы NetBSD хорошо соответствуют целям и задачам этой книги. В частности, в проекте NetBSD избегают обременительного лицензирования, стараются сделать систему максимально переносимой на все платформы и хорошо взаимодействующей с другими системами, удовлетворяют стандартам открытых систем настолько, насколько это удобно практически. Код, использованный в этой книге, взят из версии export-19980407, уже ставшей историей. В нескольких примерах приводятся найденные мною ошибки. Поскольку код NetBSD постоянно дорабатывается, есть риск, что в следующих версиях эти ошибки уже исправлены, и читатель не получит уникальной возможности проанализировать их, если взять примеры из более позднего кода.
Остальные программы, фрагменты из которых используются в книге, были выбраны по тем же причинам: высокое качество кода, структура, организация, практичность, распространенность, доступный уровень лицензирования. Я старался тщательно подбирать языки, постоянно разыскивая подходящие примеры из C++ и Java. Но в тех случаях, если понятие или принцип можно было проиллюстрировать на разных языках, в качестве наименьшего общего знаменателя выбирался язык С.
Некоторые примеры кода я привожу для того, чтобы проиллюстрировать плохой - небезопасный, трудно переносимый, неудобочитаемый - стиль программирования. Признаю, что его авторы могут воспринять это как удар ниже пояса - ведь они предоставляли код в надежде помочь развитию открытых программных систем и надеялись на конструктивное улучшение вместо издевательской критики. Заранее приношу свои извинения всем возможным оскорбленным авторам исходного кода. В свою защиту могу сказать, что в большинстве случаев критика направлена не на конкретный фрагмент, а скорее на стиль или практику, которых следует избегать. Очень часто пример ''как не надо делать'' относится к далекому прошлому- это гадкий утенок, который уже давно стал прекрасным лебедем. Просто в свое время было необходимо писать именно так из-за технических или других ограничений. Бывает и так, что плохой стиль программирования критикуется мною вообще вне всякого контекста. В любом случае надеюсь, что критика будет воспринята доброжелательно и с юмором. Заранее признаю, что мои собственные программы содержат похожие, если не худшие, упущения и недочеты.
Эта книга - альбом иллюстраций. Автор последовательно перебирает различные аспекты программирования - от основ языка к способам организации проектов, стилям программирования, ведению документации, архитектурам построения систем и инструментам разработчика - и каждый рассматриваемый аспект и способы его исполнения иллюстрирует примерами из 500 МБ исходных текстов 12-ти Open Source проектов, находящихся на компакт-диске к книге.
В отличии от других книг, показывающих и объясняющих, как, с точки зрения автора, делать можно и нужно, Диомидис рассказывает о том, как это уже сделано в реальных, живых проектах.
Книг такой направленности, к сожалению, очень мало, и автор, по доброте душевной решивший охватить столь широкий круг вопросов, вынужденно не особенно углубляется в рассмотрение каждого из них, хотя, право же, большинство глав заслуживают отдельной книги, по толщине сравнимой с этой.
Особо хочется обратить внимание преподавателей программирования на упражнения-задания, сопровождающие каждую рассматриваемую тему - вашим студентам не придется скучать :)