Fish の線引き

ユースケースの目的レベルのうち、Fish だけが行き先を一意に定められない。 要件の内訳になることもあれば、仕様に降りることもある。 この文書では、Fish をいつ立てるか、立てたものをどこに置くかの判断手順を扱う。

前提となる2つの軸の関係は「層と粒度は別の軸である」を参照。

なぜ Fish が現れるのか

Cockburn は Sea を基準とし、他のレベルは Sea から見た相対的な位置として定める。 また Fish については、重複を避けるために切り出すものであって、 網羅性のために分解するものではない、という趣旨のことを述べている。

では Sea だけで書き切れるかというと、書き切れない。

Sea は業務として完結しているが、手続きとして書き下すと内部にステップ列が現れる。 そのステップの一部は、複数の Sea に共通して現れる。 このとき取りうる選択は3つしかない。

選択結果
各 Sea に毎回書く重複する。1箇所直すと全部直すことになる
書かない記述が不完全になる
切り出して参照するFish が生まれる

Fish は導入したいものではなく、Sea を厳密に運用した結果として構造的に現れる。

根にあるもの: 目的と手段の相対性

Fish が原理的に消えないのは、目的と手段が相対的だからである。

「認証する」は申請提出から見れば手段だが、情報システム部門から見れば 「不正アクセスを防ぐ」という独立した目的であり、その立場では Sea になる。 同じ手続きが、誰の視点で見るかによって Sea にも Fish にもなる。

Cockburn が「まず Sea を見つけよ」と言うのは、この相対性を認めた上で、 主アクターを固定することで Sea を一時的に絶対化する戦略である。 視点を固定すれば Sea は確定する。 だが複数の Sea を並べると、視点をまたいだ共通部分が浮かび上がる。それが Fish である。

これは越境パターン #1(要求に解決策が書かれている)と同じ根から出た症状である。 あちらも目的と手段の相対性ゆえに、解決策が要求の位置に座る問題だった。

2つの問いを分ける

Fish を扱うときは、次の2つを別々に判断する。混ぜると決められなくなる。

  1. その Fish を立ててよいか(粒度の問題)
  2. 立てた Fish はどの層か(層の問題)

順番も入れ替えない。立てないと決まったものに層を問う意味はない。

問い1: Fish を立ててよいか

原則: 複数の Sea から参照されるとき

参照元が1つしかないなら、切り出す理由が存在しない。 Sea の記述内のステップとして本文に書けばよい。 独立させると、読み手は Sea と Fish を往復する手間だけを負う。

正当な Fish の例

社内文書システムで Sea を3つ立てた状態から始める。

S1: 稟議を申請する(主アクター: 申請者)
  1. 申請者がシステムを利用できる状態にする
  2. 申請種別を選ぶ
  3. 申請内容を入力する
  4. 根拠資料を添える
  5. 申請を提出する
  6. 承認経路の先頭に通知が届く

S2: 議事録を登録する(主アクター: 記録担当者)
  1. 記録担当者がシステムを利用できる状態にする
  2. 会議体と開催日を選ぶ
  3. 議事内容を入力する
  4. 配布資料を添える
  5. 参加者に公開する

S3: 規程を改定する(主アクター: 規程管理者)
  1. 規程管理者がシステムを利用できる状態にする
  2. 改定対象の規程を選ぶ
  3. 改定内容を入力する
  4. 改定理由書を添える
  5. 承認経路に回す

3つを並べると、ステップ1が3箇所、ステップ4が3箇所で重複していることが見える。 ここで F1「利用者を認証する」と F2「資料を添付する」を切り出す。

S1: 稟議を申請する
  1. [F1 利用者を認証する]
  2. 申請種別を選ぶ
  3. 申請内容を入力する
  4. [F2 資料を添付する]
  5. 申請を提出する
  6. 承認経路の先頭に通知が届く

判定できる点は3つある。

Sea の完結性が保たれていることが、正当な切り出しの条件である。

副次的な効果として、S1 の「根拠資料」と S2 の「配布資料」という呼び分けが F2「資料を添付する」に統一される。越境パターン #15(用語揺れ)の予防にもなる。

不当な Fish の例

同じ S1 を、網羅性を上げようとして分解した場合。

S1: 稟議を申請する
  ├ F-a: 申請フォームを開く
  ├ F-b: 申請種別を選択する
  ├ F-c: 申請内容を入力する
  ├ F-d: 入力値を検証する
  ├ F-e: 資料を添付する
  ├ F-f: 内容を確認する
  ├ F-g: 提出する
  └ F-h: 通知を送信する

見た目は網羅的で、抜けがなさそうに見える。ここが罠である。

対比

正当(F1・F2)不当(F-a〜F-h)
きっかけ他の Sea と重複した網羅性を上げたかった
切り出し後の Sea業務として読める目次になった
Fish 単独で読めるか読める読めない
参照元複数の SeaS1 だけ
分解の終点重複が消えたところない

もっとも簡単な見分け方は、その Fish が他の Sea からも参照されているかである。 F-b「申請種別を選択する」は S1 からしか呼ばれない。ならば S1 のステップ2として本文に書けばよい。

例外: 単一の Sea からでも切り出す場合

参照元が1つでも、本文に埋めると流れが読めなくなる場合がある。 これは本ハンドブックが認める例外であり、Cockburn の主張ではない。

例として、承認経路の決定を S1 の本文に埋めた場合。

S1: 稟議を申請する(主アクター: 申請者)
  1. [F1 利用者を認証する]
  2. 申請種別を選ぶ
  3. 申請内容を入力する
  4. [F2 資料を添付する]
  5. 申請を提出する
  6. 申請金額が100万円未満なら、経路は所属部門長のみとする
  7. 100万円以上500万円未満なら、所属部門長のあとに本部長を加える
  8. 500万円以上なら、さらに役員を加える
  9. 申請種別が「規程改定」なら、金額にかかわらず法務担当を経路の先頭に加える
  10. 申請者が部門長本人の場合、所属部門長は経路から除き、本部長を先頭とする
  11. 経路上に休職・退職者がいる場合、その代理者に置き換える
  12. 代理者が未設定なら、一段上位の承認者に繰り上げる
  13. 経路の先頭に通知が届く

「申請者が稟議を出して次に渡す」という流れが、6〜12の判定ロジックに飲み込まれている。 ステップ5と13は連続した1つの出来事なのに、間に7行挟まって関係が見えない。

切り出すと流れが戻る。

S1: 稟議を申請する
  1. [F1 利用者を認証する]
  2. 申請種別を選ぶ
  3. 申請内容を入力する
  4. [F2 資料を添付する]
  5. 申請を提出する
  6. [F3 承認経路を決定する]
  7. 経路の先頭に通知が届く

例外を認める3条件

すべてを満たす場合に限る。

基準内容
主アクターの行為ではないシステム側の判定であり、主アクターの動作が途切れる区間
結果だけあれば先に進める後続のステップが判定の中身に依存しない
単独で目的として読める切り出した先だけを読んで意味が通る

2番目の基準は見落とされやすい。 「経路が3段以上なら申請者に確認画面を出す」といった後続分岐があるなら、 判定結果が S1 の流れを左右するため、切り出すと逆に読めなくなる。

F3 と F-b を比べると、参照元が1つという点は同じでも結論が逆になる。

F3 承認経路の決定F-b 申請種別を選択する
参照元S1のみS1のみ
主アクターの行為かいいえ(システム判定)はい(申請者の操作)
埋めたときの行数7行1行
埋めると流れが読めるか読めない読める
単独で目的として成立するしない
結論切り出す切り出さない

判定に迷ったら

次の問いに置き換える。

その区間を「〜が決まる」の一行に要約したとき、 Sea の読み手はそれ以上の情報を必要とするか。

必要としないなら切り出せる。必要とするなら、それは Sea の本文に属している。

例外には理由を書く

例外で切り出した Fish には、理由を一行添えることを必須とする。

F3: 承認経路を決定する (参照元は S1 のみ。経路判定が7ステップに及び、申請の流れが読めなくなるため分離)

理由を書けないものは切り出されなくなる。 分解によって生まれた Fish は理由が書けないため、この一手間だけで大半が防げる。

問い2: 立てた Fish はどの層か

決めるのに発注者への確認が要るなら要件の内訳。上位文書から導出できるなら仕様。

切り出しの理由(共通性か可読性か)と、行き先の層は無関係である。 共通の Fish が要件になることも仕様になることもある。

Fish内容導出できるか層
F1 利用者を認証する認証の要否・タイミング業務判断。聞かないと決まらない要件の内訳
F2 資料を添付する選択方法・サイズ上限・形式「添付できること」から導出できる仕様
F3 承認経路を決定する金額・役職による分岐ルール業務ルール。聞かないと決まらない要件の内訳

語彙による近似

実務テストとして、画面・ボタン・項目名・APIといったシステム内部の操作語が出てきたら仕様側、 という語彙による判定が使える。

導出可能性は考えないと判定できないが、語彙は見れば分かる。 レビューでも指摘しやすい。 ただし言い換えで潜り抜けられるため、原則の代わりではなく補助として用いる。

形式ではなく検証者で判断する

F3 のような Fish は、中身が仕様書に似て見える。 条件分岐が並び、判定可能で、テストケースがそのまま起こせるためである。

だが層を決めるのは形式ではない。その内容の正しさを誰が保証するかである。 承認経路の分岐が正しいかは発注者にしか判定できない。 テスターは「書いてあるとおり動くか」は確かめられるが、 「500万円という閾値が正しいか」は確かめられない。

仕様と判定された Fish の行き先

仕様と判定された Fish は、ユースケース一覧から外し、仕様書の記法に置き換える。 Fish のまま要件の一覧に残さない。

これにより要件のユースケース一覧は Sea と要件側の Fish だけになり、粒度が揃う。 粒度が揃って初めて、一覧の網羅性を判定できる。

要件から仕様へ写すとき

要件として合意したルールは、仕様に写す段階で新たな論点を生む。 F3 でいえば、境界値の扱い(100万円ちょうどはどちらか)、 経路が確定できない場合の扱い、代理者が連鎖するときの上限。

これらは要件の文面からは決まらない。仕様を書く段階で初めて気づく。 そこで発注者に戻すか開発側で決めるかは、再び導出可能性の判定になる。

この局面では越境パターン #9(実装の都合が仕様として確定する)が起きやすい。 境界値やエラー時の扱いを実装中に決め、そのまま仕様書に反映してしまう形である。 決めた事実と決めた主体を残さないかぎり、後から誰も検証できない。

判定手順

  1. その手続きは複数の Sea から参照されるか
  2. 本文に埋めると流れが読めなくなるか(3条件をすべて満たすか)
  3. 立てた Fish は、決めるのに発注者への確認が要るか

まとめ