Объектно-ориентированный анализ
Границы между стадиями анализа и проектирования размыты, но решаемые ими задачи определяются достаточно четко. В процессе анализа мы моделируем проблему, обнаруживая классы и объекты, которые составляют словарь проблемной области. При объектно-ориентированном проектировании мы изобретаем абстракции и механизмы, обеспечивающие поведение, требуемое моделью [Обозначения и процессы, описанные в этой книге, в равной степени относятся к фазам и анализа и проектирования (в традиционном понимании), как мы увидим в главе 6. Именно по этой причине мы сменили во втором издании название книги на "Объектно-ориентированный анализ и проектирование"].
Теперь мы рассмотрим несколько проверенных практикой подходов к анализу объектно-ориентированных систем.
Классические подходы. Разные ученые находят различные источники классов и объектов, согласующихся с требованиями предметной области. Мы называем эти подходы классическими, поскольку они опираются на классическую категоризацию.
Например, Шлаер и Меллор предлагают следующих кандидатов в классы и объекты [32]:
• Осязаемые предметы | Автомобили, телеметрические данные, датчики давления |
• Роли | Мать, учитель, политик |
• События | Посадка, прерывание, запрос |
• Взаимодействие | Заем, встреча, пересечение |
Что-то в этом роде предлагает Росс, исходя из перспектив моделирования баз данных [33]:
• Люди | Человеческие существа, выполняющие некоторые функции |
• Места | Области, связанные с людьми или предметами |
• Предметы | Осязаемый материальный объект или группа объектов |
• Организации | Формально организованная совокупность людей, ресурсов, оборудования, которая имеет определенную цель и существование которой в целом не зависит от индивидуумов |
• Концепции | Принципы и идеи, сами по себе неосязаемые, но предназначенные для организации деятельности и/или общения, или же для наблюдения за ними |
• События | Нечто случающееся с чем-то в заданное время или последовательно |
Коад и Иордан предложили свой список [34]:
• Структуры | Отношения "целое-часть" и "общее-частное" |
• Другие системы | Внешние системы, с которыми взаимодействует приложение |
• Устройства | Устройства, с которыми взаимодействует приложение |
• События | Происшествия, которые должны быть запомнены |
• Разыгрываемые роли | Роли, которые исполняют пользователи, работающие с приложением |
• Места | Здания, офисы и другие места, существенные для работы приложения |
• Организационные единицы | Группы, к которым принадлежат пользователи |
На более высоком уровне абстракции Коад вводит понятие предметной области, которая в сущности является логически связанной группой классов, относящейся к высокоуровневым функциям системы.
Анализ поведения. В то время как классические подходы концентрируют внимание на осязаемых элементах предметной области, другая школа мысли объектно-ориентированного анализа сосредотачивается на динамическом поведении как на первоисточнике объектов и классов [Шлаер и Меллор дополнили свою более раннюю работу, обратив внимание также и на поведение. В частности, они изучали жизненный цикл объекта как средство понимания границ]. Это напоминает концептуальную кластеризацию, рассмотренную выше: мы формируем классы, основываясь на группах объектов, демонстрирующих сходное поведение.
Вирфс-Брок предлагает понятие ответственности объекта, под которыми следует понимать "его знания и умения. Ответственность - это способ выразить цель объекта и его место в системе. Ответственность объекта есть совокупность всех услуг, которые он может предоставлять по всем его контрактам" [36]. То есть, мы объединяем вместе те объекты, которые имеют сходные ответственности и строим иерархию классов, в которой каждый подкласс, выполняя обязательства суперкласса, привносит свои дополнительные услуги.
Рубин и Гольдберг предлагают идентифицировать классы и объекты, анализируя функционирование системы: "Наш подход основан на изучении поведения системы. Мы сопоставляем формы поведения с частями системы и пытаемся понять, какая часть инициирует поведение и какие части в нем участвуют...
Инициаторы и участники, играющие существенные роли, опознаются как объекты и делаются ответственными за эти роли" [37].
Идеи Рубина тесно связаны с предложенным в 1979 году Альбрехтом подходом с точки зрения функций. По его определению, функция "определяется как отдельное бизнес-действие конечного пользователя" [38], то есть: ввод/вывод, запрос, файл или интерфейс. Очевидно, что эта концепция происходит из области информационных систем. Однако, она может быть применена к любой автоматизированной системе. По существу, функция - это любое достоверно видимое извне и имеющее отношение к делу поведение системы.
Анализ предметной области. До сих пор мы неявно имели в виду единственное разрабатываемое нами приложение. Но иногда в поисках полезных и уже доказавших свою работоспособность идей полезно обратиться сразу ко всем приложениям в рамках данной предметной области, как, например, ведение историй болезни пациентов, торговля ценными бумагами, разработка компиляторов или системы управления ракетами. Если вы находитесь в середине разработки и застряли, анализ какой-нибудь узкой предметной области может помочь, указав вам на ключевые абстракции, оказавшиеся полезными в сходных системах. Анализ предметной области работает очень хорошо, исключая разве что лишь очень специальные ситуации, так как уникальные программные системы встречаются крайне редко.
Идею анализа предметной области впервые предложил Нейборс. Мы определим такой анализ как "попытку выделить те объекты, операции и связи, которые эксперты данной области считают наиболее важными" [39]. Мур и Байлин определяют следующие этапы в анализе области:
"Построение скелетной модели предметной области при консультациях с экспертами в этой области.
Изучение существующих в данной области систем и представление результатов в стандартном виде.
Определение сходства и различий между системами при участии экспертов.
Уточнение общей модели для приспособления к нуждам конкретной системы" [40].
Анализ области можно вести относительно аналогичных приложений (вертикально) или относительно аналогичных частей одного и того же приложения (горизонтально). Например, начиная проектировать систему учета пациентов, имеет смысл рассмотреть уже имеющиеся подобные системы, чтобы понять, какие ключевые абстракции и механизмы, использованные в них, будут вам полезны, а какие нет. Аналогично система бухгалтерского учета должна представлять различные виды отчетов. Если считать отчеты некой предметной областью, ее анализ может привести разработчика к пониманию ключевых абстракций и механизмов, которые обслуживают все виды отчетов. Полученные таким образом классы и объекты представляют собой множество ключевых абстракций и механизмов, отобранных с учетом цели исходной задачи: создания системы отчетов. Поэтому окончательный проект будет проще.
Определим теперь, кто такой эксперт? В роли эксперта часто выступает просто пользователь системы, например, инженер или диспетчер. Он не обязательно должен быть программистом, но должен быть близко знаком с исследуемой проблемой и разговаривать на языке этой проблемы.
Менеджеры проектов заинтересованы в непосредственном сотрудничестве пользователей и разработчиков системы. Но для очень сложных систем прикладной анализ является формальным процессом, для которого требуется большое число экспертов и разработчиков на длительный период времени. На практике такой формальный анализ требуется редко. Обычно для начального уяснения проблемы достаточно короткой встречи экспертов и разработчиков. Удивительно, как мало информации требуется для продуктивной работы разработчика. Однако мы считаем чрезвычайно полезными такие встречи в течение всей разработки. Анализ прикладной области лучше всего вести шаг за шагом - немного поанализировать, потом немного попроектировать и т.д.
Анализ вариантов. По отдельности классический подход, поведенческий подход и изучение предметной области, рассмотренные выше, сильно зависят от индивидуальных способностей и опыта аналитика.
Для большинства реальных проектов одновременное применение всех трех подходов неприемлемо, так как процесс анализа становится недетерминированным и непредсказуемым.
Анализ вариантов - это подход, который можно успешно сочетать с первыми тремя, делая их применение более упорядоченным. Впервые его формализовал Джекобсон, определивший вариант применения, как "частный пример или образец использования, сценарий, начинающийся с того, что пользователь системы инициирует операцию или последовательность взаимосвязанных событий" [41].
Коротко говоря, этот вид анализа можно начинать вместе с анализом требований. В этот момент пользователи, эксперты и разработчики перечисляют сценарии, наиболее существенные для работы системы (пока не углубляясь в детали). Затем они тщательно прорабатывают сценарии, раскладывая их по кадрам, как делают телевизионщики и кинематографисты [42]. При этом они устанавливают, какие объекты участвуют в сценарии, каковы обязанности каждого объекта и как они взаимодействуют в терминах операций. Тем самым группа разработчиков вынуждена четко распределить области влияния абстракций. Далее набор сценариев расширяется, чтобы учесть исключительные ситуации и вторичное поведение (Гольдстейн и Алджер называют это периферийными аспектами [43]). В результате появляются новые или уточняются существующие абстракции. Позже, в главе 6, мы покажем, как сценарии используются для тестирования.
CRC-карточки. CRC обозначает Class-Responsibilities-Collaborators (Класс/Ответственности/Участники). Это простой и замечательно эффективный способ анализа сценариев. Карты CRC впервые предложили Бек и Каннингхэм для обучения объектно-ориентированному программированию, но такие карточки оказались отличным инструментом для мозговых атак и общения разработчиков между собой.
Собственно, это обычные библиографические карточки 3х5 дюйма (если позволяет бюджет вашего проекта, купите 5х7; очень хорошо, если карточки будут линованными, а разноцветные - просто мечта). На карточках вы пишите (обязательно карандашом) сверху - название класса, снизу в левой половине - за что он отвечает, а в правой половине - с кем он сотрудничает.
Проходя по сценарию, заводите по карточке на каждый обнаруженный класс и дописывайте в нее новые пункты. При этом каждый раз обдумывайте, что из этого получается, и "выделяйте излишек ответственности" в новый класс или, что случается чаще всего, перенесите ответственности с одного большого класса на несколько более детальных классов, или, возможно, передайте часть обязанностей другому классу.
Карточки можно раскладывать так, чтобы представить формы сотрудничества объектов. С точки зрения динамики сценария, их расположение может показать поток сообщений между объектами, с точки зрения статики они представляют иерархии классов.
Неформальное описание. Радикальная альтернатива классическому анализу была предложена в чрезвычайно простом методе Аббота. Согласно этому методу надо описать задачу или ее часть на простом английском языке, а потом подчеркнуть существительные и глаголы [45]. Существительные - кандидаты на роль классов, а глаголы могут стать именами операций. Метод можно автоматизировать, и такая система была построена в Токийском технологическом институте и в Fujitsu [46].
Подход Аббота полезен, так как он прост и заставляет разработчика заниматься словарем предметной области. Однако он весьма приблизителен и непригоден для сколько-нибудь сложных проблем. Человеческий язык - ужасно неточное средство выражения, потому список объектов и операций зависит от умения разработчика записывать свои мысли. Тем более, что для многих существительных можно найти соответствующую глагольную форму и наоборот.
Структурный анализ. Вторая альтернатива классической технике объектно-ориентированного анализа использует структурный анализ как основу для объектно-ориентированного проектирования. Такой подход привлекателен потому, что много аналитиков применяют этот подход и имеется большое число программных CASE-средств, поддерживающих автоматизацию этих методов. Нам лично не нравится использовать структурный анализ как основу для объектно-ориентированного проектирования, но для некоторых организаций такой прагматический подход не имеет альтернативы.
После проведения структурного анализа мы уже имеем модель системы, описанную диаграммами потоков данных и другими продуктами структурного анализа. Эти диаграммы дают нам формальную модель проблемы. Исходя из модели, мы можем приступить к определению осмысленных классов и объектов тремя различными способами.
МакМенамин и Палмер предлагают сначала приступить к формированию словаря данных и затем к анализу контекстных диаграмм модели. Они говорят:
"рассматривая список основных структур данных, следует подумать, о чем они говорят или что описывают. Например, если они прилагательные, то какие существительные они описывают? Ответы на такие вопросы могут пополнить ваш список объектов" [47]. Эти кандидаты в объекты происходят из окружающей среды, из существенных входных и выходных данных, а также продуктов, услуг и других ресурсов, которыми она управляет.
Следующие два способа основаны на анализе отдельных диаграмм потоков данных. Если взять какую-нибудь диаграмму потоков (в терминологии Барда и Меллора [48]), то кандидаты в объекты это:
внешние сущности;
хранилища данных;
хранилища управляющих сущностей;
управляющие преобразования.
Кандидаты в классы:
потоки данных;
потоки управления.
Остается преобразование данных, которое мы можем рассматривать как операции над существующими объектами или как поведение некоторого объекта, который мы создали специально для выполнения нужного преобразования.
Зайдевиц и Старк предлагают еще один метод, который они называют анализом абстракций. Метод базируется на идентификации основных сущностей, которые по своей природе аналогичны основным преобразованиям в структурном проектировании. Как они говорят, "в структурном анализе входные и выходные данные изучаются до тех пор, пока не достигнут высшего уровня абстракции. Процесс преобразования входных данных в выходные есть основное преобразование. В абстрактном анализе разработчик делает то же самое, а также изучает основное преобразование для того, чтобы определить, какие процессы и состояния представляют наилучшую абстрактную модель системы" [49].
После определения основной сущности в диаграмме потоков данных аналитик приступает к изучению всей инфраструктуры, прослеживая входящие и исходящие потоки данных из центра, группируя процессы и состояния, встречающиеся по пути. Для практического использования авторы нашли анализ абстракций слишком сложным и в качестве альтернативы предлагают объектно-ориентированный анализ [50].
Необходимо отметить, что принципы структурного проектирования, которое, естественно, следует за структурным анализом, полностью ортогональны принципам объектно-ориентированного проектирования. Наш опыт показывает, что использование структурного анализа в процессе объектно-ориентированного проектирования часто приводит к полному провалу, если разработчик не способен сопротивляться желанию свалиться в структурную пропасть. Другая очень серьезная опасность заключается в том, что многие аналитики любят рисовать диаграммы потоков данных, которые представляют собой скорее описание проекта, чем модель существа системы. Очень трудно построить объектно-ориентированную систему, если модель столь очевидно ориентирована на алгоритмическую декомпозицию. Поэтому мы предпочитаем объектно-ориентированный анализ и анализ проблемной области как подготовительный этап для объектно-ориентированного проектирования. При этом уменьшается риск замусорить проект элементами алгоритмического анализа.
Если же по каким-либо уважительным причинам [Политические и исторические причины в качестве уважительных не принимаются] приходится взять за основу структурный анализ, прекратите строить диаграммы, как только они начинают смахивать на проект программы, а не на модель предметной области. Помните, что материалы проектирования, такие, как диаграммы потоков данных, это не конечный продукт, а инструмент разработчиков. Обычно строятся диаграммы, а затем разрабатываются механизмы, обеспечивающие необходимое поведение системы, то есть сам акт проектирования видоизменяет начальную модель. Поддержание соответствия модели и развивающегося проекта - дело трудное, и, честно говоря, бесполезное.Имеет смысл сохранять только продукт структурного анализа высокого уровня абстракции. Он отражает существенные черты и достаточно независим от проекта системы.
4.3. Ключевые абстракции и механизмы