|
Искусство программирования для Unix
Эрик Стивен Реймонд; Eric Steven Raymond;
- Часть I Контекст
- 1 Философские вопросы
- 1.1. Культура? Какая культура?
- 1.2. Долговечность Unix
- 1.3. Доводы против изучения культуры Unix
- 1.4. Что в Unix делается неверно
- 1.5. Что в Unix делается верно
- 1.5.1. Программное обеспечение с открытым исходным кодом
- 1.5.2. Кроссплатформенная переносимость и открытые стандарты
- 1.5.3. Internet и World Wide Web
- 1.5.4. Сообщество открытого исходного кода
- 1.5.5. Гибкость на всех уровнях
- 1.5.6. Особый интерес исследования Unix
- 1.5.7. Уроки Unix применимы в других операционных системах
- 1.6. Основы философии Unix
- 1.6.1. Правило модульности: следует писать простые части, связанные ясными интерфейсами
- 1.6.2. Правило ясности: ясность лучше, чем мастерство
- 1.6.3 Правило композиции: следует разрабатывать программы, которые будут взаимодействовать с другими программами
- 1.6.4. Правило разделения: следует отделять политику от механизма и интерфейсы от основных модулей
- 1.6.5. Правило простоты: необходимо проектировать простые программы и "добавлять сложность" только там, где это необходимо
- 1.6.6 Правило расчетливости: пишите большие программы, только если после демонстрации становится ясно, что ничего другого не остается
- 1.6.7. Правило прозрачности: для того чтобы упростить проверку и отладку программы, ее конструкция должна быть обозримой
- 1.6.8. Правило устойчивости: устойчивость — следствие прозрачности и простоты
- 1.6.9. Правило представления: знания следует оставлять в данных, чтобы логика программы могла быть примитивной и устойчивой
- 1.6.10. Правило наименьшей неожиданности: при проектировании интерфейсов всегда следует использовать наименее неожиданные элементы
- 1.6.11. Правило тишины: если программа не может "сказать" что-либо неожиданное, то ей вообще не следует "говорить"
- 1.6.12. Правило исправности: когда программа завершается аварийно, это должно происходить явно и по возможности быстро
- 1.6.13. Правило экономии: время программиста стоит дорого; поэтому экономия его времени более приоритетна по сравнению с экономией машинного времени
- 1.6.14. Правило генерации: избегайте кодирования вручную; если есть возможность, пишите программы для создания программ
- 1.6.15. Правило оптимизации: создайте опытные образцы, заставьте их работать, прежде чем перейти к оптимизации
- 1.6.16. Правило разнообразия: не следует доверять утверждениям о "единственно верном пути"
- 1.6.17. Правило расширяемости: проектируйте с учетом изменений в будущем, поскольку будущее придет скорее, чем кажется
- 1.7. Философия Unix в одном уроке
- 1.8. Применение философии Unix
- 1.9. Подход также имеет значение
- 2 История: слияние двух культур
- 2.1. Истоки и история Unix, 1969–1995 гг.
- 2.1.1. Начало: 1969–1971 гг.
- 2.1.2. Исход: 1971–1980 гг.
- 2.1.3. TCP/IP и Unix-войны: 1980–1990 гг.
- 2.1.4. Бои против империи: 1991–1995 гг.
- 2.2. Истоки и история хакерской культуры, 1961–1995 гг.
- 2.2.1. Академические игры: 1961–1980 гг.
- 2.2.2. Internet и движение свободного программного обеспечения: 1981–1991 гг.
- 2.2.3. Linux и реакция прагматиков: 1991–1998 гг.
- 2.3. Движение открытого исходного кода: с 1998 года до настоящего времени
- 2.4. Уроки истории Unix
- 3 Контраст: сравнение философии Unix и других операционных систем
- 3.1. Составляющие стиля операционной системы
- 3.1.1. Унифицирующая идея операционной системы
- 3.1.2. Поддержка многозадачности
- 3.1.3. Взаимодействующие процессы
- 3.1.4. Внутренние границы
- 3.1.5. Атрибуты файлов и структуры записи
- 3.1.6. Двоичные форматы файлов
- 3.1.7. Предпочтительный стиль пользовательского интерфейса
- 3.1.8. Предполагаемый потребитель
- 3.1.9. Входные барьеры для разработчика
- 3.2. Сравнение операционных систем
- 3.2.1. VMS
- 3.2.2. MacOS
- 3.2.3. OS/2
- 3.2.4. Windows NT
- 3.2.5. BeOS
- 3.2.6. MVS
- 3.2.7. VM/CMS
- 3.2.8. Linux
- 3.3. Все повторяется
- Часть II Проектирование
- 4 Модульность: четкость и простота
- 4.1. Инкапсуляция и оптимальный размер модуля
- 4.2. Компактность и ортогональность
- 4.2.1. Компактность
- 4.2.2. Ортогональность
- 4.2.3. Правило SPOT
- 4.2.4. Компактность и единый жесткий центр
- 4.2.5. Значение освобождения
- 4.3. Иерархичность программного обеспечения
- 4.3.1. Сравнение нисходящего и восходящего программирования
- 4.3.2. Связующие уровни
- 4.3.3. Учебный пример: язык С считается тонким связующим уровнем
- 4.4. Библиотеки
- 4.4.1. Учебный пример: подключаемые подпрограммы GIMP
- 4.5. Unix и объектно-ориентированные языки
- 4.6. Создание модульного кода
- 5 Текстовое представление данных: ясные протоколы лежат в основе хорошей практики
- 5.1. Важность текстовой формы представления
- 5.1.1. Учебный пример: формат файлов паролей в Unix
- 5.1.2. Учебный пример: формат файлов .newsrc
- 5.1.3. Учебный пример: PNG — формат графических файлов
- 5.2. Метаформаты файлов данных
- 5.2.1. DSV-стиль
- 5.2.2. Формат RFC 822
- 5.2.3. Формат Cookie-Jar
- 5.2.4. Формат record-jar
- 5.2.5. XML
- 5.2.6. Формат Windows INI
- 5.2.7. Unix-соглашения по текстовым файловым форматам
- 5.2.8. Аргументы "за" и "против" сжатия файлов
- 5.3. Проектирование протоколов прикладного уровня
- 5.3.1. Учебный пример: SMTP, простой протокол передачи почты
- 5.3.2. Учебный пример: POP3, почтовый протокол 3-й версии
- 5.3.3. Учебный пример: IMAP, протокол доступа к почтовым сообщениям
- 5.4. Метаформаты протоколов прикладного уровня
- 5.4.1. Классический метапротокол прикладного уровня в Internet
- 5.4.2. HTTP как универсальный протокол прикладного уровня
- 5.4.2.1. Учебный пример: база данных CDDB/freedb.org
- 5.4.2.2. Учебный пример: протокол IPP
- 5.4.3. ВЕЕР: Blocks Extensible Exchange Protocol
- 5.4.4. XML-RPC, SOAP и Jabber
- 6 Прозрачность: да будет свет
- 6.1. Учебные примеры
- 6.1.1. Учебный пример: audacity
- 6.1.2. Учебный пример: параметр -v программы fetchmail
- 6.1.3. Учебный пример: GCC
- 6.1.4 Учебный пример: kmail
- 6.1.5. Учебный пример: SNG
- 6.1.6. Учебный пример: база данных Terminfo
- 6.1.7. Учебный пример: файлы данных Freeciv
- 6.2. Проектирование, обеспечивающее прозрачность и воспринимаемость
- 6.2.1. Дзэн прозрачности
- 6.2.2. Программирование, обеспечивающее прозрачность и воспринимаемость
- 6.2.3. Прозрачность и предотвращение избыточной защищенности
- 6.2.4. Прозрачность и редактируемые формы представления
- 6.2.5. Прозрачность, диагностика и восстановление после сбоев
- 6.3. Проектирование, обеспечивающее удобство сопровождения
- 7 Мультипрограммирование: разделение процессов для разделения функций
- 7.1. Отделение контроля сложности от настройки производительности
- 7.2. Классификация IPC-методов в Unix
- 7.2.1. Передача задач специализированным программам
- 7.2.1.1. Учебный пример: пользовательский почтовый агент mutt
- 7.2.2. Каналы, перенаправление и фильтры
- 7.2.2.1. Учебный пример: создание канала к пейджеру
- 7.2.2.2. Учебный пример: создание списков слов
- 7.2.2.3. Учебный пример: pic2graph
- 7.2.2.4. Учебный пример: утилиты bc(1) и dc(1)
- 7.2.2.5. Контрпример: почему программа fetchmail не выполнена в виде конвейера
- 7.2.3. Упаковщики
- 7.2.3.1. Учебный пример: сценарии резервного копирования
- 7.2.4. Оболочки безопасности и цепи Бернштайна
- 7.2.5. Подчиненные процессы
- 7.2.5.1. Учебный пример: scp и ssh
- 7.2.6. Равноправный межпроцессный обмен данными
- 7.2.6.1. Временные файлы
- 7.2.6.2. Сигналы
- 7.2.6.3. Системные демоны и традиционные сигналы
- 7.2.6.4. Учебный пример: использование сигналов в программе fetchmail
- 7.2.6.5. Сокеты
- 7.2.6.5.1. Учебный пример: PostgreSQL
- 7.2.6.5.2. Учебный пример: Freeciv
- 7.2.6.6. Общая память
- 7.3. Проблемы и методы, которых следует избегать
- 7.3.1. Устаревшие IPC-методы в Unix
- 7.3.1.1. System V IPC
- 7.3.1.2. Потоки
- 7.3.2. Методы удаленного вызова процедур
- 7.3.3. Опасны ли параллельные процессы?
- 7.4. Разделение процессов на уровне проектирования
- 8 Мини-языки: поиск выразительной нотации
- 8.1. Классификация языков
- 8.2. Применение мини-языков
- 8.2.1. Учебный пример: sng
- 8.2.2. Учебный пример: регулярные выражения
- 8.2.3. Учебный пример: Glade
- 8.2.4. Учебный пример: m4
- 8.2.5. Учебный пример: XSLT
- 8.2.6. Учебный пример: инструментарий Documenter's Workbench
- 8.2.7. Учебный пример: синтаксис конфигурационного файла fetchmail
- 8.2.8. Учебный пример: awk
- 8.2.9. Учебный пример: PostScript
- 8.2.10. Учебный пример: утилиты bc и dc
- 8.2.11. Учебный пример: Emacs Lisp
- 8.2.12 Учебный пример: JavaScript
- 8.3. Проектирование мини-языков
- 8.3.1. Определение соответствующего уровня сложности
- 8.3.2. Расширение и встраивание языков
- 8.3.3. Написание специальной грамматики
- 8.3.4. Проблемы макросов
- 8.3.5. Язык или протокол прикладного уровня
- 9 Генерация кода: повышение уровня спецификации
- 9.1. Создание программ, управляемых данными
- 9.1.1. Учебный пример: ascii
- 9.1.2. Учебный пример: статистическая фильтрация спама
- 9.1.3. Учебный пример: программирование метаклассов в fetchmail
- 9.2. Генерация специального кода
- 9.2.1. Учебный пример: генерация кода для ascii-дисплеев
- 9.2.2. Учебный пример: генерация HTML-кода для табличного списка
- 10 Конфигурация: правильное начало
- 10.1. Конфигурируемые параметры
- 10.2. Месторасположение конфигурационной информации
- 10.3. Файлы конфигурации
- 10.3.1. Учебный пример: файл .netrc
- 10.3.2. Переносимость на другие операционные системы
- 10.4. Переменные окружения
- 10.4.1. Системные переменные окружения
- 10.4.2. Пользовательские переменные окружения
- 10.4.3. Когда использовать переменные окружения
- 10.4.4. Переносимость на другие операционные системы
- 10.5. Параметры командной строки
- 10.5.1. Параметры командной строки от -а до -z
- 10.5.2. Переносимость на другие операционные системы
- 10.6. Выбор метода
- 10.6.1. Учебный пример: fetchmail
- 10.6.2. Учебный пример: сервер XFree86
- 10.7. Нарушение правил
- 11 Интерфейсы: модели проектирования пользовательских интерфейсов в среде Unix
- 11.1. Применение правила наименьшей неожиданности
- 11.2. История проектирования интерфейсов в Unix
- 11.3. Оценка конструкций интерфейсов
- 11.4. Компромиссы между CLI- и визуальными интерфейсами
- 11.4.1. Учебный пример: два способа написания программы калькулятора
- 11.5. Прозрачность, выразительность и возможность конфигурирования
- 11.6. Модели проектирования интерфейсов в Unix
- 11.6.1. Модель фильтра
- 11.6.2. Модель заклинаний
- 11.6.3. Модель источника
- 11.6.4. Модель приемника
- 11.6.5. Модель компилятора
- 11.6.6. Модель редактора ed
- 11.6.7. Rogue-подобная модель
- 11.6.8. Модель "разделения ядра и интерфейса"
- 11.6.8.1. Пара конфигуратор/актор
- 11.6.8.2. Пара спулер/демон
- 11.6.8.3. Пара драйвер/ядро
- 11.6.8.4. Пара клиент/сервер
- 11.6.9. Модель CLI-сервера
- 11.6.10. Модель интерфейсов на основе языков
- 11.7. Применение Unix-моделей проектирования интерфейсов
- 11.7.1. Модель многопараметрических программ
- 11.8. Использование Web-браузера в качестве универсального клиента
- 11.9. Молчание — золото
- 12 Оптимизация
- 12.1. Отказ от оптимизации
- 12.2. Измерения перед оптимизацией
- 12.3. Размер кода
- 12.4. Пропускная способность и задержка
- 12.4.1. Пакетные операции
- 12.4.2. Совмещение операций
- 12.4.3. Кэширование результатов операций
- 13 Сложность: просто, как только возможно, но не проще
- 13.1. Сложность
- 13.1.1. Три источника сложности
- 13.1.2. Компромиссы между сложностью интерфейса и реализации
- 13.1.3. Необходимая, необязательная и случайная сложность
- 13.1.4. Диаграмма видов сложности
- 13.1.5. Когда простоты не достаточно
- 13.2. Редакторы
- 13.2.1. ed
- 13.2.2. vi
- 13.2.3. Sam
- 13.2.4. Emacs
- 13.2.5. Wily
- 13.3. Необходимый и достаточный размер редактора
- 13.3.1. Идентификация проблем сложности
- 13.3.2. Компромиссы не действуют
- 13.3.3. Является ли Emacs доводом против Unix-традиции?
- 13.4. Необходимый размер программы
- Часть IV Сообщество
- 17 Переносимость: переносимость программ и соблюдение стандартов
- 17.1. Эволюция С
- 17.1.1. Ранняя история С
- 17.1.2. Стандарты С
- 17.2. Стандарты Unix
- 17.2.1. Стандарты и Unix-войны
- 17.2.2. Влияние новых Unix-систем
- 17.2.3. Стандарты Unix в мире открытого исходного кода
- 17.3. IETF и процесс RFC-стандартизации
- 17.4. Спецификации — ДНК, код — РНК
- 17.5. Программирование, обеспечивающее переносимость
- 17.5.1. Переносимость и выбор языка
- 17.5.1.1. Переносимость С
- 17.5.1.2. Переносимость С++
- 17.5.1.3. Переносимость shell
- 17.5.1.4. Переносимость Perl
- 17.5.1.5. Переносимость Python
- 17.5.1.6. Переносимость Tcl
- 17.5.1.7. Переносимость Java
- 17.5.1.8. Переносимость Emacs Lisp
- 17.5.2. Обход системных зависимостей
- 17.5.3. Инструменты, обеспечивающие переносимость
- 17.6. Интернационализация
- 17.7. Переносимость, открытые стандарты и открытый исходный код
- 18 Документация: объяснение кода в Web-сообществе
- 18.1. Концепции документации
- 18.2. Стиль Unix
- 18.2.1. Склонность к большим документам
- 18.2.2. Культурный стиль
- 18.3. Многообразие форматов документации в Unix
- 18.3.1. troff и инструментарий Documenter's Workbench
- 18.3.2. TEX
- 18.3.3. Texinfo
- 18.3.4. POD
- 18.3.5. HTML
- 18.3.6. DocBook
- 18.4. Современный хаос и возможный выход из положения
- 18.5. DocBook
- 18.5.1. Определения типов документов
- 18.5.2. Другие DTD-определения
- 18.5.3. Инструментальная связка DocBook
- 18.5.4. Средства преобразования
- 18.5.5. Инструменты редактирования
- 18.5.6. Связанные стандарты и практические приемы
- 18.5.7. SGML
- 18.5.8. Справочные ресурсы по XML-DocBook
- 18.6. Лучшие практические приемы написания Unix-документации
- 19 Открытый исходный код: программирование в новом Unix-сообществе
- 19.1. Unix и открытый исходный код
- 19.2. Лучшие практические приемы при взаимодействии с разработчиками открытого исходного кода
- 19.2.1. Хорошая практика обмена исправлениями
- 19.2.1.1. Отправляйте заплаты, а не целые архивы или файлы
- 19.2.1.2. Отправляйте исправления к текущей версии кода
- 19.2.1.3. Не следует включать заплаты для генерируемых файлов
- 19.2.1.4. Не отправляйте заплат, которые только убирают $-идентификаторы систем RCS или SCCS
- 19.2.1.5. Используйте вместо формата по умолчанию (-e) форматы -с или -u
- 19.2.1.6. Сопровождайте заплаты документацией
- 19.2.1.7. Сопровождайте заплату пояснениями
- 19.2.1.8. Включайте в код полезные комментарии
- 19.2.1.9. Не огорчайтесь, если заплата отклонена
- 19.2.2. Хорошая практика наименования проектов и архивов
- 19.2.2.1. Используйте GNU-стиль названий с именной частью и номерами (основной.второстепенный.заплата)
- 19.2.2.2. По возможности необходимо придерживаться локальных соглашений
- 19.2.2.3. Упорно ищите уникальный префикс имени, который легко вводить
- 19.2.3. Хорошая практика разработки
- 19.2.3.1. Не полагайтесь на частный код
- 19.2.3.2. Используйте автоинструменты GNU
- 19.2.3.3. Тестируйте код перед выпуском версии
- 19.2.3.4. Выполняйте контроль ошибок в коде перед выпуском версии
- 19.2.3.5. Проверяйте орфографию в документации и README-файлах перед выпуском версии
- 19.2.3.6. Рекомендованные практические приемы переносимости кода C/C++
- 19.2.4. Хорошая практика создания дистрибутивов
- 19.2.4.1. Убедитесь, что архивы всегда распаковываются в один новый каталог
- 19.2.4.2. Включайте в дистрибутив README-файл
- 19.2.4.3. Придерживайтесь стандартной практики именования файлов
- 19.2.4.4. Проектирование с учетом обновлений
- 19.2.4.5. В Linux создавайте RPM-пакеты
- 19.2.4.6. Предоставляйте контрольные суммы пакетов
- 19.2.5. Практические приемы хорошей коммуникации
- 19.2.5.1. Публикация на сайте Freshmeat
- 19.2.5.2. Публикация в соответствующих группах новостей
- 19.2.5.3. Создайте Web-сайт
- 19.2.5.4. Поддерживайте списки рассылки проекта
- 19.2.5.5. Публикуйте проект в главных архивах
- 19.3. Логика лицензирования: как выбрать лицензию
- 19.4. Почему следует использовать стандартную лицензию
- 19.5. Многообразие лицензий на открытый исходный код
- 19.5.1. Лицензия MIT или Консорциума X
- 19.5.2. Классическая BSD-лицензия
- 19.5.3. Артистическая лицензия
- 19.5.4. General Public License
- 19.5.5. Mozilla Public License
- 20 Будущее: опасности и перспективы
- 20.1. Сущность и случайность в традиции Unix
- 20.2. Plan 9: каким представлялось будущее Unix
- 20.3. Проблемы в конструкции Unix
- 20.3.1. Unix-файл представляет собой только большой блок байтов
- 20.3.2. Слабая поддержка GUI-интерфейсов в Unix
- 20.3.3. Удаление файлов в Unix необратимо
- 20.3.4. Unix предполагает статичную файловую систему
- 20.3.5. Конструкция системы управления задачами была плохо реализована
- 20.3.6. В Unix API не используются исключительные ситуации
- 20.3.7. Вызовы ioctl(2) и fcntl(2) являются препятствиями
- 20.3.8. Модель безопасности Unix, возможно, слишком примитивна
- 20.3.9. Unix имеет слишком много различных видов имен
- 20.3.10. Файловые системы могут считаться вредными
- 20.3.11. На пути к глобальному адресному пространству Internet
- 20.4. Проблемы в окружении Unix
- 20.5. Проблемы в культуре Unix
- 20.6. Причины верить
|
|