要求分析駆動設計
DDDと要求分析駆動設計
DDDの問題あるいは難しいと言われる原因の一つは、パターンはわかっても目の前のドメインにパターンを適用する方法が明確でないということだと思っている。もっぱら使われるモデリング手法はクラス図だけであり、EntityとせいぜいValueObjectの候補を明らかにするだけで、Application ServiceやSpecificationは元となるモデルが存在しない。
要求のプラクティスとしてモデリング手法は数多くあり、要求分析駆動設計はそれらのプラクティスによってDDDを拡張することを目指している。
DDDのパターンと要求分析駆動設計の対比についてまとめると以下のようになる。
DDD | 要求分析駆動設計のクラス | 要求プラクティス |
---|---|---|
Application Service | UseCase | ユースケース、スイムレーン |
Entity | Entity | データモデリング |
Aggregate | Entity | データモデリング |
Module | Feature | フィーチャーツリー |
Specification | Rule(制約) | ビジネスルール分析 |
- | Rule(制約以外) | ビジネスルール分析 |
ValueObject | ValueObject | データディクショナリ |
- | State | 状態遷移図、状態遷移表、データディクショナリ |
ドメインイベント | Event | ビジネスルール(アクションイネーブラ)分析 |
ユビキタス言語は、用語集、ビジネスルール、データディクショナリ、データモデリングで出てくる名詞や動詞に対応する。わざわざ定義のぼやける用語を持ち込む必要性はないため、要求分析駆動設計ではユビキタス言語という言葉は使わない。 DDDの戦略的設計については、一旦、要求分析駆動設計のスコープ外としているが、スコープ定義の話題であり、コンテキスト図やエコシステムマップなどの要求プラクティスに対応すると考えている。
要求分析駆動設計とは
要求分析駆動設計とは、要求分析のプラクティスとDDDのコード上の表現においてもドメイン知識を利用するというアイディアを組み合わせたものである。私が独自に考えたものであり、他に情報源はない。しかし、オリジナリティといえるものは「要求分析のプラクティスとコード上の表現のリンク」だけであり、情報を求めるのなら「Code Complete」のような実務システムのコーディングスキルを高める本、「ソフトウェア要求」のような要求分析スキルを高める本、「エッセンシャルスクラム」のようなスクラム開発スキルを高める本など参考になる情報源は多い。逆に言えば、これらのスキルは要求分析駆動設計の基礎であり、これらのスキルが欠けた状態で実践することは難しい(まあ、任意の開発方法論において言えることであり、わざわざ明記する必要もないことだが)。
要求分析駆動設計のメリットを上げると以下のようなものがある。
- 要求分析の実施を強制する(ソフトウェア開発プロジェクトにおけるエラーや問題の原因の40%から50%近くが要求に関連するものだったという調査結果がある)
- 顧客が理解できる粒度で分析を行えば、それに対応づくコードも理解できる粒度となる
- 顧客とコミュニケーションする言葉を整理できれば、コードにでてくる名前も可読性の高い名前にできる
- ユースケースや状態遷移のような連続性のあるモデルに対応するコードが一箇所にまとまる
- 法律で毎年改正されるような処理をビジネスルールとして認識できれば、改正の影響を一箇所に集中させることができる
- 大半のクラスをイミュータブルにしてミュータブルなクラスを限定できる
などなど。
注意
この方法論は、半年ほどDDDと関連トピックについて調べ続けた結果として生じたアイディアであり、実践投入の実績はない。 マイクロサービスに関しては私の実務経験がないため、言及箇所は完全に的外れの可能性がある。
制限
要求分析を行いその結果を設計に反映させる方法論である以上、要求分析のためのコストがかかる。通常はかけたコスト以上の工数削減になる。 しかし、すべてのプロジェクトがそうなるとは限らない。 何年か前にSlideShareか何かで「ゲームの仕様変更が激しすぎて、書くコストがペイしないためテストコードを書かないという選択をした」というのを見かけた。 こういうテストコードすら置き去りにするほどに仕様が安定しないプロジェクトなら、要求分析にコストをかける価値はない。 ここまでではなくとも、実装済の機能が頻繁かつドラスティックに変更されるのなら、この方法論は適さないだろう(おそらくDDDも適さない)。
ただし、逆に要求に時間をかけていないためにその状況に陥っている可能性もある。
アジャイルプロジェクトでは要求をそれほど推敲しない、ということではなく、要求をあとで推敲する。要求を推敲しないという過ちを犯しているアジャイルプロジェクトもあるが、それはアジャイルというよりもコード&フィックス開発の特徴である。
More Effective Agile 第13章 より効果的なアジャイル:要求の作成 13.2 アジャイル要求では何が異なるのか
あるいは、適切にスクラムの実践ができていないか、ビジネスサイドへのソフトウェア開発に関する教育が不十分な可能性も考えられる。 適切な改善を行えば、この方法論が適用できる状態になるかもしれない。
本題に入るための補足
要求分析のプラクティスはカタカナ(ユースケースなど)、対応するコードは英語(UseCaseなど)で表記する。
本エントリはRuby on Railsのコードをサンプルとして上げているが、サーバサイドのウェブアプリケーションなら大部分は他の言語やフレームワークにおいてもそのまま適用できるか、いくらかの読み替えで適用できるだろう。もしかすると、DDDやCleanArchitectureに則ったフレームワークとは噛み合わせが悪いかもしれない。 また、ActiveRecord(PofEAA)パターンでないフレームワークの場合、Entityについては独自に実現方法を考え出さなければならないかもしれない。 要求分析という言葉から、アップフロントな方法という印象をもつかも知れないが、ウォーターフォール開発での実戦については言及せず、スクラム開発での実践方法について後述する。だが、アジャイル開発のイメージがXPのような初期のアジャイルのままなら、かなり頭の硬い印象をうけるだろう。
attr_accessor
はgetter
、setter
を定義するシンタックスシュガーで、サンプルコードでは多用している。
これは自己カプセル化のためにこうしている。
人によってはYAGNIでない、setter
がpublic
になっていると思うかも知れない。
YAGNIでないということに対しては、Rubyではインスタンス変数を直接参照するコードも自己カプセル化のコードも実装する手間がさして変わらないので、安全側に倒しても問題ないと考えている。シンタックスシュガーの存在しないJavaなどなら確かに煩雑なので、言語によってはインスタンス変数を直接参照した方が良いかも知れない。
setter
がpublic
になっていることを気にする向きは、以下のようにprivate
修飾子を付ければ良い。
private
attr_accessor :xxx
public
# 他のメソッドが続く。publicを書きたくないなら、attr_accessorをクラス末尾に移動させれば良い。
また、delegate
については、以下のように個別に宣言しないとprivate
にならないので注意が必要である。
delegate :method1, :method2, to: :raw
private :method1, :method2
もし、public
だからと言ってsetter
を外部から呼び出してしまうような人がプロジェクトにいるなら、その人にはこの方法論(ないしDDD)を理解できるだけの知識や考え方が備わっていないので、サポートをした方が良い。
なお、データディクショナリ(ValueObject)で後述するが、getter
を使ってobject.getter.method
のようにメソッドチェインしたい場合、object
にgetter.method
を呼び出すだけのメソッドを追加した方が安全である。
Rails用のジェネレータ
要求分析駆動設計のファイルの雛形を生成するRails用のRaddというジェネレータGemを作成したので、よかったら利用して欲しい。
目次
- ユースケース(ユーザーストーリー)、スイムレーン
- データモデリング
- ビジネスルール
- データディクショナリ
- 状態遷移図、状態遷移表
- Viewのためのクラス
- イベント
- ドキュメンテーション
- 要求分析駆動設計の流れ
- スクラムでの実践
- ミュータブル、イミュータブル
- 実践するために
ユースケース(ユーザーストーリー)、スイムレーン
DDDではApplicationService相当のもののため、具体的なドメインロジックは直接記述せずトランザクションの管理などを行う。Controllerからコードを独立させることにより、テストが容易になり、バッチ実行など画面から切り離した呼び出しが可能になる。
データモデリング
データモデリングの結果はDDDではEntityとAggregateに相当する。データモデリングといっても、物理データモデルではなく、論理データモデルのことである。
ビジネスルール
ビジネスルールはDDDではSpecificationに相当するが、カバー範囲はSpecificationよりも広い。
ビジネスルールはいくつかに分類することができる。ソフトウェア要求では単純な部類体系として以下の5つを上げている。
- ファクト
- 制約
- アクションイネーブラ
- 推論
- 計算
データディクショナリ
データディクショナリはDDDではValueObjectに相当する。
状態遷移図、状態遷移表
状態遷移図、状態遷移表から作成するStateクラスはDDDではValueObjectに分類されるだろう。 Stateの目的はラッパーValueObjectとしての役割とある状態から別の状態に遷移する関係を制御することにある。
Viewのためのクラス
ここまで一括りにView、Helperとしてきたが、ViewModelやPresenterなどViewで使うためのクラスも存在する。このレイヤのクラスについて簡単に言及しておきたい。
イベント
Entityの操作の中で条件が満たされ、メールを送信したかったり、他のサービスにメッセージを送りたい場合がある。
ドキュメンテーション
各々の要求分析プラクティスでドキュメンテーションについては言及してきた。 ここではドキュメンテーション全般に関することを話したい。
要求分析駆動設計の流れ
スクラムでの実践
スクラム開発に詳しい方はご存知の通り、プロダクトバックログのリファインメントによって要求を洗練させる。
ミュータブル、イミュータブル
実践するために
冒頭でも述べたが、要求のスキル、実務システムの開発スキル、アジャイル開発のスキルは最低限必要になる。ただ、チームとしてである。 全員が持っている必要はなく、チームとしてこれらのスキルを持っていると言える状態ならば良い。