UMLの読み解き方とプログラムへの落とし込み方

# UMLとは
UMLとは、システムやソフトウェアの設計を視覚的に表現するための図式言語（モデリング言語）です。要するに、プログラムやシステムの構造・振る舞いを「図」でわかりやすく説明するツールです。要件定義や基本設計では、お客様や開発メンバー間でこれから構築するシステムの認識のすり合わせを行うために使い、詳細設計では、開発者に、どのようにプログラミングしていくのかを具体的に指示するために使います。
今回は、詳細設計工程の成果物としてのUMLの読解とプログラムへどのように落とし込むのかという、開発者寄りのテーマで説明していきたいと思います。

# クラス図
UMLの代表的な構造図の一つで、システムの中に存在するクラス単体の定義とクラス間の関係を表した図をクラス図といいます。そもそもクラスとは、構築するシステムの中で登場する現実世界の人や物をオブジェクトとし、そのオブジェクトの共通部分を洗い出したオブジェクトの設計書のようなものです。
それでは、クラス単体の定義とクラス間の関係について見ていきましょう。

### クラス単体の定義
![クラス図単体.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/0b8b87ab-8dc2-4ae8-8e4d-597d06da88bd.png)
クラスは主に３つの区画から構成されます。上から、クラス名、属性（そのクラスが所持している情報）、操作（メソッド）になります。上のクラス図を見ると、「本」の部分がクラス名、「タイトル」「著者名」の部分が属性、「タイトル名を表示」「著者名を表示」の部分が操作に該当します。クラスはこのように、システムの中で扱う現実世界の物（オブジェクト）が所有する情報と操作をひとまとめに記述しているのが特徴です。
また、大体のクラスは、「-」記号で属性に直接アクセスできないようにすることが多く、アクセスしたいときは、操作を呼び出して属性の値を取得するように設計します。これを情報隠蔽と呼びます。

#### なぜ情報隠蔽するのか
属性に直接アクセス可能にすると、同じように属性の値を取得できるのですが、同時に属性の値の編集、書き換えも出来てしまいます。これにより利用者の誤った操作で、予期せぬデータ操作を行ってしまい、データが壊れてしまう可能性があります。よって、属性の値の参照は、操作を経由してあげることで、定義した操作以外の参照を無くし、安全性を担保します。

### クラス間の関係の定義
#### 関連
![クラス図 関連.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/ae8dbd06-4fee-4f0f-8ff2-a41bc0400c50.png)

こちらの関係は、関連といって、クラス同士に何かしらの関係があるときにこの状態になります。例えば社員クラスと部署クラスがあったとすると、社員はどこかしらの部署に所属しているということで、継続的なつながりがあると考えられます。属性区画には書いていませんが、この関係があることから、社員クラスは部署クラス型の属性を保持することになります。このようにクラス同士で継続的な関係を持っていれば、関連という関係になります。

#### 集約
![クラス図 集約.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/7d374b9c-4108-4dbe-a9cd-55b4cd491289.png)


こちらの関係は、集約といって、関連よりもワンランク強めの関係を表しています。クラス同士が包含関係にあるときにこの関係になります。例えば、図書館は本を所有しているので、図書館クラスは本クラスを集約していると考えることができます。属性区画には書いていませんが、この関係があることから、図書館クラスは、本クラスの集合型の属性を保持
することになります。

#### 多重度
数字や*（アスタリスク）は多重度といって、一方のクラスに対して、もう一方のクラスがいくつ存在できるかを表現したものです。図の例でいくと、一つの図書館には、複数(0以上)の本が存在することを表しています。

### クラスについて補足
補足として、汎化について紹介していきます。

#### 汎化
![クラス図 汎化.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/4b2f6260-16d1-4d41-9635-91354a4c2b03.png)

共通部分を表す抽象クラスと詳細部分を表す具象クラスとの関係のことです。図の例だと、社員クラスから、技術社員、営業社員、事務社員というように具体的なクラス名になって派生しているのがわかると思います。派生していったクラスたちは、社員クラスの特徴を引き継いで新しく作られるので、このクラスたちは、「社員クラスを継承している」と表現します。

# シーケンス図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/0894b321-abca-4c85-9afe-6c7013d4653c.png)

UMLの代表的な振る舞い図の一つで、結論からいうと、オブジェクト間の相互作用を時系列で表すダイアグラムです。
プログラムにおいて、どのタイミングで、オブジェクトが生成されるのか、どのタイミングでメソッドを呼び出すのかを時系列で表します。基本的な読み解き方としては、上から下に向かって時間が経過しているという風に読み解きます。シーケンス図を構成する要素は主に、オブジェクト名、ライフライン、実行指定、メッセージ、クラス名の５つから構成されます。

### オブジェクト名、クラス名
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/cfb320b2-1978-465d-a883-4fb548485b03.png)

システムに登場するクラスやオブジェクトを表します。四角形の中に名前だけ書いてあるのが、オブジェクト名で、四角形の中に名前の先頭に「:」がついているのがクラス名を表します。また、:の両方に名前が記述されている場合は、オブジェクト名:クラス名のように記述します。

### ライフライン、実行指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/da1fe84f-da12-4246-b75d-d8bec38e1a93.png)

下に向かって、点線が引かれているものがあると思います。これは、ライフラインといって、オブジェクトが生成されてから存在している期間を表しています。
ライフライン上に白抜きの四角形があると思います。これが、実行指定です。これは、他のオブジェクトからメソッド呼び出し等をされて動いているタイミングを表します。


### メッセージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/e9f767f0-84e1-4f5e-b709-df2dab0ca593.png)

横に伸びている点線や実線をメッセージと呼びます。とあるオブジェクトから別のオブジェクトにメソッド呼び出しをする場合は実線を、オブジェクトを生成する場合は点線を記述することになります。メソッド呼び出しの線の上にあるメソッドは、矢印が向いている側のオブジェクトが持っているメソッドで、そのメソッドを矢印元のオブジェクトが呼び出しているという関係になっています。


# プログラムへの落とし込み方
これまで紹介してきた、UMLからどのようにプログラムを記述していけばよいのかを紹介していきたいと思います。
今回は、Java言語を使用してコードを書きたいと思います。

### クラス単体の定義
![詳細クラス　単体２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/0b675591-fef1-4990-b79a-54f58365457b.png)


最初にクラス名区画を見ていきます。クラス名はBookなので、Bookとします。
<pre>
public class Book{
    
}
</pre>

続いて、属性区画では、「アクセス修飾子 変数名:データ型」のようなで記述されています。アクセス修飾子の「-」は、privateを表しているので、privateと記述します。次にデータ型です。データ型はStringとなっているので、Stringと記述します。最後に変数名を記述して属性区画は完成です。

<pre>
public class Book{
    //属性
    private String title;
    private String contents;
}
</pre>

最後に操作区画です。「アクセス修飾子 メソッド名(変数名:データ型...):戻り値のデータ型」のような形式で記述されています。アクセス修飾子の「+」はpublicを表しているので、publicと記述します。続いてメソッド名を記述するのですが、「Book」はクラス名と同じ名前なので、コンストラクタとして記述します。今回はコンストラクタに引数もあるので、データ型と変数名を図から読み取って記述します。残りのgetTitleとgetContentは普通のメソッドとして記述します。今回は、戻り値型も定義されているので、アクセス修飾子の次に戻り値のデータ型を記述します。
<pre>
public class Book{
    //属性
    private String title;
    private String contents;

    //操作
    public Book(String title, String contents){
        ・・・
    }
    
    public String getTitle(){
        ・・・
    }

    public String getContent(){
        ・・・
    }
}
</pre>

### クラス間の関係の定義（関連）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/a0e178ca-eb9c-496e-adf3-26992b3712a7.png)


利用する側のクラスの属性に利用される側のクラス型の変数を持たせます。その際、利用される側のクラスの矢印の上にあるものをロール名と呼ぶのですが、これは、利用する側のクラスに持たせる変数名を表しています。よってアクセス修飾子と合わせて属性に記述していきます。

<pre>
//部署クラス
public class Department{・・・}

//社員クラス
public class Employee{
    //属性
    private Department department;
}
</pre>

### クラス間の関係の定義（集約）
![詳細クラス2 集約.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/a2bee1cc-def5-42e2-b29e-08856b50d16b.png)

利用する側のクラスの属性に利用される側のクラスの集合型を持たせます。アクセス修飾子と変数名の書き方は先程の関連と同じですが、変数の型はArrayList<利用される側のクラス>型となります。
<pre>
//本クラス
public class Book{・・・}

//図書館クラス
public class Library{
    //属性
    private ArrayList&lt;Book&gt; bookList;
}
</pre>

### シーケンス図（オブジェクト生成）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/ada40d0c-5a79-42af-8d1f-3589e3deef5e.png)
シーケンス図では、newキーワードを使用しています。これは、矢印の先にあるクラスをインスタンス化することを表しています。引数も、シーケンス図に習って記述します。
<pre>
public class Library{
    Book book;
        ・・・
        book = new Book(title, contents);
}
</pre>

### シーケンス図（メソッド呼び出しと戻り値）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962435/d1fb6474-22cd-42cb-9f75-04b73bc95474.png)
左から右に向かっている矢印はメソッド呼び出し、右から左に向かっている矢印は戻り値を表しています。これをコードに起こすと、「lendBook(title)」は、Libraryクラスのlibraryオブジェクトが所有するメソッドなので、「library.lendBook(title)」という形でコードに起こすことになります。戻り値の部分を見ていくと「:Book」とあるので、戻り値のデータ型が「Book」となります。よって、Bookクラスのbookという変数に戻り値を格納するように記述します。

<pre>
public class User{
        ・・・
        Book book = library.lendBook(title);
}
</pre>

# まとめ
今回は、UMLを読み解いて、コードに起こす方法をご紹介しました。分析や設計にUMLを採用することによって、お客様にとっては、システムの全体像が分かりやすく表現され、開発者にとっては、コーディングの指針がわかりやすいとても便利なツールなので、ぜひ、読解の仕方を覚えみてはいかがでしょうか。