元海岸沿い現西新宿SIerのまつい師匠(@nmatsui)の「良いコードとは」というスライド、お読みになられたでしょうか。まだの方は是非!
http://www.slideshare.net/nbykmatsui/ss-55961899
さて、そのスライド中で出てくる「ロジックをシンプルに保つ」という話、以前まついさんと社内SNSでディスカッションしたことがある内容で、その結果をまとめておいたのが、以下になります。
http://www.slideshare.net/kawasima/ss-26968240
デシジョンテーブルを簡略化すると、プログラムの複雑度を減らすことができ、なにより仕様が単なる記号でなくて、顧客の要求が浮き出てきて理解しやすくなるよ、というものです。
ただ、この中では非常に単純な例しか挙げていないので、もう少し実践的な仕様で、ご説明したいと思います。
出力が多値のデシジョンテーブル
「第5回 仕様整理に「デシジョンテーブル」を使ってみよう」の記事より、問題を拝借します。
とある、健康ランドの精算システムの仕様は以下のとおりとする。
- クーポン持参:10%OFF
- 平日割引:30%OFF
- 平日シニア割引(65歳以上):50%OFF
- 2つ以上の割引サービスが重なった場合は,割引率が高い方が優先される
デシジョンテーブルを書くと以下のようになります。
これは、最初の仕様だけ書いてあれば、みなさんというか、大半のプログラマは以下のようにコード書くと思います。
int discountRate = 0;
if (hasCoupon()) {
discountRate = 10;
}
if (isWeekday()) {
if (isElderly()) {
discountRate = 50;
} else {
discountRate = 30;
}
}
ですが、設計書に上記のようなデシジョンテーブル(だけ)が書いてあると、そのとおりIF文が8個書かれることが往々にしてあります。設計者とプログラマが別々の人で、上記のようなデシジョンテーブルしかない場合は、まずそのまま実装することでしょう。
さて、これを簡略化するのもカルノー図を書けばよいです。
3つ以上の値をとる場合も、同じ値で隣接マスをグルーピングします。
これより、以下の仕様を導くことができます。
- クーポンを持っておらず、休日である → 割引なし
- クーポンを持っていて、休日である → 10%OFF
- 平日で65歳未満である → 30%OFF
- 平日で65歳以上である → 50%OFF
もとの要求事項から、「2つ以上の割引サービスが重なった場合は,割引率が高い方が優先される」のルールを展開して書いた仕様で明確です。これならIF文3つで済みます。
N/Aの扱い
記事の中で、
- 土日祝ジュニア割引(15歳以下):20%OFF
の割引ルールが仕様追加された例もとりあげておられます。
またデシジョンテーブルを書きます。
今度は、条件Cと条件Dを同時に満たすユーザはありえないので、ここがN/A(Not applicable)になります。
そしてカルノー図ですが、N/Aの部分(図中"-"で表している部分)は、ワイルドカード的に扱います。隣接領域が大きいほど、簡略化できるということになるので、N/Aを活かしてできるだけ領域を大きくします。
さて、これで仕様を言語化すると…
- クーポンを持っておらず、休日である → 割引なし
- クーポンを持っていて、休日で、16歳以上である → 10%OFF
- 休日で、15歳以下である → 20%OFF
- 平日で65歳未満である → 30%OFF
- 平日で65歳以上である → 50%OFF
となります。IF文4個で済み、各条件式もシンプルなものになります。
というように、N/Aは仕様を簡略化するチャンスなので、積極的に見つけ出すようにしましょう。
まとめ
デシジョンテーブルを作ったら、簡略化までして設計書に書いておくのが、要件定義におけるシステムエンジニアのマナーです。どうぞよろしくお願いします