Основным преимуществом объектно-ориентированных языков программирования, таких, как C++ и Smalltalk, является высокая степень повторного использования в хорошо спроектированных системах. Это означает, что для разработки каждого следующего приложения требуется гораздо меньше нового кода; следовательно, меньшее количество кода требуется сопровождать и поддерживать.

Повторное использование принимает различные формы: заимствование отдельных строк кода, отдельных классов или логически связанных между собой групп классов. Повтор строк наиболее прост (кто из программистов хоть однажды не использовал редактор для копирования реализации того или иного алгоритма из одной программы в другую?), но наименее выгоден (один и тот же фрагмент кода просто дублируется в различных приложениях). Мы поступим гораздо лучше, используя объектно- ориентированные языки программирования и обращаясь к существующим классам, модифицируя их или наследуя от них. Но еще больших успехов можно достичь, используя наборы классов, организованные в инструментальные библиотеки, - среды разработки. Как уже отмечалось в главе 4, под средой разработки понимается совокупность классов, предоставляющих набор услуг в определенной области; таким образом, среда разработки экспортирует ряд отдельных классов и механизмов, которые клиенты могут использовать непосредственно или адаптировать.

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

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

9.1. Анализ

Определение границ проблемной области

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

Тем, кого интересует теоретический фундамент, можно посоветовать обратиться к плодотворной работе Кнута [2], а также других исследователей в данной области, прежде всего: Ахо, Хопкрофт и Ульман [3], Керниган и Плаугер [4], Седжуик [5], Стабс и Вебре [6], Тененбаум и Аугенстейн [7] и Вирт [8]. По мере изучения теории мы сможем определить ряд основных абстракций для нашей библиотеки, таких как очереди, стеки и графы, а также алгоритмы быстрой сортировки, сравнение с образцом, заданным регулярным выражением, и направленный поиск по дереву.

Первое открытие в ходе нашего анализа - это четкое отделение структурных абстракций (таких как очереди, стеки и графы) от алгоритмических (сортировка, сравнение с образцом и поиск). Первая категория понятий хорошо соответствует классам. Вторая категория, на первый взгляд, не поддается объектно- ориентированной декомпозиции. Однако при надлежащем подходе оказывается, что она вполне возможна: мы можем ввести классы, экземпляры которых будут агентами, выполняющими данные функции. Как будет видно далее, объективация алгоритмических абстракций обеспечивает преимущества общности, благодаря тому, что алгоритмы можно разместить в иерархии 'обобщение/специализация'.

Требования к библиотеке базовых классов

Библиотека должна содержать универсальные структуры данных и алгоритмы, способные удовлетворить потребности большинства стандартных приложении C++. Кроме того, библиотека должна быть:  

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

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

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

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

• Простой  Библиотека должна иметь прозрачную структуру, дающую возможность пользователю легко находить и подключать к приложению ее фрагменты. 

• Расширяемой  Для пользователя должна быть реализована возможность включения в библиотеку новых классов. При этом архитектурная целостность среды разработки не должна нарушаться. 

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

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

Таким образом, первым результатом нашего анализа будет разделение всех абстракций на две категории:  

• Структуры   Содержит все структурные абстракции. 

 • Инструменты   Содержит все алгоритмические абстракции. 

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

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату