Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
kernigan_paik.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.91 Mб
Скачать

Введение

Приходилось ли вам когда-нибудь:

- тратить кучу времени на то, чтобы закодировать неверный алгоритм?

- использовать слишком сложную структуру данных?

- при тестировании программы пропустить очевидную проблему?

- тратить день на то, чтобы обнаружить ошибку, которую можно было бы найти за пять минут?

- сталкиваться с тем, что программа должна работать в три раза быстрее и использовать меньше памяти?

- затрачивать титанические усилия на то, чтобы перевести программу с рабочей станции на PC или наоборот?

- пытаться внести изменения в чужую программу?

- переписывать программу целиком, потому что разобраться в ней не удалось?

Ну и как — понравилось?

С программистами такое происходит все время. Однако справиться с подобными проблемами часто гораздо труднее, чем хотелось бы, по­скольку такие темы, как тестирование, отладка, переносимость, произ­водительность, альтернативы проектирования и стиль, темы, относящи­еся к практике программирования, как правило, оказываются вне сферы внимания информатики и учебных курсов по программированию. Боль­шинство программистов изучают их сами по себе, в основном, на соб­ственном опыте, а некоторые не изучают вообще.

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

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

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

Книга родилась из нашего многолетнего опыта в написании и под­держке разнообразнейших программ, в преподавании .программиро­вания и в общении с большим количеством программистов. Мы хотим поделиться знаниями, приобретенными благодаря этому опыту, чтобы помочь программистам всех уровней работать более эффективно и про­фессионально.

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

Мы надеемся, что наши советы помогут вам писать более качествен­ные программы. Единственное, что вам необходимо, — это иметь неко­торый опыт в программировании, желательно на С, C++ или Java. Есте­ственно, чем больше ваш опыт, тем проще вам будет понять и применить наши советы, ничто не сможет сделать эксперта из новичка за 21 день. Для работающих с системами Linux и Unix многие примеры будут более знакомы, чем для тех, кто использовал только системы Windows и Ma­cintosh, однако все без исключения найдут в этой книге рекомендации, которые облегчат им жизнь.

Каждая из девяти глав, составляющих книгу, посвящена конкретно­му глобальному аспекту практики программирования.

В главе 1 обсуждается стиль программирования. Хороший стиль на­столько необходим для написания хороших программ, что мы решили начать разговор именно с него. Хорошо написанные программы лучше, чем плохо написанные, — в них меньше ошибок, их легче отлаживать и модифицировать, — поэтому задумываться о стиле надо с самого нача­ла. В этой главе затрагивается и такой важный аспект хорошего про­граммирования, как применение идиом, соответствующих используемо­му языку программирования.

Алгоритмы и структуры данных — предмет обсуждения главы 2 — за­нимает центральное место в учебных планах всех курсов программиро­вания. Поскольку большинство читателей в той или иной степени уже знакомо с этим материалом, мы даем лишь краткий обзор ряда алгорит­мов и структур данных, которые встречаются во многих программах. Бо­лее сложные алгоритмы и структуры данных, как правило, являются производными от этих базовых вариантов, так что главное — разобрать­ся с основами.

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

Интерфейсы между пользователями, программами и частями про­грамм являются одной из фундаментальных основ программирования; успех того или иного программного продукта во многом определяется тем, насколько хорошо спроектированы и реализованы в нем интерфей­сы. В главе 4 показана эволюция небольшой библиотеки для синтакси­ческого разбора одного широко используемого формата данных. Хотя пример и невелик, он иллюстрирует многие понятия, связанные с проек­тированием интерфейсов: абстракцию, сокрытие информации, управле­ние ресурсами и обработку ошибок.

Как бы мы ни старались писать программы корректно с первого раза, ошибки в них, а следовательно, и отладка вечны. Глава 5 описывает стра­тегию и тактику систематической и эффективной отладки. Среди рас­сматриваемых здесь аспектов назовем характеристики частых ошибок и важность "нумерологии", для которой образцы отладочных печатей часто показывают, где таится ошибка.

Тестирование — это попытка дать разумное обоснование работоспо­собности программы. Глава 6 посвящена систематическому тестирова­нию программ как вручную, так и с помощью компьютера. Тесты на гра­ничные условия проверяют потенциальные слабые места программ. Механизация и специальная тестовая оснастка позволяют осуществ­лять комплексное тестирование с достаточно скромными затратами. Особым типом тестов являются стрессовые тесты, они проверяют устой-чивость программ.

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

В главе 8 разговор идет о переносимости. Удачные программы живут достаточно долго, так что меняются системы, в которых их используют; нередко приходится переносить их на другие платформы или на другие машины или использовать в других странах. Смысл переносимости в том, чтобы уменьшить расходы на поддержание программы, миними­зировав количество изменений, необходимых для адаптации к новому окружению.

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

Разговор о программировании, естественно, не может обойтись без де­монстрации изрядного количества кода. Большинство примеров написа­но специально для этой книги, но некоторые небольшие фрагменты были взяты из ранее написанных программ. Мы очень старались писать свой код хорошо; все примеры тестировались на нескольких системах. Допол­нительную информацию можно получить на web-сайте, посвященном этой книге (в английском варианте — The Practice of Programming).

Большинство программ написано на С; есть примеры на C++ и Java; предпринят и краткий экскурс в языки скриптов. На нижнем уровне С и C++ практически идентичны, так что наши программы на С являются вполне приемлемыми программами на C++. Языки. C++ и Java — прямые наследники С, они унаследовали изрядную долю синтаксиса, эффективности и выразительности С, добавив более широкие системы типов и библиотек. Мы сами в повседневной работе широко используем и эти три языка, и множество других. Выбор языка зависит от задачи: операционные системы лучше всего писать на эффективном и не давя­щем языке вроде С или C++; создавать на скорую руку прототипы про­ще на командных интерпретаторах или языках скриптов вроде Awk или Perl; для пользовательских интерфейсов хорошо подходят Visual Basic, Tcl/Tk и Java.

В выборе языка для наших примеров есть глубокий педагогический смысл. Поскольку нет языка, который был бы одинаково хорош для ре­шения всех задач, ни один конкретный язык не может лучшим образом представить все аспекты. Языки высокого уровня предопределяют неко­торые проектные решения. Если же мы используем язык низкого уров­ня, мы получаем возможность для альтернативных решений проектных вопросов; показывая больше подробностей, мы можем обсуждать эти вопросы лучше. Опыт учит, что даже при использовании возможностей языка высокого уровня важно понимать, как они соотносятся с низким уровнем, без такого понимания можно упереться в проблемы произво­дительности и загадочного поведения программы. Поэтому часто мы ис­пользуем в своих примерах язык С, даже в тех случаях, когда в реальной работе мы бы выбрали какой-нибудь другой язык.

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

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

Мы глубоко признательны нашим друзьям и коллегам, которые чита­ли черновики этой книги и выдали нам множество ценнейших коммен­тариев. Ион Бентли (Jon Bentley), Pacc Кокс (Russ Сох), Джон Лакос (John Lakos), Джон Линдерман (John Linderman), Питер Мемишиан (Peter Memishian), Ян Лэнс Тейлор (Ian Lance Taylor), Говард Трики (Howard Trickey) и Крис Ван Вик (Chris Van Wyk) читали рукопись, некоторые не по одному разу, с величайшей старательностью и внима­нием. Мы обязаны Тому Каргиллу (Tom Cargill), Крису Клиланду (Chris Cleeland), Стиву Дьюхерсту (Steve Dewhurst), Эрику Гроссу (Eric Grosse), Эндрю Херрону (Andrew Herron), Джерарду Холзманну (Gerard Holzmann), Дугу Мак-Илрою (Doug Mcllroy), Полу Мак-Неми (Paul MacNamee), Питеру Нельсону (Peter Nelson), Деннису Ритчи (Dennis Ritchie), Ричу Стивенсу (Rich Stevens), Тому Шимански (Тот Szymanski), Кентаро Тойаме (Kentaro Toyama), Джону Уейту (John Wait), Дэниэлю С. Вангу (Daniel С. Wang), Питеру Вайнбергеру (Peter Weinberger), Маргарет Райт (Margaret Wright) и Клиффу Юнгу (Cliff Young) неоценимыми комментариями к черновикам, сделанными на разных стадиях работы над книгой. Мы также высоко ценим советы и продуманные пожелания от Ала Ахо (Al Aho), Кена Арнольда (Ken Arnold), Чака Байглоу (Chuck Bigelow), Джошуа Блоха (Joshua Bloch), Билла Кограна (Bill Coughran), Боба Фландрены (Bob Flandrena), Рени Френча (Renee French), Марка Кернигана (Mark Kernighan), Энди Кё-нига (Andy Koenig), Сейпа Маллендера (Sape Mullender), Эви Немет (Evi Nemeth), Марти Рабиновича (Marty Rabinowitz), Марка В. Шейни (Mark V. Shaney), Бьёрна Страуструпа (Bjarne Stroustrup), Кена Томп­сона (Ken Thompson) и Фила Уадлера (Phil Wadler). Спасибо вам всем.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]