5.1. Элементы обозначений
5.1. Элементы обозначений
Необходимость разных точек зрения
Невозможно охватить все тонкие детали сложной программной системы одним взглядом. Как отмечают Клейн и Джингрич: "Необходимо понять как функциональные, так и структурные свойства объектов. Следует уяснить также таксономическую структуру классов объектов, используемые механизмы наследования, индивидуальное поведение объектов и динамическое поведение системы в целом. Эта задача в чем-то аналогична показу футбольного или теннисного матча, когда для вразумительной передачи происходящего действия требуется несколько камер, расположенных в разных углах спортивной площадки. Каждая камера передает свой аспект игры, недоступный другим камерам" [4].
На рис. 5-1 представлены различные типы моделей (описанные в главе 1), которые мы считаем главными в объектно-ориентированном подходе. Через них будут выражаться результаты анализа и проектирования, выполненные в рамках любого проекта. Эти модели в совокупности семантически достаточно богаты и универсальны, чтобы разработчик мог выразить все заслуживающие внимания стратегические и тактические решения, которые он должен принять при анализе системы и формировании ее архитектуры. Кроме того, эти модели достаточно полны, чтобы служить техническим проектом реализации практически на любом объектно-ориентированном языке программирования.
Наша система обозначений богата деталями, но это не означает, что в каждом проекте необходимо использовать все ее аспекты. На практике для описания большей части итогов анализа и проектирования достаточно некоторого малого подмножества этой системы; один наш коллега называет такие облегченные обозначения "нотацией Booch Lite" (сокращенная нотация Буча). В процессе знакомства с нашей системой обозначений мы четко выделим это подмножество. Зачем же тогда беспокоиться о деталях системы обозначений, не вошедших в минимальное подмножество? В основном они нужны, чтобы выражать некоторые важные тактические решения; а некоторые из них предназначены для создания программных инструментов CASE. Мы будем называть их дополнениями.
Как отмечает Вайнберг: "В некоторых областях (таких, как архитектура), в процессе проектирования графический план чаще всего представлен в виде общих набросков, а строго детализированные описания, пока не окончена творческая часть становления проекта, используются редко" [5]. Следует помнить, что обозначения - только средство выразить итоги размышлений над архитектурой и поведением системы, а никак не самоцель. Надо пользоваться исключительно теми элементами обозначений, которые необходимы, и не более того. Также, как опасно ставить слишком жесткие требования, нехорошо чересчур подробно описывать решение задачи. Например, на чертеже архитектор может показать расположение выключателя света в комнате, но его точное место не будет определяться, пока заказчик и прораб не произведут осмотр уже сооруженного здания для уточнения деталей отделки. Глупо было бы заранее указывать на чертеже трехмерные координаты этого выключателя (конечно, если это не является функционально важной деталью для заказчика: может быть, все члены его семьи имеют рост намного выше или ниже среднего). Если разработчики большой программной системы - высококвалифицированные специалисты и уже сработались друг с другом, им будет достаточно и грубых набросков, хотя и в этом случае они должны оставить свое творческое наследие эксплуатационщикам в удобоваримом виде. Если же разработчики неопытны, отделены друг от друга во времени или пространстве или если так установлено контрактом, то на протяжении всего процесса проектирования необходимы более детальные эскизы проекта. Система обозначений, которую мы представляем в этой главе, учитывает эти ситуации.
Рис. 5-1. Объектные модели.
Различные языки программирования описывают одни и те же понятия различно. Наша система обозначений не зависит от конкретного языка. Конечно, некоторые ее элементы могут не иметь аналогов в языке, на котором будет написана проектируемая система. В этом случае просто не надо ими пользоваться. Например, в Smalltalk не бывает свободных подпрограмм, следовательно, в проект нет смысла закладывать утилиты классов. Аналогично, C++ не поддерживает метаклассы, следовательно, этот элемент должен быть исключен. Но нет ничего предосудительного в подгонке обозначений под конструкции выбранного языка. Например, в CLOS операции можно снабдить специальными пометками, чтобы определить методы :before, :after и :around. Подобным же образом, в системе автоматического проектирования для C++ вместо спецификаций класса можно пользоваться прямо заголовочными файлами.
Цель этой главы - определить синтаксис и семантику наших обозначений для объектно-ориентированного анализа и проектирования. В качестве примера мы будем использовать гидропонную теплицу, которая рассматривалась в главе 2. В настоящей главе не обсуждается, как, собственно, были получены представленные в примерах решения: это задача главы 6. В главе 7 обсуждаются практические аспекты этого процесса, а в главах 8-12 система обозначений демонстрируется в деле на серии примеров разработки приложений.
Модели и ракурсы
В главе 3 мы объяснили, что такое классы и объекты, а также какова связь между ними. Как показано на рис. 5-1, при принятии решений в анализе и проектировании полезно рассмотреть взаимодействие классов и объектов в двух измерениях: логическом/физическом и статическом/динамическом. Оба этих аспекта необходимы для определения структуры и поведения объектной системы.
В каждом из двух измерений мы строим несколько диаграмм, которые дают нам вид моделей системы в различных ракурсах. Таким образом, модели системы содержат всю информацию о ее классах, связях и других сущностях, а каждая диаграмма представляет одну из проекций модели. В установившемся состоянии проекта, все такие диаграммы должны быть согласованы с моделью, а, следовательно, и друг с другом.
Рассмотрим для примера систему, включающую в себя несколько сотен классов; эти классы образуют часть модели. Невозможно, а на самом деле и не нужно представлять все классы и их связи на единственной диаграмме. Вместо этого мы можем описать модель в нескольких диаграммах классов, каждая из которых представляет только один ее ракурс. Одна диаграмма может показывать структуру наследования некоторых ключевых классов; другая - транзитивное замыкание множества всех классов, используемых конкретным классом. Когда модель "устоится" (придет в устойчивое состояние), все такие диаграммы становятся семантически согласованными друг с другом и с моделью. Например, если по данному сценарию (который мы описываем на диаграмме объектов), объект A посылает сообщение M объекту B, то M должно быть прямо или косвенно определено в классе B. В соответствующей диаграмме классов должна быть надлежащая связь между классами A и B, так, чтобы экземпляры класса A действительно могли посылать сообщение M.
Для простоты на диаграммах все сущности с одинаковыми именами в одной области видимости рассматриваются как ссылки на одинаковые персонажи системы. Исключением из этого правила могут быть только операции, имена которых могут быть перегружены.
Чтобы различать диаграммы, мы должны дать им имена, которые отражали бы их предмет и назначение. Можно снабдить диаграммы и другими комментариями или метками, которые мы вскоре опишем; эти комментарии, как правило, не имеют дополнительной семантики.
Логическая и физическая модели
Логическое представление описывает перечень и смысл ключевых абстракций и механизмов, которые формируют предметную область или определяют архитектуру системы. Физическая модель определяет конкретную программно-аппаратную платформу, на которой реализована система.
При анализе мы должны задать следующие вопросы:
• Каково требуемое поведение системы?
• Каковы роли и обязанности объектов по поддержанию этого поведения?
Как было отмечено в предыдущей главе, чтобы выразить наши решения о поведении системы мы пользуемся сценариями. В логической модели важнейшим средством для описания сценариев служат диаграммы объектов. При анализе могут быть полезны диаграммы классов, позволяющие увидеть общие роли и обязанности объектов.
При проектировании мы должны задать следующие вопросы относительно архитектуры системы:
• Какие существуют классы и какие есть между ними связи?
• Какие механизмы регулируют взаимодействие классов?
• Где должен быть объявлен каждый класс?
• Как распределить процессы по процессорам и как организовать работу каждого процессора, если требуется обработка нескольких процессов?
Чтобы ответить на эти вопросы, мы используем следующие диаграммы:
• диаграммы классов
• диаграммы объектов
• диаграммы модулей
• диаграммы процессов.
Статическая и динамическая модели
Четыре введенные нами типа диаграмм являются по большей части статическими. Но практически во всех системах происходят события: объекты рождаются и уничтожаются, посылают друг другу сообщения, причем в определенном порядке, внешние события вызывают операции объектов. Не удивительно, что описание динамических событий на статическом носителе, например, на листе бумаги, будет трудной задачей, но эта же трудность встречается фактически во всех областях науки. В объектно-ориентированном проектировании мы отражаем динамическую семантику двумя дополнительными диаграммами:
• диаграммами переходов из одного состояния в другое
• диаграммами взаимодействия.
Каждый класс может иметь собственную диаграмму переходов, которая показывает, как объект класса переходит из состояния в состояние под воздействием событий. По диаграмме объектов, имея сценарий, можно построить диаграмму взаимодействий, чтобы показать порядок передачи сообщений.
Инструменты проектирования
Плохой разработчик, имея систему автоматического проектирования, сможет создать своего программного монстра за более короткий срок чем раньше. Великие проекты создаются великими проектировщиками, а не инструментами. Инструменты проектирования дают возможность проявиться индивидуальности, освобождают ее, чтобы она могла сосредоточиться исключительно на творческих задачах проектирования и анализа. Существуют вещи, которые автоматизированные системы проектирования могут делать хорошо, и есть вещи, которые они вообще не умеют. Например, если мы используем диаграмму объектов, чтобы показать сценарий с сообщением, посылаемым от одного объекта другому, автоматизированная система проектирования может гарантировать, что посылаемое сообщение будет в протоколе объекта; это пример проверки совместимости. Если мы введем инвариант, например, такой: "существует не более трех экземпляров данного класса", то мы ожидаем, что наш инструмент проследит за соблюдением данного требования; это пример проверки ограничения. Кроме того, система может оповестить вас, если какие-либо объявленные классы или методы не используются в проекте (проверка на полноту). Наконец, более сложная автоматическая система проектирования может определить длительность конкретной операции или достижимость состояния на диаграмме состояний; это пример автоматического анализа. Но, с другой стороны, никакая автоматическая система не сможет выявить новый класс, чтобы упростить вашу систему классов. Мы, конечно, можем попытаться создать такой инструмент, используя экспертные системы, но для этого понадобятся, во-первых, эксперты как в области объектно-ориентированного программирования, так и в предметной области, а во-вторых, четко сформулированные правила классификации и много здравого смысла. Мы не ожидаем появления таких средств в ближайшем будущем. В то же время, у нас есть вполне реальные проекты, которыми стоит заняться.