- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Искусство программирования для Unix - Реймонд Эрик Стивен
Шрифт:
Интервал:
Закладка:
Другое направление является нисходящим, от абстракции к конкретным функциям, от высокоуровневых спецификаций, описывающих проект в целом или логику приложения, вниз к отдельным операциям. Следовательно, при проектировании программного обеспечения для контроллера запоминающего устройства большой емкости, который может оперировать несколькими различными типами носителей, можно начинать с определения абстрактных операций, таких как "поиск логического блока", "чтение логического блока", "запись логического блока", "переключение индикатора активности". Данные операции отличались бы от операций аппаратного уровня с подобными названиями тем, что они были бы предназначены в качестве общих для различных видов физических устройств.
Два описанных выше примера могут представлять два конструкторских подхода для одного и того же семейства аппаратного обеспечения. Выбор решения в подобных ситуациях представляется таким: абстрагировать аппаратное обеспечение (так чтобы объекты инкапсулировали реальные элементы внешнего мира, а программа просто представляла собой список операций по их обработке), либо организовать программу на основе некоторой поведенческой модели (а затем внедрить действительные аппаратные манипуляции, которые осуществляют эту модель в потоке поведенческой логики).
Аналогичный выбор обнаруживается во многих других ситуациях. Предположим, что разрабатывается программа цифрового музыкального синтезатора (MIDI sequencer). Организовывать такой код можно вокруг его верхнего уровня (упорядочение дорожек) или вокруг нижнего уровня (переключение фрагментов или выборок и управление генераторами колебаний).
Существует весьма точный способ анализа данных различий. Он заключается в том, чтобы выяснить, организована ли конструкция вокруг ее главного событийного цикла (стремящегося к тесной связи с высокоуровневой логикой приложения) или вокруг служебной библиотеки всех операций, которые может вызывать главный цикл. Проектировщик, разрабатывающий программу сверху вниз, начнет с обдумывания ее основного событийного цикла, а специфические события внедрит позднее. Проектировщик, работающий снизу вверх, начнет с обдумывания инкапсуляции специфических задач, а позднее соединит их в некую логическую последовательность.
В качестве более крупного примера рассмотрим разработку Web-браузера. Верхним уровнем конструкции Web-браузера является спецификация ожидаемого поведения данной программы: какие типы URL-адресов (http: или ftp:, или file:) она интерпретирует, какие виды изображений она способна визуализировать, допускает ли она использование языков Java или JavaScript и с какими ограничениями и т.д. Уровень реализации, который соответствует данному верхнему уровню, является основным событийным циклом программы. В каждой итерации цикл ожидает, накапливает и координирует действия пользователя (такие как нажатие Web-ссылки или ввод символа в поле).
Однако Web-браузер для решения поставленных перед ним задач вынужден вызывать большой набор основных примитивов. Одна группа примитивов занята установкой сетевых соединений, отправкой данных по ним, а также получением ответов. В другую группу входят операции GUI-инструментария, который используется браузером. Третья группа может быть занята механическим преобразованием полученных HTML-документов из текстовой формы в объектное дерево документа.
Важно то, с какой стороны этого набора начинается разработка, поскольку уровень на противоположной стороне, весьма вероятно, будет ограничен первоначальным выбором. В частности, если программа разрабатывается исключительно сверху вниз, то программист может оказаться в неудобном положении, когда примитивы предметной области, которые необходимы логике приложения, не совпадают с теми, которые фактически можно реализовать. С другой стороны, если программа разрабатывается исключительно снизу вверх, то может оказаться, что приходится проделывать большой объем работы, не соответствующей логике приложения, или просто проектируется "штабель кирпичей", в то время как необходимо "построить здание".
С момента возникновения полемики по поводу структурного программирования в 60-х годах, начинающих программистов, как правило, учат, что верный подход заключается в проектировании сверху вниз. То есть в поэтапном усовершенствовании, где на абстрактном уровне определяется, для чего предназначена данная программа, и постепенном заполнении пустот реализации до тех пор, пока не будет образован точно работающий код. Нисходящий подход становится хорошей практикой, когда выполняются три предусловия: (а) можно с большой точностью определить, для решения каких задач предназначена данная программа, (b) значительные изменения спецификации в ходе реализации маловероятны и (с) большая свобода выбора на низком уровне, каким образом программа будет выполнять свои функции.
Данные условия наиболее часто выполняются в программах, расположенных сравнительно близко к пользователю и высоко в стеке программ, т.е. в прикладном программировании. Однако даже в этом случае указанные предусловия часто не выполняются. Невозможно заранее определить "правильный" режим работы текстового редактора или графической программы до тех пор, пока пользовательский интерфейс не пройдет тестирование среди конечных пользователей. Исключительно нисходящее программирование часто характеризуется чрезмерным вложением трудозатрат в код, который придется удалить за ненадобностью и перестроить, поскольку интерфейс не проходит проверку в реальных условиях.
Для того чтобы обезопасить себя, программисты пытаются использовать оба подхода — описывают абстрактную спецификацию как нисходящую логику приложения и собирают множество низкоуровневых примитивов предметной области в функциях или библиотеках с тем, чтобы в случае изменения высокоуровневой конструкции их можно было использовать повторно.
Unix-программисты наследуют традицию, которая является центральной в системном программировании, где низкоуровневыми примитивами являются операции аппаратного уровня, которые имеют постоянный характер и чрезвычайно важны. Следовательно, "благодаря приобретенному инстинкту" они более склонны к восходящему программированию.
Независимо от того является программист системным или нет, восходящий подход также может выглядеть более привлекательно при программировании исследовательским способом, когда пытаются получить контроль над феноменами аппаратного или программного обеспечения или реальными феноменами, которые еще не полностью понятны. Восходящее программирование предоставляет время и пространство для уточнения нечеткой спецификации. Кроме того, восходящее программирование "апеллирует к естественной человеческой лени" программистов: когда требуется удалить часть кода и перестроить его, при работе в нисходящем направлении приходится удалять более крупные фрагменты, чем при работе в восходящем направлении.
Таким образом, создание реального кода склоняется к использованию как нисходящего, так и восходящего подходов. Нередко нисходящий и восходящий код является частью одного и того же проекта. В таком случае возникает необходимость использования связующих уровней.
4.3.2. Связующие уровни
Довольно часто столкновение нисходящего и восходящего подходов является причиной некоторого беспорядка. Верхний уровень логики приложения и нижний уровень основных примитивов необходимо согласовать с помощью уровня связующей логики.
Один из уроков, которые Unix-программисты осваивали десятилетиями, состоит в том, что связующая технология представляет собой опасное нагромождение, и жизненно важным является сохранение связующих уровней как можно более тонкими. Связующий уровень должен соединять другие уровни, но его не следует использовать для сокрытия "изломов" и "шероховатостей" в них.
В примере с Web-браузером связующий уровень включал бы в себя код визуализации, который преобразовывает объект документа, полученный из входящего HTML-файла в сглаженное визуальное изображение в виде растра в буфере экрана, используя для формирования изображения основные примитивы GUI-интерфейса. Данный код визуализации печально известен как наиболее подверженная ошибкам часть браузера. Он содержит в себе ухищрения, направленные на разрешение проблем, которые связаны как с синтаксическим анализом HTML-кода (ввиду большого количества неверно сформированной там разметки), так и в инструментальном наборе GUI (в котором могут отсутствовать действительно необходимые примитивы).