ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.11.2023

Просмотров: 919

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

277
В дополнение к тем деталям, которые могут сообщить эксперты за- казчика по предметной области, разработчику придется решить, как в системе представить эти данные в доступной форме для самого заказчи- ка, и в любом случае придется решать задачу того, как сохранять ин- формацию, вводимую потенциальными пользователями программной системы. Для решения этих вопросов используются интерфейсные
классы, классы-контроллеры и классы-сущности [15,16]. Интерфейс- ный класс – это класс, предназначенный для связи элементов вне систе- мы с элементами, входящими в состав системы. Поэтому такой класс часто называют граничным. Классы сущности представляют данные.
Обычно сущности передают информацию, которая хранится в базе дан- ных. Классы-контроллеры управляют другими классами.
Как правило, пользователи (заказчик) могут дать много полезной информации о классах-сущностях и помочь определить вид графиче- ского интерфейса пользователя, основываясь на том, как они выполня- ют задачи своей повседневной деятельности. Однако этого недостаточ- но, и разработчику нужно еще выявить классы-контроллеры и интер- фейсные классы. Автор работы [16] рекомендует помнить тот факт, что эксперты по предметной области могут сообщить разработчику боль- шое количество информации. Они могут рассказать многое о данных, которые им необходимо хранить, пояснить кое-какие детали о процес- сах, с помощью которых они получают эти данные, и немного о том, каким образом им хотелось бы вводить эти данные в компьютер.
Вторым важным моментом является то, что эксперты предметной области в рамках своей деятельности могут выполнять большое количе- ство действий, которые будут просто непонятны постороннему наблю- дателю. Это означает, что проектировщик, возможно, никогда и не пы- тался исследовать в целом то, что делает фирма-заказчик и как она это делает, и не пытался найти способ, как оптимизировать ее деятельность.
В результате проектировщик может получить много информации от клиентов об их деятельности, которая, с его точки зрения, будет иметь слабое отношение к разрабатываемой системе. Но при этом эксперты по предметной области будут считать, что эта информация очень сущест- венна.
После того, как разработчик выяснит у пользователей все о классах- сущностях, его задачей становится определение классов-контроллеров и интерфейсных классов. При разработке модели системы к сущностным классам добавляется стереотип “entity” и специальный символ класса- сущности, поддерживаемый во многих инструментах разработки, на- пример, Rational RSA (рис. 6.7). Класс-контроллер является связующим кодом, который управляет другими классами и обеспечивает передачу данных между классами-сущностями и интерфейсными классами. Клас- сы-контроллеры обозначаются при помощи стереотипа “control”, добав- ляемого к обычному классификатору, и специального символа (см. рис.
6.7). Интерфейсные или граничные классы моделируются, как показано на этом же рисунке и имеют стереотип “boundary”.


278
Рис. 6.7. Изображение классов в Rational RSA
Заметим, что классы-сущности включают в себя логические сущно- сти. Обычно их появление является результатом какого-либо смешанно- го запроса в базу данных. Выявление логических и простых сущностей является относительно простой задачей, так как теория реляционных баз данных легка для понимания. Классам-сущностям, определенным для отдельных таблиц и различных смешанных запросов, включающих обращения к нескольким таблицам, можно присваивать стереотип
“table”.
Вообще процесс выявления классов при работе над проектом систе- мы весьма нетривиален. Существует много рекомендаций по организа- ции такой работы. Одна из них – использование CRC (Class responsibil- ity and collaborator) – карты функциональности и сотрудников класса
[16].
В заключение этого раздела отметим, что многие специалисты (про- граммисты и ученые) высказывают отрицательные суждения по вопросу перспективности объектно-ориентированной технологии программиро- вания. Поводом к таким высказываниям послужила публикация извест- ной и классической в мире программирования статьи “Почему объект- но-ориентированное программирование провалилось?”. Статья была написана доктором компьютерных наук Стэнфорда, старшим архитек- тором по разработке ПО сначала Sun, а потом и IBM, Ричардом Гэбрие- лом (Richard Gabriel) [34]. Он никогда не скрывал своего скептического отношения к парадигме ООП. В 2002 году, по прошествии 2 лет после первоначальной публикации критической статьи, автора пригласили выступить на ежегодной конференции OOPSLA (центральная конфе- ренция IT-специалистов по объектно-ориентированным языкам и мето- дологиям разработки ПО) и изложить свои критические взгляды.
В качестве оппонента пригласили Гая Стила (Guy Steele) , разработ- чика языка Scheme, крупнейшего специалиста-теоретика по ООП, авто- ритет которого в американской академической среде непререкаем. Что- бы максимально отразить позиции выступающих, их решили усилить ещё двумя выступающими. В качестве “анти-объектника” дополнитель- но пригласили Пола Грэма (Paul Graham) , крупнейшего специалиста по
Lisp, автора многочисленных книг и стандартизаций Lisp. В стан объ- ектников пригласили Джеймса Ноубла (James Noble), автора одних из первых книг и работ по теории ООП. Многие участники вспоминают, что конференция надолго запомнилась им по тому уровню обсуждения, которое завязалось тогда в этой публичной “интеллектуальной дуэли” фактически диаметрально разных школ программирования. Но факт остаётся фактом: сторона, представлявшая объектно-ориентированное


279 программирование, во время открытой дискуссии с противниками под смех зала даже запуталась в своих же концепциях.
Пол Грэм утверждал, что половина всех концепций ООП являются скорее плохими, чем хорошими, в связи с чем он искренне сочувствует
ООП-программистам, тогда как вторая половина от оставшихся кон- цепций и вовсе не имеет никакого отношения к ООП, с которыми их почему-то постоянно ассоциируют. Например, он говорит [34]: “В восьмидесятых годах метод повторного использования каким-то неяс- ным мне образом связали с объектно-ориентированным программиро- ванием, и сколь угодно многочисленные имеющиеся доказательства обратного, по-видимому, уже не избавят этот метод от клейма ООП.
Хотя иногда объектно-ориентированный код годится для повторного использования, таким его делает вовсе не объектно-ориентированность, а программирование в стиле "снизу-вверх". Возьмём, например, биб- лиотеки: их можно подгружать и повторно использовать сколько угод- но, потому что, по сути, они представляют собой отдельный язык. И при этом совсем неважно, написаны ли они в объектно-ориентированном стиле или нет.
Читателям этой книги будет интересно познакомиться с полным тек- стом статьи [34]. Однако только время покажет, кто в итоге окажется правым, а кто искренне заблуждался.
6.4.3. Компонентный подход
Компоненты представляют собой автономный код (подсистему), ко- торый может быть повторно использован за счет его независимого раз- вертывания. Компоненты не обязательно должны быть большими по объему кода, но в основном они больше по объему отдельного класса или группы слабо связанных классов. Компоненты имеют множество предоставляемых и требуемых интерфейсов и используются в больших сложных приложениях с десятками и сотнями классов предметной об- ласти. В сложных случаях разработки больших систем, например при разработке корпоративной информационной системы потребуются диа- граммы компонентов [11, 18].
Как отмечается автором книги [16], существует два основных спосо- ба выявления компонентов. Первым является метод движения сверху вниз, а вторым – движение снизу вверх. По сути это методы проектиро- вания архитектуры программной системы, которые характерны и для структурного проектирования с модульно-интерфейсным подходом.
Если смотреть глубже – это не что иное, как метод декомпозиция сложной системы в первом случае методом сверху вниз, а во втором случае – синтез сложной системы на основе метода проектирования снизу вверх. При этом образуется многоуровневая архитектура про- граммной системы (см. п. 2.6).
В ряде монографий и статей рекомендуется определять архитектуру системы на основе компонентов методом сверху вниз. В этом случае в первую очередь определяются компоненты (крупные модули системы),


280 а потом интерфейсы этих компонентов. Как только компоненты и их интерфейсы определены, можно разделить задачи реализации системы среди участников процесса разработки, поручив проектирование каждо- го компонента отдельным группам. С того момента, как каждый согла- сится с разработкой интерфейсов, проектировщики будут свободны в реализации внутренних частей компонента и могут осуществлять ее любым способом, который они выберут.
По мнению автора [16], такой поход может быть эффективным в том случае, если команда проектировщиков применяет хорошо продуман- ные компоненты с понятными и известными им интерфейсами. Однако правильно выявить все новые компоненты путем проектирования свер- ху вниз достаточно сложно. Кроме того, это достаточно сложный стиль программирования, связанный с тем, что системы, основанные на ком- понентах, имеют от трех до пяти вспомогательных интерфейсов и про- межуточных классов для каждого класса предметной области. Поэтому системы, основанные на компонентах, могут быть достаточно трудоем- кими, дорогими и рискованными.
При разработке компонентной системы методом снизу вверх в пер- вую очередь определяются классы предметной области, т.е. те, которые служат непосредственно для решения задач предметной области, а не вопросов архитектуры приложения. В результате основные усилия кон- центрируются, прежде всего, на решении поставленной задачи вместо описания сложной архитектуры. Применяя метод разработки снизу вверх и выявляя классы предметной области, проектировщики имеют больший потенциал для решения поставленной задачи. Кроме того, все- гда можно объединить классы предметной области в компоненты, если сложность проекта растет, некоторые группы классов можно развернуть и повторно использовать, включив их в состав компонентов.
Оба метода проектирования компонентных систем имеют право на использование. Для небольших приложений и приложений среднего размера, вероятно, не потребуются компоненты и в этих случаях можно воспользоваться методом снизу вверх. Для приложений корпоративного масштаба потребуется более мощная методология, и в этом случае ме- тод проектировании сверху вниз может оказаться более подходящим.
Способы декомпозиции могут быть различными. При модульно- интерфейсном подходе на верхних уровнях осуществляется структурная декомпозиция, на средних и нижних – функциональная. При объектно- ориентированном подходе декомпозиция связана с правильным подхо- дом к определению классов предметной области. Каждый класс должен согласоваться с принципами хорошего объектно-ориентированного проектирования. К принципам хорошего объектно-ориентированного проектирования, в частности, относятся принцип единственной ответст- венности (ПЕО – Single Responsibility Principle (SRP)), принцип откры- тости-закрытости (ПОЗ – OpenClosed Principle (OCP)) и принцип под- становки Лискова (ППЛ – Liskov Substitution Principle (LSP)) [27].
Принцип единственной ответственности говорит о том, что у такого элемента, как класс, должна быть лишь одна, определяемая им ответст-


281 венность. Если же класс отвечает и за представление данных и доступ к ним, это характерный пример нарушения принципа ПЕО. Принцип от- крытости-закрытости заключается в том, что класс должен быть закрыт для модификации, но открыт для расширения. При изменении класса всегда существует риск что-то нарушить. Но если вместо модификации класс расширяется подклассом, такое изменение менее рискованно.
Принцип подстановки Лискова (ППЛ) лучше пояснить следующим примером. Допустим, что существует иерархия наследования для клас- сов Person (Лицо) и Student (Студент). При использовании класса Person должна быть возможность использовать класс Student, поскольку он является подклассом Person. На первый взгляд, это всегда происходит автоматически, хотя и не совсем очевидно в отношении рефлексии — метода, позволяющего проверять программными средствами тип экзем- пляра объекта, считывать и устанавливать его свойства и поля, а также вызывать его методы, ничего не зная заранее об этом типе. Так, в мето- де, использующем рефлексию для обращения к классу Person, может и не предполагаться подкласс Student.
Проблема рефлексии имеет отношение к синтаксису. Мартин Р.
[Мартин] приводит в большей степени семантический пример класса
Square (Квадрат), который относится к классу Rectangle (Прямоуголь- ник). Но когда используется метод задания ширины квадрата SetWidth() для класса Square, это не имеет смысла — по крайней мере, для этого нужно еще вызвать (внутренним образом) метод задания высоты квад- рата SetHeight(). Такое поведение отличается оттого, что требуется для класса Rectangle.
Безусловно, все эти принципы оказываются спорными в определен- ных контекстах. Ими следует руководствоваться лишь как рекоменда- циями, но не “истиной в последней инстанции”. Например, применяя
ПОЗ, нетрудно переусердствовать до такой степени, когда становится ясно, что для реализации метода лучше модифицировать класс, чем расширять его. И ввод метода в класс можно также рассматривать как расширение.
Заключая рассмотрение различных методов представления архитек- туры сложных программных систем, можно констатировать факт пред- ставления архитектуры таких систем в виде многослойной иерархиче- ской системы, которую удобно представлять иерархической системой вложенных виртуальных машин.
1   ...   21   22   23   24   25   26   27   28   ...   37