ЛК 5 Моделирование структуры

Объект – структура из данных и процедур их обработки, существующая в памяти компьютера во время выполнения программы.

Класс – описание множества однотипных объектов к тексте программы.

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

Доступ к реализации возможен только через интерфейс. Обычно в интерфейсе различают свойства (которые синтаксически выглядят как переменные) и методы (которые синтаксически выглядят как процедуры или функции). Мы будем использовать собирательное название составляющие для свойств и методов класса.

Кроме основной идеи инкапсуляции, с объектно-ориентированным программированием принято ассоциировать также понятия наследования и полиморфизма. Наследование — это способ структуризации описаний многих классов, который позволяет сократить текст программы, сделав его тем самым более обозримым, а значит более надежным и удобным.

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

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

Рассмотрим более детально, какие именно структуры нужно моделировать и зачем.

Мы выделяем следующие структуры:

• структура связей между объектами во время выполнения программы;

• структура хранения данных;

• структура программного кода;

• структура компонентов в приложении;

• структура используемых вычислительных ресурсов;

• структура сложных объектов, состоящих из взаимодействующих частей

• структура артефактов в проекте.

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

Структура связей между объектами во время выполнения программы. В парадигме объектно-ориентированного программирования процесс выполнения программы состоит в том, что программные объекты взаимодействуют друг с другом, обмениваясь сообщениями. Наиболее распространенным типом сообщения является вызов метода объекта одного класса из метода объекта другого класса. Для того чтобы вызвать метод объекта, нужно иметь доступ к этому объекту. На уровне программной реализации этот доступ может быть обеспечен самыми разнообразными механизмами. Например, в объекте содержащем вызывающий метод может хранится указатель (ссылка) на объект, содержащий вызываемый метод. Еще вариант: ссылка на объект с вызываемым методом может быть передана в качестве аргумента вызывающему методу. Возможно, используется какой-либо системный механизм удаленного вызова процедур, обеспечивающий доступ к объектам (например, такие как CORBA или DCOM) по идентификаторам. Если свойства объектов представлены записями в таблице базы данных, а методы — хранимыми процедурами СУБД (нередкий вариант реализации), то идентификация объектов осуществляется по первичному ключу таблицы. Как бы то ни было, во всех случаях имеет место следующая ситуация: один объект "знает" другие объекты и, значит, может вызвать открытые методы, использовать и изменять значения открытых свойств и т. д. В этом случае, мы говорим что объекты связаны, т. е. между ними есть связь. Для моделирования структуры связей в UML используются отношения ассоциации на диаграмме классов.

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

• persistent — экземпляры классификатора, ассоциации или значения атрибута,

соответственно, должны быть хранимыми;

• transient — противоположно предыдущему — сохранять экземпляры не

требуется (значение по умолчанию).

Структура программного кода. Не секрет, что программы существенно отличаются по величине — бывают программы большие и маленькие. Удивительным является то, насколько велики эти различия: от сотен строк кода (и менее) до сотен миллионов строк (и более). Столь большие количественные различия не могут не проявляться и на качественном уровне. Действительно, для маленьких программ структура кода практически не имеет значения, для больших — наоборот, имеет едва ли не решающее значение. Поскольку UML не является языком программирования, модель не определяет структуру кода непосредственно, однако косвенным образом структура модели существенно влияет на структуру кода. Большинство инструментов поддерживает полуавтоматическую генерацию кода для одного или нескольких объектно- ориентированных языков программирования. В большинстве случаев классы модели транслируются в классы (или эквивалентные им конструкции) целевого языка.

Структура сложных объектов, состоящих из взаимодействующих частей. Для моделирования этой структуры применяется новое средство UML 2 — диаграмма внутренней структуры классификатора.

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

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

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

Важнейшим типом дескрипторов являются классификаторы. Классификатор — это дескриптор множества однотипных объектов. Из этого определения непосредственно вытекает основное и характеристическое свойство классификатора: классификатор (прямо или косвенно) может иметь экземпляры.

В UML используются следующие классификаторы:

• класс;

• интерфейс;

• тип данных;

• узел;

• компонент;

• действующее лицо;

• вариант использования;

• подсистема.

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

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

Во-вторых, как уже было сказано, классификатор может иметь экземпляры. Экземпляры бывают прямые и косвенные.

Если некоторый объект непосредственно порожден с помощью конструктора классификатора А, то этот объект называется прямым экземпляром А.

Если классификатор А является обобщением классификатора В или если классификатор В является реализацией классификатора А, то все экземпляры классификатора В являются косвенными экземплярами классификатора А.

Данное свойство является транзитивным: если классификатор В является обобщением классификатора С, то все экземпляры С также являются косвенными экземплярами А. Именно это обстоятельство позволяет рассматривать абстрактные классификаторы. Действительно, абстрактный классификатор — это такой дескриптор множества объектов, в котором нет прямого описания элементов множества, но данный классификатор связан отношением обобщения с другими классификаторами и объединение множеств их экземпляров считается множеством экземпляров данного абстрактного классификатора. Другими словами, множество определяется не прямо, а через совокупность подмножеств. Например, интерфейс, будучи абстрактным классом, не может иметь непосредственных экземпляров, но реализующий его класс может, стало быть, интерфейс является классификатором.

В-третьих, классификатор (как и другие элементы модели) имеет видимость. Видимость определяет, может ли свойство одного классификатора (в том числе имя) использоваться в другом классификаторе. Другими словами, если в определенном контексте нечто доступно и может быть как-то использовано, то оно является видимым (в этом контексте). Если же оно не видимо, то и не может быть использовано. Видимость является свойством всех элементов модели (хотя не для всех элементов это свойство является существенным). Видимость может иметь одно из трех значений:

• открытый (обозначается знаком + или ключевым словом public);

• защищенный (обозначается знаком # или ключевым словом protected);

• закрытый (обозначается знаком – или ключевым словом private).

В-четвертых, все составляющие классификатора имеют область действия. Область действия определяет, как проявляет себя составляющая классификатора в экземплярах, т. е. имеют экземпляры свои значения составляющей или совместно используют одно значение.

Область действия имеет два возможных значения:

• экземпляр — никак специально не обозначается, поскольку подразумевается по умолчанию;

• классификатор — описание составляющей классификатора подчеркивается.

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

• У классификатора нет экземпляров — такой классификатор называется службой. Все составляющие службы имеют областью действия классификатор. Хранение информации, обрабатываемой службой, обеспечивают объекты использующие службу. Типичный пример — набор процедур общего пользования, скажем, библиотека математических функций. Службы используются в приложениях достаточно часто, поэтому есть даже стандартный стереотип (utility), определяющий класс как службу.

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

• Классификатор имеет фиксированное число экземпляров. Такой вариант не часто, но встречается. Например, порты в концентраторе.

• По умолчанию классификатор имеет произвольное число экземпляров.

Поскольку этот вариант встречается чаще всего, он никак специально не указывается.

В-шестых, классификаторы (и только они!) могут участвовать в отношении обобщения.

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

• словарь предметной области;

• реализация вариантов использования;

• образцы проектирования.

Опишем только первое, как наиболее простое для понимания решение.

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

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

• прием;

• перевод;

• увольнение;

• сотрудник;

• создание;

• ликвидация;

• подразделение;

• вакансия;

• сокращение;

• должность.

Заметим, что некоторые их этих слов по сути являются названиями действий (и по форме являются отглагольными существительными). Фактически, это глаголы, замаскированные особенностями родного языка. Это ясно видно, если переписать текст технического задания в форме простых утверждений. Отбросим замаскированные глаголы. Таким образом, остается список из четырех слов:

сотрудник,

подразделение;

вакансия;

должность.

При анализе технического задания мы отметили (опираясь на знание предметной области), что вакансия — это должность в особом состоянии. Таким образом, это слово в списке лишнее и у нас остались три кандидата, которые мы оставляем в словаре (и заодно присваиваем им английские идентификаторы).

• Сотрудник (Person);

• Подразделение (Department);

• Должность (Position).


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: