PlantUMLを試してみる

はじめに

MacでUML図(特にクラス図)を書きたかったのですが、Omniは高いですしうんうんうなりながら、いつも手書きの設計や頭の中でぼんやり考えるだけだったのですが、いい加減限界に来ていたので、何か良さげなツールは無いかしら?と探してPlantUMLと出会ったので、今回はその記事です。

PlantUMLって?

UML図をコードで書き起こしていくツールです。

例えば、以下のように記載すると

@startuml
class Character {
    +Name
    +Hp
    +Mp
    +Move()
    +Run()
    +Escape()
}

class Player {
    +Money
}

Player --u|> Character

class Enemy {
    +Group
}

Enemy --u|> Character

@enduml

f:id:project-unknown:20170903145430p:plain

こんな感じで書き起こしてくれます。
設計ツールはVisio等のGUIベースのものに慣れていたので、最初「うっ!?」と思ったのですが、やってみるとかなり直感的に掛けるので凄い便利ですよ。

PlantUMLのinstall

brewからinstall出来ます

$ brew install graphviz
$ brew install plantuml

brewをSierraで初めて使うときなど、以下の記事に記載したエラーに出会うかもしれませんので、brewがうまく動かない場合は、以下を参照ください。

www.project-unknown.jp

PlantUMLを使ってみる

有名所だとAtomとかになるのでしょうけど、最近家での開発はもっぱらUnityで、Unityのエディタを最近VSCodeに変えたばかりですので、VSCodeに突っ込みます。

VSCodeで以下のpackageをinstallします。

f:id:project-unknown:20170903134359p:plain

installが終わったら一度VSCodeを再起動してください。

後は新規にファイルを作成して、冒頭で記載したコードを打ち込み、「option+D」を押すとプレビューが表示されます。

f:id:project-unknown:20170903134543p:plain

Atomでもそうですが、ファイルは別に保存する必要が無いので、さっと思考を整理する時にとりあえず書いてみて消すって事が出来るのが非常に便利です。

クラス図の主な記法

qiita.com
ここがメチャクチャ詳しく載っていますので、詳細はここを御覧ください。

クラス図の書き方を軽くピックアップすると

まず、UMLを書く際は、以下を最初と最後に記載します。

@startuml
@enduml

次にClassはいつものクラス宣言とほぼ同じです。

class GameManager {
}

これを書くだけで
f:id:project-unknown:20170903134938p:plain
こんな感じで描画してくれます。

またPublicなフィールドを書く場合は

class GameManager {
    + IsGameOver
}

と書くと

f:id:project-unknown:20170903135106p:plain

こうなります。

Privateだと

class GameManager {
   - IsGameOver
}

f:id:project-unknown:20170903135146p:plain

こんな感じ。

またメソッドは、フィールドの書き方に加えて最後に「()」を付けるだけです。

class GameManager {
    -IsGameOver

    +GameStart()
    -GameEnd()
}

f:id:project-unknown:20170903135242p:plain

次に継承等の関係図を書く場合ですが、

まずクラスを書きます

class Character {
}
class Player {
}

f:id:project-unknown:20170903145540p:plain

その下に

Player -|> Character

と、「-|>」を書くことで継承関係を表現出来ます。

f:id:project-unknown:20170903145604p:plain

ただ、ちょっと図のクラス間が近くでごちゃごちゃしてるなーとなったら「-」の数を増やすことで距離を稼げます。

Player -------|> Character

f:id:project-unknown:20170903145630p:plain

(そうぞうより長かった(;・∀・))

また、基底クラスは上に来て欲しい等、クラス間の配置関係を弄る場合は、「left」「right」「up」「down」を記載します。
(上記はそれぞれ「l」「r」「u」「d」で省略できます)

Player ------u-|> Character

f:id:project-unknown:20170903145709p:plain

namespaceの表現

クラス図の延長でnamespaceも表現できます。
書き方はクラスを「namespace」で囲うだけです。

namespace Chara {
    class Character {

    }
    class Player {

    }
    class Enemy {

    }
    class Attack {

    }
    Player ---u-|> Character
    Player --> Attack
    Enemy ---u|> Character
    Enemy --> Attack
}

f:id:project-unknown:20170903145814p:plain

ぶっちゃけ、個人デベロッパだと細かいクラス相関図は不要だと思っていて、軽く継承や接続が見えてれば十分だと思うので、これだけあれば大分設計がしやすくなると思います。

クラス図その他の記法

線形

以下の表の注意事項

  • 線形の部分は「–r」と最後に「r」を入れてます。
    • 単純に表が縦に長くなるのを防ぐためです。
    • 記法では不要なので、必要な所以外は省略してます。
    • ものによっては、横並びだと見にくい線形は縦に表現します。
関係 線形 記法
汎化(継承) f:id:project-unknown:20170903150403p:plain <|--
Chara <|– Player
実現 f:id:project-unknown:20170903151712p:plain <|..
Chara <|.. Player
集約 f:id:project-unknown:20170903150824p:plain o--
Chara o– Player
コンポジション、合成 f:id:project-unknown:20170903150452p:plain *--
Chara *– Player
依存 f:id:project-unknown:20170903150703p:plain <..
Chara <.. Player
関係 f:id:project-unknown:20170903151218p:plain --
Chara – Player ()
誘導可能性 f:id:project-unknown:20170903152909p:plain -->
Chara –> Player
破線 f:id:project-unknown:20170903152114p:plain ..
Chara .. Player

関係の軽い説明

  • 汎化(継承)
    • 継承( is-a )の関係です
  • 実現
    • 基底クラスがインタフェースや抽象クラス等で、派生クラスがその振る舞いを実装する場合は、実現になります。
  • 集約
    • has - aの関係で、全体と部分の関係性を指します。
  • コンポジション、合成
    • 結合の強い集約。全体と部品
  • 依存
    • 変更すると紐付いているクラスにも変更が走るような関係
  • 関係
    • クラス間に何かしらの関係がある一番広義な関係です
  • 誘導可能性
    • 関係に矢印がつくことで誘導可能性を示し、矢印の方向にのみ関連があります。
  • 破線
線形のラベル、多重度

ラベル

線形 記法
f:id:project-unknown:20170903163449p:plain クラス 線種 クラス : ラベル
Chara –r> Player : メッセージ

多重度

線形 記法
f:id:project-unknown:20170903163603p:plain ```クラス “多重度” 線種 “多重度” クラス : ラベル
クラス描画のカスタマイズ

色を付ける

class "クラス名" RBG値
class Chara {

}
class "Chara" #FFFF00

以下が結果
f:id:project-unknown:20170903163905p:plain

列挙体
enum CharacterKind {
    Hero,
    Wiz,
    War
}

f:id:project-unknown:20170903165103p:plain

抽象クラス
abstract Observer {
    class Hoge
}

f:id:project-unknown:20170903165138p:plain

インターフェース
interface Fuga {
    {abstract} int FugaFuga(Fuga *other)
}

f:id:project-unknown:20170903165208p:plain

抽象クラス、インタフェースをそれっぽくつなぐと

f:id:project-unknown:20170903165402p:plain

こんな感じ

namespace

namespace ネームスペース名 {
}

namespace NameSpaceSample {
    class Controller {

    }   
}

f:id:project-unknown:20170903170945p:plain

また、Namespaceの外と線形を引きたい場合は、以下の書式で書きます。

ネーススペース名.クラス名 <-- クラス名

(見えにくいですが、「.」(ドット)で繋ぎます)

また、ネームスペースに所属していないクラス等の場合は、ネームスペースの部分を省略して以下の用に記載します

.クラス名

具体的な例は以下を見てください

namespace NameSpaceSample {
    class Controller {

    }
}

namespace NameSpaceSample2 {
    class Controller {

    }

    NameSpaceSample.Controller <-- Controller
    .Player <-- Controller
}

f:id:project-unknown:20170903171401p:plain

パッケージ

パッケージはどちらかと言うとJava依りの概念ですが、以下に示すデザインを使うことでクラス図に視認性を齎すことが出来ます。
(あくまでパッケージの概念を使っているので、やりすぎるとクラス図からずれてきます)

書き方は以下の通りです。

package {
}

package PackageSample {

    class Network {

    }
    class Listner {

    }

    Network <|- Listner

}

f:id:project-unknown:20170903170040p:plain

パッケージのスタイル

パッケージにステレオタイプで指定する事で形状を変えることが出来ます

スタイル 記法
f:id:project-unknown:20170903170215p:plain <<Node>>
package PackageSample <<Node>>
f:id:project-unknown:20170903170405p:plain <<Folder>>
package PackageSample <<Folder>>
f:id:project-unknown:20170903170454p:plain <<Frame
package PackageSample <<Frame>>
f:id:project-unknown:20170903170530p:plain <<Cloud>>
package PackageSample <<Cloud>>
f:id:project-unknown:20170903170617p:plain <<Database>>>
package PackageSample <>```

ノート、コメント

もちろんコメント機能も備わっています。
コメントは以下の記法に従います。

note ポジション of クラス名 : コメント

ポジションは以下から選択します。

  • left
  • right
  • top
  • bottom

以下は例です。

class Chara {
    Name

    +SetName(string name)
}
note top of Chara : キャラクターの基底クラス

f:id:project-unknown:20170903171656p:plain

改行を入れたい場合は、コメントの最中に「\n」を入れます。

@startuml
class Chara {
    Name

    +SetName(string name)
}
note top of Chara : キャラクターの\n基底クラス
@enduml

f:id:project-unknown:20170903171828p:plain

さいごに

書き方になれるまではうっっと思う時はあるかもしれませんが、実際にマウス操作が無くてクラス図を書いていけるのは非常に便利ですね。

需要があれば、PlantUMLはシーケンス等も書けるのでそちらも書いていきます。

参考

www.itsenka.com

Written by ゆう@あんのうん