[ЗАНЯТИЕ 1.04] Практика построения моделей предметной области
Привет!
Этот пост дополняет занятие "Введение в моделирование". При проверке домашних работ и общении с учащимися выяснилось, что практически все сталкиваются с очень похожими трудностями при попытке построить модель предметной области и нарисовать диаграмму классов. В этом и следующем постах я покажу вам ряд приемов, которые могут помочь быстрее и легче разобраться с моделированием.
Еще раз отмечу, что моделирование - это навык, который развивается только в процессе практики. Вы можете сколько угодно читать о том, как надо плавать, но пока вы не зайдете в воду, толку с этого не будет. С каждой решенной задачей строить модели будет немного проще, и со временем это должно стать для вас почти так же естественно, как и выражать свои мысли на родном языке.
Как выделять сущности?
Когда вы начинаете изучение предметной области, можно сначала описать ее простым текстом. Если вы столкнулись с новыми для себя понятиями, дайте им определения. Постарайтесь максимально доступно, но в то же время полно описать процессы, происходящие в сфере деятельности вашего заказчика.
Вот пример того, как может выглядеть начало описания предметной области для задачи про фермера из предыдущей домашней работы:
Написав такой текст, мы просматриваем его и выбираем существительные, которые обозначают объекты, имеющие одну или несколько характеристик. В нашем примере все крутится вокруг паев, их владельцев и договоров аренды - они выделены в тексте зеленым. Это и есть наши сущности, для каждой из которых понадобится отдельный класс в модели предметной области. Теперь пройдемся еще раз по описанию и подчеркнем свойства каждой сущности. Если записать все в виде структурированного текста, получается примерно следующее:
Земельный_пай
площадь: га
удаленность: км
плодородие: коэффициент, от 0 до 1
Договор_аренды_фикс
цена: руб/га*год
Договор_аренды_процент
процент
Владелец_пая
фио
номер_паспорта
серия_паспорта
номер_счета
Для договоров получилось 2 разных класса. У договора с фиксированной оплатой есть свойство цена
, которое бессмысленно для договора с оплатой под процент. Точно так же свойство процент
не нужно для договоров с фиксированной оплатой. Следовательно, мы имеем дело с очень похожими, но все же различными сущностями и для того, чтобы не путать их друг с другом, вводим два различных класса.
Теперь давайте разберемся со связями.
Фермер использует земельный пай на основании договора, следовательно, между паем и договором есть связь, которая называется ассоциация. Для каждого пая в каждый конкретный момент существует один и только один договор, поэтому кратность ассоциации пай -> договор
равна 1
. Остается открытым вопрос, может ли один договор давать фермеру право на обработку нескольких паев, так как из нашего описания это неясно. В реальной жизни придется уточнить этот момент у заказчика, а пока просто предположим, что на аренду каждого пая заключается отдельный договор, то есть кратность ассоциации договор -> пай
тоже равна единице.
Вы заметили, что, рассуждая о связи между договорами и паями, я не упоминаю, о каком конкретно типе договора идет речь, хотя у нас в модели их два? В данном случае важен сам факт наличия договора, но не важны его условия - процент или фиксированная оплата. Ассоциировать класс Земельный_пай
с каждым из классов, отвечающих у нас в модели за договоры, можно, но это неудобно - придется ввести в модель 2 связи вместо одной. Плюс будет необходимо правило, что для каждого пая должен быть только один договор, но не два сразу. Выглядит это вот так:
рисунок 1.04.1
Не сказать, что слишком красиво, есть решение получше. Давайте добавим новую сущность - класс Договор_аренды
. Этот новый класс станет родительским для Договор_аренды_фикс
Договор_аренды_процент
, и с ним будет связан ассоциацией класс Земельный_пай
. Оба дочерних класса унаследуют эту ассоциацию, так как она, в сущности, просто добавляет новое свойство предмет_договора
к нашему классу Договор_аренды
. Вот так это выглядит:
рисунок 1.04.2
Договор аренды заключается с конкретным физлицом, которое является владельцем пая - это еще одна ассоциация. Она также общая для классов Договор_аренды_фикс
и Договор_аренды_процент
, поэтому мы можем отнести ее к их общему предку, классу Договор_аренды
. Кратность этой ассоциации будет равна 1 для арендодателя (договор подписывается с одним и только одним лицом) и от 1 до бесконечности для договора (у одного арендодателя может быть несколько паев, которые он сдает в аренду по договорам разных типов).
Теперь возьмем листок бумаги и карандаш и перенесем все вышеописанное на диаграмму:
рисунок 1.04.3
Немного о свойствах
В процессе анализа описания предметной области у вас может возникнуть вопрос: почему мы выделяем одни существительные (пай, договор, владелец) как сущности, а другие как их свойства (площадь, фио, номер). В целом все достаточно просто. Если что-то обладает несколькими свойствами, то это сущность, которая на диаграмме классов будет представлена как класс. Если мы имеем дело с числом, строкой, датой, логическим значением (да/нет) и т.д., то это - свойство.
Если видите, что в свойствах сущности у вас оказалось нечто, что само по себе является объектом, имеющим несколько свойств, то это повод пересмотреть модель и добавить в нее еще одну сущность.
Встречаются также ситуации, когда можно выбрать, как представить ту или иную информацию. Например, у Владельца_пая
есть номер и серия паспорта. Вы можете использовать два свойства, как это сделано в примере выше, или выделить новую сущность Паспорт
, перенести эти свойства в нее и добавить ассоциацию Владельца_пая - Паспорт
с кратностью 1. Второе решение может показаться избыточным для нашего примера, но если у вас появится еще одна сущность, для которой нужны будут паспортные данные, то вы просто добавите еще одну связь, например, 'Наемный_работник - Паспорт', вместо того, чтобы дублировать одинаковые поля в разных местах.
Следует отметить, что в ситуации выше можно избежать дублирования полей еще одним способом. Как это сделать, подумайте сами в качестве маленького упражнения :)
Что пока лучше оставить за бортом?
Рассмотрим еще один пример. Предположим, вы решили создать свой клиент для блокчейна Голос. Описание задачи может начинаться так:
Из этого текста мы можем сразу выделить сущности Пользователь
и Пост
. А вот нужны ли нам сущности Сайт
и Страница
? Ответ на этот вопрос звучит так: "Они нам понадобятся, но не сейчас." На данном этапе мы занимаемся изучением предметной области и нас не должны волновать вещи, относящиеся к реализации программы.
Загвоздка тут в том, что в процессе проектирования из модели предметной области может получиться несколько весьма разных моделей.
В процессе разработки структуры таблиц базы данных (схемы БД) мы построим диаграмму, которая называется "сущность-связь", она очень похожа на нашу диаграмму классов, но не является ее точной копией, так как реляционные базы данных имеют свои особенности, в частности, они не поддерживают наследование.
Затем мы, как правило, используем модель предметной области повторно - для проектирования части программы, работающей с данными, которая будет написана на языке высокого уровня, например, Python или JavaScript. У нас получится диаграмма классов, но уже с учетом реализации на конкретном языке, на ней можно будет записать все имена согласно требований языка, указать видимость свойств и их типы, обозначить важные операции, добавить связи, которые показывают зависимости между классами, и т.д. При проектировании на диаграммы также добавится много новых классов, вот тут нам и пригодятся сущности Сайт
и Страница
.
В простейшем случае у нас будет 3 разных модели - одна, полученная в процессе анализа предметной области, и две производные от нее. А теперь представим, что наше приложение должно работать одновременно в браузере и на нескольких мобильных платформах, например, на iOS и Android. В этом случае нам потребуется спроектировать базу данных (БД), затем реализовать отдельный сервис, который обеспечит доступ к БД трем разными приложениям для веб, iOS и Android. Для сервиса и для самих приложений нам потребуются 4 немного разных модели предметной области... А если приложения имеют различный функционал, например, мобильные приложения, как это часто бывает, являются урезанными версиями основного приложения, то для их реализации могут потребоваться уже не слегка, а весьма различные модели. Но в любом случае все модели получатся производными от модели предметной области, с которой и начиналась вся наша разработка.
Моделирование предметной области без привязки к реализации также может помочь найти нестандартное решение поставленной задачи. Иногда возникает такая ситуация, когда лучшим выходом для заказчика будет не создание приложения, а нечто иное, например, небольшое изменение бизнес-процесса. Или его потребности лучше удовлетворит приложение совершенно другого типа, чем казалось изначально, например, не нужна полноценная программа для Windows, а простой скрипт, который преобразует какие-то данные и загружает их в уже существующее приложение.
Если вы заранее сосредоточитесь на реализации, особенно в каком-то конкретном виде, вы можете очень легко упустить такие возможности, ведь, когда в руках молоток, все кругом кажется гвоздями.
Для того чтобы понять, как именно выглядит рассматриваемая предметная область без привязки к реализации можно использовать такой прием. Представьте, что компьютеров не существует. Вместо машины вы даете инструкции сотруднику, который должен проделать всю работу вручную. Теперь подумайте, какая информация важна для решения задачи и как она должна быть структурирована. Ваши сущности могут выглядеть как записи в журнале, карточки в картотеке или заполненные анкеты... Пост из предыдущего превратится в запись в бумажном дневнике. Список постов будет в этом же дневнике на отдельной страничке, как содержание в книге.
Про программы
Под конец еще одно небольшое замечание. Неожиданно для себя обнаружил, что многие используют для рисования диаграмм графические редакторы или специализированные программы для работы с UML, такие как StarUML. Если вам так нравится, вы, разумеется, можете это делать, в желании получить красиво нарисованную диаграмму нет абсолютно ничего плохого. Правда, стоит отметить, что в реальной жизни использование программ - это не всегда лучший вариант.
Тщательно отрисовывать диаграммы имеет смысл если они нужны, например, для документации. А вот для того чтобы понять задачу, все же лучше использовать блокнот и карандаш или доску с маркерами. Они намного более универсальны, чем любые программы, не загоняют вас в какие-либо рамки и почти всегда под рукой. Хорошей практикой является держать на столе "рабочую тетрадь", которая как раз и используется для заметок и рисования всяких схем и диаграмм. На моем последнем месте работы в Qualcomm Inc, несмотря на то что нам было доступно в буквальном смысле любое ПО, которое могло бы потребоваться для работы, тетради, блокноты и прочие канцтовары выдавали практически в принудительном порядке и я не помню там ни одного инженера, который бы так или иначе не использовал в работе ручку и бумагу.
Практика (домашнее задание)
Если вы еще не закончили домашнюю работу к предыдущему занятию, то, надеюсь, что этот текст поможет вам это сделать. Если что-то непонятно, пишите в комментариях или заходите в наш Сад в Телеграм. Не стесняйтесь задавать вопросы, даже если они кажутся вам глупыми.
Как уже упоминалось в начале поста, освоить моделирование вам может помочь исключительно практика. Поэтому рекомендую разобрать как минимум 2-3 различных задачи. Решения оставляйте под постом с прошлой домашкой - я обязательно проверю их все и напишу вам замечания и рекомендации.
Желаю успеха,
@wealthycat
Успех проекта @studychain зависит от вас -
каждый голос и репост важен!
Спасибо!
❤