
- •Оглавление
- •Теоретические сведения
- •Способы применения uml
- •Диаграммы uml
- •Диаграмма классов (Class diagram)
- •Свойства
- •Атрибуты
- •Кратность
- •Операции
- •Отношения
- •Зависимость
- •Ассоциация
- •Двунаправленные ассоциации
- •Агрегация и композиция
- •Обобщение
- •Реализация
- •Примечания и комментарии
- •Ключевые слова
- •Статические операции и атрибуты
- •Диаграмма последовательности (Sequence diagram)
- •Создание и удаление участников
- •Циклы, условия
- •Синхронные и асинхронные вызовы
- •Практическая часть Инструментарий
- •Начало работы
- •Создание первого проекта
- •Пример создания uml-диаграмм архитектуры проекта с помощью PlantUml
- •Создание диаграммы классов
- •Создание диаграммы последовательностей
- •Сценарий нахождения чего-либо в библиотеке по имени
- •Сценарий удаления чего-либо из библиотеки по идентификатору
- •Коррекция диаграммы классов
- •Задания для самостоятельной работы
Создание первого проекта
Для создания нового проекта нужно выбрать в стартовом меню “Create New Project”. Далее необходимо определить Java SDK для нового проекта. Необходимо нажать кнопку “New” и выбрать “JDK”, а также местоположение с ранее установленной JDK. При обычной установке JDK 8 в Windows - это путь C:\Program Files\Java\jdk1.8.0_31. Нажать Next.
Далее после нажатия можно выбрать “Create project from template”. Отметьте галкой, что действительно необходимо создать проект по шаблону. В нем будет лишь заготовка для одного класса.
Далее необходимо ввести все параметры будущего проекта. Название проекта - PromProgLabs. Расположение проекта - там, где будут храниться все файлы проекта. Base package (базовый пакет) - это название группы классов (пакета), которые будут реализованы в текущем проекте. Это название должно быть вашим инвертированным доменным именем, а также через точку дополнительно, возможно, название проекта и подпроекта. К примеру, для компании с доменным именем kozel.ru и проекта kozlomir базовый пакет будет таким: ru.kozel.kozlomir. Для своего проекта укажите домен miet.ru, группу, предмет и свое имя и фамилию.
После создания проекта и его сканирования (это может занять до полминуты) будет показано основное окно IntelliJ IDEA. На скриншоте показаны основные части среды разработки.
Рекомендуется включить расширенный вид тулбара через меню View>Toolbar. При включении тулбар приобретет следующий вид (на скриншоте он вместе с меню).
В редакторе кода вместо комментария “write your code here” наберите код, отвечающий за вывод классического “Hello world!”.
System.out.println("Hello world!");
Запустим программу нажатием кнопки Run. На скриншоте видно, что запуск успешен, программа работает корректно.
Пример создания uml-диаграмм архитектуры проекта с помощью PlantUml
Задание: разработать эскиз проекта системы управления книгами в библиотеке.
При выполнении задания ограничимся диаграммами классов и последовательности.
Создадим новый проект. В меню необходимо выбрать File>New Project. В диалоге выбора шаблона проекта, не нужно выбирать никакого шаблона (т.е. проект будет пустой, но с одним одноименным модулем). Название проекта - UMLLab. Если появится запрос на замену текущего проекта создаваемым, то лучше разрешить замену, так как старый проект уже не нужен.
После открытия проекта разверните содержимое модуля UMLLab с помощью серого треугольника. Папка .idea и файл UMLLab.iml хранят в себе все настройки проекта и модуля. Папка src будет включать в себя исходные коды .java программы.
Создание диаграммы классов
Откройте контекстное меню модуля и выберите создание новой UML-диаграммы классов.
В качестве имени файла можно ввести LibraryClassDiagram. В итоге среда разработки примет следующий вид.
В центре показан “код” диаграммы, которая загружается в качестве примера каждый раз при создании новой диаграммы классов. Слева показана уже нарисованная диаграмма. При редактировании кода диаграмма сразу же изменяется.
Код диаграммы начинается строчкой @startumlи заканчивается@enduml. Между ними описываются сущности (классы, интерфейсы, перечисления и т. д.), а также связи между сущностями. Как именно это делать, будет пояснено ниже, нополную информацию можно посмотреть в файле PlantUML_Language_Reference_Guideили по адресуhttp://plantuml.sourceforge.net/classes.html.
Удалим все, что находится между конечной и начальной строкой и приступим к проектированию системы управления книгами в библиотеке.
Так как составляется диаграмма классов, то главными сущностями будут именно классы, и диаграмма будет описывать большей частьюструктурусистемы. В будущей системе будут классы Book и Library. Создадим их.
@startuml
class Book {
}
class Library {
}
@enduml
Видно, что ни атрибутов, ни операций у этих двух классов пока нет. Добавим их исходя из необходимой функциональности.
У класса Book должны быть атрибуты: международный стандартный книжный номер (ISBN), название, автор, номер книги в библиотеке, год издания, а также операции, устанавливающие и получающие данные атрибуты. Однако по причине их многочисленности и общеупотребительности, эти операции не будут включаться в диаграмму классов. Помимо них, у класса Book нет других операций.
В классе Library должны быть атрибуты: количество книг и название библиотеки. Операции: найти нужную книгу по какому-либо параметру, например, по ISBN, добавить новую книгу в библиотеку, удалить необходимую книгу.
@startuml
skinparam classAttributeIconSize 0
class Book {
-ISBN : String
-author : String [1..*]
-numberInLibrary : long
-year : int
}
class Library {
-numberOfBooks : long
-name : String
+findBookByISBN(ISBN : String) : Book
+addNewBook(book : Book) : boolean
+deleteBook(number : long) : boolean
}
@enduml
Строка “skinparam classAttributeIconSize 0” отключает изображение метки видимости в виде картинки. Это нужно потому, что символы меток видимости стандартизированы, а картинки - нет, поэтому лучше использовать символы, если нет соглашений об иных обозначениях меток видимости.
Можно задать вопрос, а где же указано то, что в библиотеке хранятся книги? Пока на диаграмме изображены два разрозненных класса. Добавим эту информацию. Это можно сделать двумя путями, добавить некий атрибут в класс Library, который будет представлять собой список книг, хранящихся в библиотеке, а можно эту же самую информацию представить в виде ассоциации, но не однонаправленной, а двунаправленной.
Представление такой информации в виде ассоциации нагляднее, поэтому лучше выбрать именно ассоциацию. Почему ассоциация двусторонняя? Потому что не только библиотеке нужно хранить в себе информацию о всех книгах, входящих в неё, но и книга должна знать, какой библиотеке она принадлежит. Добавим информацию об этой ассоциации, дописав следующую строчку.
Book "0..*" <--> "1" Library
На диаграмме сразу отобразились все изменения, классы были перекомпонованы. Данная ассоциация может быть прочитана как “в библиотеке может быть от нуля до бесконечности книг, а у книги может быть только одна библиотека (в которой она находится)”.
Продолжим конкретизировать эскиз. В библиотеке могут находиться также не только обычные книги, но и, к примеру, журналы. Самым очевидным решением было бы сделать класс Magazine подклассом класса Book. Но у журналов нет ISBN и конкретного автора! К тому же для большинства журналов для обозначения даты издания только года недостаточно. Соответственно, архитектурным решением может быть сделать общий абстрактный класс AbstractBook, в котором будут реализованы общие операции для всех сущностей, что находятся в библиотеке. От него будут наследоваться классы Book и Magazine. Но нельзя создать никаких экземпляров класса AbstractBook, а нам необходимо именно ими управлять в классе Library. Это решение не подходит, либо должно быть усовершенствовано.
Далее, для того, чтобы сделать возможным управление классами-наследниками AbstractBook, можно вынести методы из AbstractBook в интерфейс LibraryEntity. Абстрактный класс будет реализовывать этот интерфейс. Таким образом, Library сможет управлять объектами типа LibraryEntity. Например, станет возможным такой код.
LibraryEntity entity = new Book();
Почему такое возможно? Потому что абстрактный класс AbstractBook реализует интерфейс LibraryEntity, а класс Book наследует абстрактный класс AbstractBook. Язык Java позволяет присваивать интерфейсу ссылки на объекты тех классов, которые реализуют этот интерфейс.
Это решение и является подходящим для такой ситуации.
Соответственно, будут изменения и в классе Library, изменятся названия атрибутов, добавятся новые операции и изменятся старые. Дополнительно изменено имя свойства “numberInLibrary” на “ID”.
Если бы не было этапа проектирования, который сейчас и выполняется, то именно сейчас пришлось бы переписывать огромное количество кода. Именно поэтому принцип “сначала спроектируй - потом пиши код” позволяет повысить эффективность. Сейчас изменить архитектуру, даже полностью её переписать, будет намного легче, чем переписать весь код, который её в будущем будет реализовывать.
Внесем все эти изменения в UML-код.
@startuml
skinparam classAttributeIconSize 0
interface LibraryEntity {
+getID() : long
+getName() : String
}
abstract class AbstractBook {
-ID : long
-name : String
}
class Book {
-ISBN : String
-author : String [1..*]
-year : int
}
class Magazine {
-datePublication: LocalDate
-publisher : String
}
class Library {
-numberOfEntities : long
-name : String
+findEntityByName(name : String) : LibraryEntity
+findEntityByID(id : long) : LibraryEntity
+addNewEntity(entity : LibraryEntity) : boolean
+deleteEntity(id : long) : boolean
}
LibraryEntity "0..*" <--> "1" Library
LibraryEntity <|.. AbstractBook
AbstractBook <|-- Book
AbstractBook <|-- Magazine
@enduml
Добавим комментарий к классу Magazine.
class Magazine {
-datePublication: LocalDate
-publisher : String
}
note right: LocalDate is from DateTime API in Java 8
Эта диаграмма классов только поверхностно охватила систему управления книгами, но этого вполне достаточно в качестве примера, как следует начинатьразрабатывать архитектуру приложений. Безусловно, в этом примере можно сделать еще много уточнений и усовершенствований, прежде чем на основе полученной архитектуры можно будет сделать рабочий проект.