[ЗАНЯТИЕ 1.04] Практика построения моделей предметной области


Привет!

Этот пост дополняет занятие "Введение в моделирование". При проверке домашних работ и общении с учащимися выяснилось, что практически все сталкиваются с очень похожими трудностями при попытке построить модель предметной области и нарисовать диаграмму классов. В этом и следующем постах я покажу вам ряд приемов, которые могут помочь быстрее и легче разобраться с моделированием.

Еще раз отмечу, что моделирование - это навык, который развивается только в процессе практики. Вы можете сколько угодно читать о том, как надо плавать, но пока вы не зайдете в воду, толку с этого не будет. С каждой решенной задачей строить модели будет немного проще, и со временем это должно стать для вас почти так же естественно, как и выражать свои мысли на родном языке.


black-programming.jpg

Как выделять сущности?

Когда вы начинаете изучение предметной области, можно сначала описать ее простым текстом. Если вы столкнулись с новыми для себя понятиями, дайте им определения. Постарайтесь максимально доступно, но в то же время полно описать процессы, происходящие в сфере деятельности вашего заказчика.

Вот пример того, как может выглядеть начало описания предметной области для задачи про фермера из предыдущей домашней работы:


domain_example1.png

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

Земельный_пай
площадь: га
удаленность: км
плодородие: коэффициент, от 0 до 1

Договор_аренды_фикс
цена: руб/га*год

Договор_аренды_процент
процент

Владелец_пая
фио
номер_паспорта
серия_паспорта
номер_счета

Для договоров получилось 2 разных класса. У договора с фиксированной оплатой есть свойство цена, которое бессмысленно для договора с оплатой под процент. Точно так же свойство процент не нужно для договоров с фиксированной оплатой. Следовательно, мы имеем дело с очень похожими, но все же различными сущностями и для того, чтобы не путать их друг с другом, вводим два различных класса.

Теперь давайте разберемся со связями.

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

Вы заметили, что, рассуждая о связи между договорами и паями, я не упоминаю, о каком конкретно типе договора идет речь, хотя у нас в модели их два? В данном случае важен сам факт наличия договора, но не важны его условия - процент или фиксированная оплата. Ассоциировать класс Земельный_пай с каждым из классов, отвечающих у нас в модели за договоры, можно, но это неудобно - придется ввести в модель 2 связи вместо одной. Плюс будет необходимо правило, что для каждого пая должен быть только один договор, но не два сразу. Выглядит это вот так:


1_04_1.jpg
рисунок 1.04.1

Не сказать, что слишком красиво, есть решение получше. Давайте добавим новую сущность - класс Договор_аренды. Этот новый класс станет родительским для Договор_аренды_фикс Договор_аренды_процент, и с ним будет связан ассоциацией класс Земельный_пай. Оба дочерних класса унаследуют эту ассоциацию, так как она, в сущности, просто добавляет новое свойство предмет_договора к нашему классу Договор_аренды. Вот так это выглядит:


1_04_2.jpg
рисунок 1.04.2

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

Теперь возьмем листок бумаги и карандаш и перенесем все вышеописанное на диаграмму:


1_04_3.jpg
рисунок 1.04.3

Немного о свойствах

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

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

Встречаются также ситуации, когда можно выбрать, как представить ту или иную информацию. Например, у Владельца_пая есть номер и серия паспорта. Вы можете использовать два свойства, как это сделано в примере выше, или выделить новую сущность Паспорт, перенести эти свойства в нее и добавить ассоциацию Владельца_пая - Паспорт с кратностью 1. Второе решение может показаться избыточным для нашего примера, но если у вас появится еще одна сущность, для которой нужны будут паспортные данные, то вы просто добавите еще одну связь, например, 'Наемный_работник - Паспорт', вместо того, чтобы дублировать одинаковые поля в разных местах.

Следует отметить, что в ситуации выше можно избежать дублирования полей еще одним способом. Как это сделать, подумайте сами в качестве маленького упражнения :)

Что пока лучше оставить за бортом?

Рассмотрим еще один пример. Предположим, вы решили создать свой клиент для блокчейна Голос. Описание задачи может начинаться так:


domain_example2.png

Из этого текста мы можем сразу выделить сущности Пользователь и Пост. А вот нужны ли нам сущности Сайт и Страница? Ответ на этот вопрос звучит так: "Они нам понадобятся, но не сейчас." На данном этапе мы занимаемся изучением предметной области и нас не должны волновать вещи, относящиеся к реализации программы.

Загвоздка тут в том, что в процессе проектирования из модели предметной области может получиться несколько весьма разных моделей.

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

Затем мы, как правило, используем модель предметной области повторно - для проектирования части программы, работающей с данными, которая будет написана на языке высокого уровня, например, Python или JavaScript. У нас получится диаграмма классов, но уже с учетом реализации на конкретном языке, на ней можно будет записать все имена согласно требований языка, указать видимость свойств и их типы, обозначить важные операции, добавить связи, которые показывают зависимости между классами, и т.д. При проектировании на диаграммы также добавится много новых классов, вот тут нам и пригодятся сущности Сайт и Страница.

В простейшем случае у нас будет 3 разных модели - одна, полученная в процессе анализа предметной области, и две производные от нее. А теперь представим, что наше приложение должно работать одновременно в браузере и на нескольких мобильных платформах, например, на iOS и Android. В этом случае нам потребуется спроектировать базу данных (БД), затем реализовать отдельный сервис, который обеспечит доступ к БД трем разными приложениям для веб, iOS и Android. Для сервиса и для самих приложений нам потребуются 4 немного разных модели предметной области... А если приложения имеют различный функционал, например, мобильные приложения, как это часто бывает, являются урезанными версиями основного приложения, то для их реализации могут потребоваться уже не слегка, а весьма различные модели. Но в любом случае все модели получатся производными от модели предметной области, с которой и начиналась вся наша разработка.

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

Если вы заранее сосредоточитесь на реализации, особенно в каком-то конкретном виде, вы можете очень легко упустить такие возможности, ведь, когда в руках молоток, все кругом кажется гвоздями.

Для того чтобы понять, как именно выглядит рассматриваемая предметная область без привязки к реализации можно использовать такой прием. Представьте, что компьютеров не существует. Вместо машины вы даете инструкции сотруднику, который должен проделать всю работу вручную. Теперь подумайте, какая информация важна для решения задачи и как она должна быть структурирована. Ваши сущности могут выглядеть как записи в журнале, карточки в картотеке или заполненные анкеты... Пост из предыдущего превратится в запись в бумажном дневнике. Список постов будет в этом же дневнике на отдельной страничке, как содержание в книге.

Про программы

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

Тщательно отрисовывать диаграммы имеет смысл если они нужны, например, для документации. А вот для того чтобы понять задачу, все же лучше использовать блокнот и карандаш или доску с маркерами. Они намного более универсальны, чем любые программы, не загоняют вас в какие-либо рамки и почти всегда под рукой. Хорошей практикой является держать на столе "рабочую тетрадь", которая как раз и используется для заметок и рисования всяких схем и диаграмм. На моем последнем месте работы в Qualcomm Inc, несмотря на то что нам было доступно в буквальном смысле любое ПО, которое могло бы потребоваться для работы, тетради, блокноты и прочие канцтовары выдавали практически в принудительном порядке и я не помню там ни одного инженера, который бы так или иначе не использовал в работе ручку и бумагу.

Практика (домашнее задание)

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

Как уже упоминалось в начале поста, освоить моделирование вам может помочь исключительно практика. Поэтому рекомендую разобрать как минимум 2-3 различных задачи. Решения оставляйте под постом с прошлой домашкой - я обязательно проверю их все и напишу вам замечания и рекомендации.


Желаю успеха,
@wealthycat


logo

Успех проекта @studychain зависит от вас -
каждый голос и репост важен!
Спасибо!


Comments 1