[ЗАНЯТИЕ 1.03] Введение в моделирование
На прошлом занятии мы в самых общих чертах разобрались с процессом разработки программ, а в домашнем задании впервые попробовали проанализировать предметную область и выделить из нее сущности, которые важны для решения конкретной задачи. То есть мы создали простую модель выбранной предметной области.
Выполняя задание, вы, возможно, уже задали себе вопрос - как правильно описывать модели? Вот этим мы и займемся сегодня и на следующем занятии, а именно разберемся с основными приемами моделирования, изучим терминологию и общепринятый способ записи полученных моделей.
Понятие класса
Начнем с того, что нам необходимо описывать объекты реального мира. Так как этих объектов может быть очень много, мы прежде всего разделим их на группы. В каждую группу соберем объекты, обладающие одними и теми же свойствами. Эти группы мы назовем классами.
Давайте рассмотрим следующий пример. Предположим нам надо решить задачу, связанную с учетом сотрудников предприятия. С точки зрения кадрового учета, для каждого сотрудника требуется хранить табельный номер, ФИО и дату рождения - это свойства любого сотрудника. На данном этапе у нас нет необходимости различать сотрудников между собой, и поэтому мы просто вводим в нашу модель класс сотрудник
и говорим, что этот класс обладает тремя свойствами - номер
, фио
и дата_рождения
. То есть мы заменили множество конкретных живых сотрудников единственной абстракцией, которая описывает только то, что нам нужно решения задачи.
Продолжая изучать кадровый учет, мы обнаружим, что каждый сотрудник работает в том или ином отделе или цеху предприятия. Для описания множества подразделений предприятия мы введем в модель еще один класс и так и назовем его подразделение, пусть у него пока будут всего два свойства: номер подразделения и название. Теперь у нас получилось 2 различных класса: сотрудник и подразделение.
рисунок 1.03.1
Видите что происходит? Мы берем некую часть реального мира - в данном случае это предприятие, на котором в принципе могут работать тысячи сотрудников в десятках различных отделов и цехов - в реальности это множество различных объектов. Мы собираем однотипные объекты в группы или, как обычно говорят, классы. Таким образом, вместо того чтобы думать о каждом сотруднике отдельно, мы можем иметь дело только с классом сотрудник и несколькими его свойствами, важными для решения задачи. По сути, в рамках предметной области мы пытаемся сделать примерно то же самое, что делают, например, биологи, когда делят живые организмы на виды, рода и семейства. В программировании мы также выстраиваем классификацию и переходим от изучения конкретных объектов к работе с абстракциями, которые и называем классы.
В процессе моделирования, когда мы говорим класс, мы подразумеваем не конкретный объект, а именно множество объектов, обладающих одинаковыми свойствами. Иногда это множество может состоять из одного экземпляра, а иногда включать миллионы и миллиарды однотипных объектов. Слово "экземпляр" здесь используется неслучайно. В тех случаях, когда нам нужно указать, что речь идет не о классе, а о конкретном объекте этого класса мы скажем, например, что объект Иванов И.И.
является экземпляром класса сотрудник
.
Понятие наследования
При моделировании может получиться так, что один и тот же объект будет принадлежать к нескольким различным классам. Предположим, что при анализе предметной области кадрового учета мы столкнулись с тем фактом, что не все сотрудники одинаковы. Например, нам необходимо учитывать, что у каждого начальника отдела есть заместитель, а у директора предприятия, кроме заместителя, есть еще и секретарь. В этом случае нам необходимо добавить два новых класса: начальник
, который имеет свойство заместитель
и директор
со свойством секретарь
. Теперь получается, что рядовой сотрудник принадлежит к классу сотрудник
, начальник отдела - к классам сотрудник
и начальник
, а директор относится аж к трем классам сразу - сотрудник
, начальник
и директор
.
В примере выше мы по сути имеем дело с множествами и подмножествами. Из всего множества сотрудников предприятия (класс сотрудник
) сначала выделяется подмножество начальников (класс начальник
), а затем из этого узкого круга выделяется подмножество директоров (класс директор
), состоящее в нашем случае всего из одного элемента. По сути, для описания данной предметной области мы создали простую иерархическую классификацию.
рисунок 1.03.2
Рассматривая данный пример, мы можем легко заметить, что все экземпляры класса начальник
одновременно являются и экземплярами класса сотрудник
, то есть не существует начальников, которые не являлись бы сотрудниками предприятия. Можно сказать, что между классами сотрудник
и начальник
существует связь - класс начальник
является как бы производным от класса сотрудник
. Такая связь между двумя классами называется наследование, по той причине, что класс начальник
наследует свойства номер
, фио
и дату рождения
от класса сотрудник
, а класс директор
наследует уже 4 свойства - номер
, фио
и дату рождения
и заместитель
от двух "родительских" классов.
Введение наследования помогает нам упростить нашу модель. С помощью него мы устанавливаем иерархию классов, например, говорим, что класс директор
является производным и наследует свойства класса начальник
, который, в свою очередь, является производным от класса сотрудник
. Теперь каждый работник предприятия принадлежит только к одному классу: кто-то является сотрудником
, кто-то начальником
, а один из них будет директором
, следовательно у нас уже нет необходимости относить один и тот же объект одновременно к нескольким различным классам.
Понятие ассоциации
Продолжим строить нашу модель. Предположим, что для ведения кадрового учета необходимо знать в каком подразделении работает каждый конкретный сотрудник. У нас уже есть классы сотрудник
и подразделение
, то есть нам остается только установить между ними связь, которая показывает, что экземпляр класса сотрудник
относится к конкретному подразделению. Для этого к классу сотрудник
мы добавляем новое свойство, которое назовем работает
. Теперь каждый экземпляр класса сотрудник
ассоциируется с конкретным экземпляром класса подразделение
. Связь между этими двумя классами так и называется - ассоциация.
Теперь представим, что нам нужно получить список сотрудников для каждого конкретного подразделения предприятия. Для этого мы добавляем свойство сотрудники
к классу подразделение
и таким образом создаем еще одну ассоциацию между этими двумя классами. То есть у нас теперь есть связь сотрудник -> подразделение
, с помощью которой можно узнать, в каком подразделении работает конкретный сотрудник, и обратная ей связь подразделение -> сотрудник
, предназначенная для получения списка сотрудников подразделения.
Две описанные выше ассоциации, кроме того, что имеют противоположенное направление, еще отличаются характеристикой, которая называется кратность. Если в рамках нашей модели сотрудник может работать только в одном подразделении, то кратность связи сотрудник -> подразделение
будет равна 1
- это означает, что мы всегда знаем в каком конкретном подразделении работает каждый сотрудник. А вот ассоциация подразделение -> сотрудник
будет иметь кратность 1 - ∞
, что читается "от одного до бесконечности" и означает, что в каждом подразделении работает хотя бы один сотрудник и не существует верхнего ограничения на их количество. По сути, кратность указывает сколько экземпляров другого класса может быть ассоциировано с рассматриваемым объектом.
При моделировании нам также может потребоваться установить связь между экземплярами одного и того же класса. Предположим, что нам необходимо знать, кому подчиняется каждый сотрудник предприятия. Для этого в класс сотрудник
мы добавляем новое свойство - руководитель
, которое указывает на объект этого же класса. Такую ассоциацию можно назвать циклической или рекурсивной и с ее помощью мы моделируем иерархию сотрудников предприятия (не путайте с иерархией классов, которая получается при наследовании). Кратность ассоциации сотрудник -> сотрудник
будет равна 0-1
, так как нам необходимо учесть тот факт, что у директора предприятия, он ведь тоже сотрудник, не будет начальника.
При необходимости мы можем добавить в модель еще одну связь, которая будет показывать, какие подчиненные существуют у данного сотрудника (она противоположена ассоциации, описанной в предыдущем абзаце). Это также будет ассоциация вида сотрудник -> сотрудник
, но ее кратность будет уже 0 - ∞
, так как у рядовых сотрудников не будет подчиненных, но при этом число людей, которыми может руководить начальник, ничем не ограничено.
Две описанные выше связи могут использоваться, например, для создания штатного расписания предприятия. С помощью них мы описываем иерархию или, как еще говорят, дерево объектов, которое не следует путать с иерархией классов, обсуждавшейся в предыдущем разделе. В иерархии объектов мы устанавливаем связи между конкретными экземплярами одного и того же класса, а в иерархии классов - между множествами. Не забываем, что, говоря "класс", мы подразумеваем именно множество объектов, обладающих одинаковыми свойствами.
Диаграммы
На данный момент в состав нашей модели входит 4 класса, 11 их свойств, и 8 различных связей между ними классами. Да-да, связей именно 8, а не 6, как может показаться - еще две ассоциации определяются свойствами заместитель
и секретарь
у классов Начальник
и Директор
. Видите, даже для такой простой модели уже становится достаточно непросто удержать в уме всю картину целиком. С увеличением числа сущностей (классов, объектов) и связей между ними станет все труднее описывать модель в виде текста.
Нам требуется другой подход для того, чтобы можно было комфортно работать со сложными моделями. Поэтому от работы с текстом, мы перейдем к рисованию диаграмм.
Для диаграмм мы будем использовать стандартную нотацию (набор обозначений), которая является подмножеством языка UML - это расшифровывается как Unified Modeling Language (унифицированный язык моделирования). Язык UML широко используется в индустрии для моделирования предметной области и проектирования программ.
рисунок 1.03.3
На диаграммах класс отображается в виде прямоугольника, разделенного на три части двумя горизонтальными линиями. В верхней части записывается имя класса, в средней находится список свойств или как еще принято говорить атрибутов класса, а нижняя часть пока у нас будет оставаться пустой, в будущем мы будем записывать туда операции, которые применимы к экземплярам данного класса. Если у класса свойства и/или операции отсутствуют или они несущественны в контексте данной диаграммы, то соответствующие им секции можно не рисовать, как это показано на рисунке выше.
рисунок 1.03.4
Связи между классами отображаются в виде линий. Если речь идет о наследовании, то линия снабжается треугольной стрелкой, которая указывает на тот класс, свойства которого наследуются. Этот класс еще называется "родитель", а класс, который наследует свойства обычно именуется "потомок". Другими словами, стрелка, обозначающая наследование, направлена от класса-потомка к классу-родителю.
рисунок 1.03.5
Ассоциация между классами отображается непрерывной линией, под которой мы подписываем названия свойств классов, соответствующих этой ассоциации. Например, если у нас в модели есть ассоциация сотрудника с подразделением, то под линией ассоциации, рядом с классом Сотрудник
мы можем дописать работает
- это свойство, которое указывает в каком подразделении работает сотрудник.
На диаграмме также можно указать кратность ассоциации. Для ассоциации сотрудник -> подразделение
кратность 1
указывается над линией ассоциации, рядом с классом Подразделение
. Такая запись подчеркивает, что каждый сотрудник работает в одном подразделении.
рисунок 1.03.6
Если пара классов в нашей модели связана двумя ассоциациями (или, как еще говорят, двунаправленной ассоциацией), то они отображаются одной линией. Например, связь сотрудник -> подразделение
, показывает в каком подразделении работает сотрудник, а ассоциация подразделение -> сотрудник
нужна для получения списка всех сотрудников подразделения. В этом случае под линией ассоциации мы можем подписать названия соответствующих свойств (работает
, сотрудники
), а над линией - можем указать кратности (1
, 1-∞
).
рисунок 1.03.7
Циклическая ассоциация изображается в виде "уха", как показано на рисунке. Такое обозначение может с непривычки показаться довольно странным, и чтобы его правильно интерпретировать необходимо вспомнить, что когда говорится "класс", на самом деле подразумевается множество однотипных объектов. То есть ассоциация устанавливается между двумя различными объектами, относящимися к одному и тому же классу. В нашем случае это два экземпляра класса Сотрудник
- один из которых подчиненный, а другой его начальник.
Обратите внимание на кратность этой ассоциации:
0 - 1
означает, что у любого сотрудника, кроме директора, будет только один начальник.0 - ∞
- количество подчиненных сотрудника в рамках модели не ограничено и может равняться нулю для рядовых работников.
Структурное моделирование
рисунок 1.03.8
На диаграмме выше вы видите модель, над которой мы работали на протяжении этого занятия. Она состоит из нескольких классов и двух типов связей - наследования и ассоциации. Создавая диаграмму классов, мы фиксируем важные для решения задачи особенности структуры предметной области, но при этом многие интересные аспекты остаются за бортом. В частности, глядя на диаграмму классов, трудно понять, как, например, выглядит процесс приема на работу или увольнения сотрудника предприятия.
Получается, созданная нами модель не полная? Да, это так. На этом занятии мы разобрали только часть понятий, обычно используемых при моделировании, и научились строить только одну диаграмму. Для решения некоторых задач этого вполне достаточно, но в большинстве случаев необходимо использовать и другие инструменты для того, чтобы создать модель, пригодную для реализации. В частности, кроме структуры еще нужно будет научиться описывать процессы. Вот именно этим мы и займемся на следующем занятии.
Дополнительные материалы
Книга Гради Буч, Джеймс Рамбо, Ивар Якобсон "Язык UML. Руководство пользователя"
Если вы раньше никогда не сталкивались с Объектно Ориентированным Программированием (ООП), то вам желательно прочитать только главу 1 и бегло просмотреть главы 2 и 3. После того как мы в рамках курса разберемся с парадигмами языков программирования и познакомимся с ООП, очень рекомендую вернуться к этой книге и дочитать ее до конца.
Отношения классов — от UML к коду - классы и связи между ними с примерами на языке Java.
Домашнее задание
Итоги по выбору лучшей домашней работы будут подводиться в понедельник, 18 сентября, после 10 часов утра по МСК.
Начиная с этого занятия, мы решили дать вам больше времени, чтобы спокойно разобраться с материалом, выполнить задание, просмотреть домашки других студентов и выбрать работу, которая вам нравится больше всего.
Вопросы
Если в процессе чтения у вас возникли вопросы, задавайте их в комментариях к этому посту.
Желаю успеха,
@wealthycat
Успех проекта @studychain зависит от вас -
каждый голос и репост важен!
Спасибо!
❤