スキルアップ
【連載】要求工学における「利用状況」の扱いをめぐる考察:アジャイルにもウォーターフォールにも効果的! 振る舞い駆動開発(BDD: Behavior Driven Development)のプラクティス(第3回①)

イントロダクション
連載第1回の最後で「別の機会に述べる」と約束しましたので、振る舞い駆動開発(BDD:Behavior Driven Development)と呼ばれる開発手法と、その中での「状況」の扱い方について解説します。
BDDがそれほど知れ渡っていない現状を鑑みると、そこから説明する必要もあり、BDDの主要な考え方の説明が本稿の大部分を占めます。このため、今回は「状況の話」が脇役になります。
読者の中にはBDDと受け入れテスト駆動開発(ATDD: Acceptance test–driven development)、またテスト駆動開発(TDD: Test-driven development)の関係をご存じの方もいらっしゃるかと思います。歴史的経緯を踏まえると、BDDはTDDをベースにして発展した開発手法ですから、TDDと比較する形で説明されることも多いです。本稿は基本的にTDDの知識が全くなくても理解できるように記述していますから、TDDを知らない方も、安心して読み進んでください。
アジャイル開発の現場はもちろん、ウォーターフォール開発の現場の方にも大いに参考になると思います。特に、要求漏れや上流文書の品質、更新の遅れなどの問題を抱えている場合、今回紹介するプラクティスの一部を採用するだけでも効果が期待できます。
上流の品質向上を目指すと言いつつ、文書体裁の品質向上に熱を上げてしまい、要求仕様の内実や体系化などには改善が及ばない現場は少なくないように見えます。それどころか、せっかく体裁を整えた文書に多数の関与者による改訂が入ることを嫌う管理者が運用規則を増やしてしまうことすらあります。その結果、それがボトルネックになって文書更新が滞る事態を招き、本末転倒になっている現場を見たことがあります。ウォーターフォール開発は、ごく一部の例外を除けば文書駆動開発でもあるため、文書品質を重視するのは分かります。ただ、手段であるはずの文書品質向上が自己目的化してしまい、開発対象の品質向上に結び付かないのでは意味がありません。
特にウォーターフォール開発からアジャイル開発への移行を検討している方にも、ぜひとも読んでいただきたいです。文書の欠如がプロジェクトに与えるリスクを考慮すると、アジャイルへの移行に対して慎重になるのは当然です。多くの管理者がそのような懸念を抱いているのは理解できます。BDDのプラクティスをある程度取り入れれば、少なくともその懸念は払拭できるのではないかと思います。
本稿は工程上のどこの話?
アジャイル開発はデリバリーチームの活動にフォーカスしたプロセス図が示されることが多く、短いサイクルでくるくる回る印象だけが強く残り、それがいろいろと誤解を招く結果になっているのではないでしょうか。
ストーリーのライフサイクルに着目した方が実装チームの外側にも視野を広げられ、見通しが良くなります。Jeff Pattonが同じ趣旨の図を示している[1]のを基に描き直した図を以下に示します(図表1)。

連載第1回でコンセプト策定からディスカバリ前半辺りまでの話をしました。ユーザーストーリーやジョブストーリー、タスク表現は、ユーザーストーリーマッピングなどの手法を使って分析・整理され、評価・選抜され、抽象度や粒度が大きくばらついている状態から適正な粒度に分解されます。「適正な粒度」と表現しましたが、それはステークホルダーや置かれている立場ごとに何が適正かが違ってくるため難しいところです。最終的に何を実装するのかが決まらなければならないので、デリバリーチームとしては細部を詰めた上で作るのに適正なサイズに分解する必要があります。この辺りからデリバリーチームと他のステークホルダーとのコミュニケーションが悪くなっていくことが多いようです。検討内容の粒度が、ビジネス側ステークホルダーの立場からは、主要な関心事よりはさまつに感じる大きさになっていくので、デリバリーチーム任せにしてしまいがちです。デリバリーチームは技術用語などの使用が増え、自分達だけが分かるコミュニケーションに閉じてしまいがちです。そうなると、従来のドキュメント駆動と変わらなくなってしまいます。しかもそのドキュメントは、カードに書かれたユーザーストーリーであったり、ユーザーストーリーマップの写真であったりするので、ウォーターフォール開発よりもさらに共通の理解を妨げる結果になります。BDDはちょうどその辺り、ディスカバリ後半以降の開発手法で、上記で述べた問題を防ぎます。ドキュメントの書き方・管理方法や、継続してビジネス側とデリバリー側との間のコミュニケーションを効果的に行うためのプラクティスが多数含まれています。
先のストーリーのライフサイクル視点での工程図に、BDDの主要な工程を示すと、下図(図表2)の左下に示したようになります。ディスカバリは共通していますが、BDDらしさが発揮されてくるのは後半からになります。定式化(Formulation)、自動化(Automation)という工程が、デリバリー、実装構築に対応する部分に用意されています。ただし、自動化は例えばノーコードのようなコーディングの自動化ではなく、要求仕様と受け入れ基準に対する実例による検証、テストの自動化のことであり、実装や評価の限られた一部であることに注意してください。

ここで「テストの自動化」という表現が出てきますので、「なるほど、テスト自動化が主な目的なのだな!」などとそこに注目してしまう方も多いようですが、そうではありません。自動化は手段であり、二の次であると考えた方がよいです。テスト自動化だけが目的であれば、他にもっと効率が良い方法がさまざまあります。
BDDにおけるディスカバリの主なゴール
BDDのプラクティスの中では、要求とソフトウェアを結び付けるものとして、実例(examples)の作成があります。ルールも作成しますが、これは後で説明します。さらにその実例やルールを次の工程で表現し直してシナリオと呼ぶ形式にするのですが、その話は今回しません。ただ、BDDで実例、ルール、シナリオといえば、概念的にはほぼ対応するものになっていて、表現の抽象度や表現形式の厳密さが違うだけなのだということは、早めに知っておいて損はないでしょう。
工数・工期をかけて作ったのに、フィードバックをもらってみたら、要求を誤解していたことが分かった。あるいは要求の理解が不十分であったことが分かった。アジャイルでサイクルが短期になっているとしても、このような事態は無駄でしかないですから、避けなければなりません。
そこで、作ろうとしているシステムや製品の振る舞い(Behaviour)を定義し、実例(examples)を作り、それを見てもらって要求側からより早くフィードバックを得ることを狙うわけです。
機能の詳細な要件は、デリバリーチームが主導すればよいのですが、ビジネスチームと共同で定義すべきです。
振る舞いの定義を示して確認してもらえば良さそうにも思いますが、あまりうまい方法とは言えません。確認する側の意識が、その振る舞いが要求通りで間違っていないことの確認に集中してしまうからです。そして、間違ってはいないが足りないことには気付きにくくなってしまうのです[2]。開発側としては、このような要求漏れの事態はぜひとも避けたいことです。後から、これこれのケースで機能が足りないとか、振る舞いが期待と異なるといった問題が発覚し、「使えない!」などと言われてしまうからです。一方、実例を使ったコミュニケーションでは、確認する側は使用しているイメージを持ちやすく、さまざまな使用場面や状況を想像しやすくなるようです。
そこで、良い実例を表現することが大事になってきます。「良い実例」とはどういうものでしょうか?
少なくともここでの目的にかなうという意味での「良い」であるべきなので、以下のようなことが望まれます[3]。
・システムがどのように振る舞うべきかを明確に示す具体的な実例であること
・要求を素早く検討し、要求されていることを開発側が全員正確に理解できること
・ビジネス側の要求を開発側が理解できていること、どう理解しているかを示せること
(もう少し大局的にみた質の評価基準は、本稿でも後で改めて説明します。)
ビジネス領域に根差した曖昧さのない用語を使って、システムに期待される振る舞いの共通理解を文書化します。
良い実例は、下図(図表3、4)に示したような3つの部分で構成されているものです[3]※1。


自動販売機の実例を考えてみましょう。最近の自動販売機は電子マネーやモバイル決済への対応など、複雑さが増しています。次のような実例(examples)が出て来るのではないかと思います。

まず、この「操作(Action)」を誤解せずに正しく理解することが大切です。この操作(Action)は、システム側に期待される主要な動きのことではありません(BDDではシステムの期待される動きや働きは「振る舞い(Behavior)」と表現されます)。この操作(Action)は主にユーザーのシステムへの働きかけ(操作)のことを言っており、システム側から見れば入ってくるイベント(Event)に相当します。実例はビジネス領域に根差した曖昧さのない用語を用いて定義するのがよいと先に説明しました。ですから、ここではイベント(Event)ではなく、操作(Action)と表現されているのだと理解するとよいでしょう。
本稿を読まれている方は大別すれば開発側に属すると想定されますので、伝統的な構図と比較すると理解が早いと思います。下図(図表5、6)のようなシンプルなIPO図(Input-Process-Output図)との対応関係を見ることで、理解が深まることでしょう。


この構図では、状況(Context)と操作(Action)は入力(Input)に、そして結果(Outcome)が処理(Process)や出力(Output)に対応しています。そしてデータと制御の流れを分けて、状況(Context)がデータで、操作(Action)が制御に対応しています。(図表7)

BDDの枠組みの中では、実例だけではなく、必ずルール(rule)も定義しないといけません。むしろ、本来はルールの方が欲しいわけです。実例なしでルールを網羅的に抽出することが難しいので、わざわざ回り道をしているわけです。ルールと実例の関係は以下の図(図表8)のようになっています。

ルールだけを最初から考えて、それを網羅的に抽出することは困難です。そこで、実例をいくつも挙げながら帰納推論によってルールを導き出します。これは非常に有効な方法です。ただし、実例をいくら積み重ねたとしても、決してルールに取って代わることはできません[5]。どこかで必ずルールとして定義する必要が出てきます。これを実装者任せにしてはいけません。なぜなら、各個が帰納推論によって導き出したルールが一致するとは限らないからです※2。ですから、ルールとして明確に定義して、ステークホルダー間で確認して合意形成しておく必要があるわけです。
先ほどの自動販売機の実例(examples)を考えてみますと、以下のようなルール※3が出てきます。

このルールはわざわざ実例を考えなくてもすぐに出てきそうな気がします。しかし、ここで実例をさらに考えていきますと、以下のようなものも挙がることでしょう。

5円玉が出てくる実例から、受け入れ可能な硬貨についての制限があり、そのためのルールが必要なことに気が付きます。
500ウォン硬貨の出てくる実例から、外国人が間違えたりする以外に、不正を働こうとした可能性も考えられ、その場合にどうするべきかのルールを明確にする必要があることにも気付きます。
このようなルールはこれから作るシステムの振る舞いを定義しているわけですから、このルールがシステムに対する要求仕様になります。また、基のユーザーストーリー(タスク表現のものを含む)の受け入れ基準にもなります。BDDの先導者の中には、「ストーリーはストーリーである。ルールが要求である。」という説明の仕方をする人もいます。今から作るべきシステムの要求仕様としてはルールがふさわしいことを強調していると理解するとよいでしょう。ここに至って、BDDでは必ず要求仕様と受け入れ基準がルールとして明記される仕組みになっていることが理解されたことでしょう。そして、途中で列挙してきた実例は受け入れ基準を満たしているかを測るテストで使用できます。
ただし、テストで使用できるとはいえ、各プロジェクトで求められる状況や条件に適した本来なされるべきテストに相当するような十分なものではありません。それでも、即時にフィードバックが得られる最小限のテストが準備されたことにはなります。開発の過程で、いつでもこの即時フィードバックが得られることの意義は大きいといえます。
リビング(生きている)ドキュメントへの道
ディスカバリ(Discovery)に続き、定式化(Formulation)、自動化(Automation)工程に説明が続くことを期待される方もいらっしゃると思いますが、本稿では割愛します※4。
流れの理解のために、ごく簡単に説明します。定式化(Formulation)では、実例をシナリオ(scenarios)にGherkinと呼ばれる言語を使って定式化(formulate)します。Gherkinは非常にシンプルな言語で、それを使って実例を定義し直すことで、機械処理できる程度に構造化できるので、自動テストとして使用でき、同時にビジネス観点で読み取り可能な要求仕様を表現できます。自然言語のようにも読めるシナリオでドキュメントを作成することで、ビジネス側とのコミュニケーションに活用することと、機械処理して自動テストに活用することを両立させるのです。そして自動化(Automation)では、システムの動作を検証できるようにシナリオを自動化します。
さて、Seb Roseは、次のような面白い問いかけを行っています[4]。
「間違った文書と文書がないのと、どちらを選ぶべきですか?」
そんな選択を迫られても困ってしまうわけですが、にもかかわらず多くの現場がどちらかを選んだことになってしまっています。ウォーターフォールの現場で、更新されていない文書の古いままの記述を信用してしまい、欠陥を作り込んでしまった。そんな苦い経験を多くの開発者が持っています。更新されていないことが問題なのですが、運用の徹底が難しいので、いっそのこと文書など作らなくてもよいアジャイル開発の方がうまくいくのではないか、そう考える人たちもいるようです。
ところで、アジャイル開発では文書を作らないというのは誤解です。もしもそのような誤った理解をしている人に出会ったら、文書は不要ということではなくて、文書化のアプローチが異なるのだと説明するとよいでしょう。アジャイル開発では必要な情報を適切なタイミングで提供し、過度な文書作成を避けることを重視します。それでも、プロジェクトの成功に必要な文書はしっかりと作成・維持しなければなりません。ただ現実には確かに問題もあります。アジャイル手法を選択した途端、文書について、形式や手順・運用がデリバリーチーム任せになってしまっているケースは残念ながら多いようです。
BDDでは、自動化(Automation)までを含めて実践すれば、その中でリビング(生きている)ドキュメントが実現します。リビングドキュメントとは、開発の進行と共に常に更新され続ける文書で、仕様と実装が一致することを保証するものです。
実装の変更を急ぎ、対応する文書の変更を忘れたり、漏れなく修正したはずなのに、他の思わぬところに影響が及んで不一致が発生してしまう、そのようなことはよく起こります。自動化が実現できていれば、ドキュメントと実装が少しでも乖離(かいり)したら、すぐにアラートが上がってきます。また影響がどこに出ているかも特定できます。
リビングドキュメントは、ウォーターフォール開発の現場でも、ずっと望まれてきたことです。
例えば、システムズエンジニアリングを実践している現場で、伝統的に文書ベースで行われてきた活動をモデルベースアプローチに移行する場合、その目的は次に示すようなことをより容易なものにしたり、向上させたりする効果を期待しているはずです[6]。
・ステークホルダー間、開発チーム間のコミュニケーション
・仕様および設計の品質
・システム仕様と設計成果物の再利用性
この問題意識や狙いはBDDと非常に似ています。
なぜモデルベースである必要があるのかという主要な理由として、Friedenthalら[6]は、文書ベースでの厳密な運用が難しいこと、それは文書という単位がトレースに必要な粒度に対して粗過ぎることを挙げています。文書内を必要な粒度まで分解した見方をすることは、理屈としては考えられますし、ツールにそのための機能も普通は用意されています。とはいえ、実際にこういったことに取り組まれたことがある現場では皆さん実感していると思いますが、運用を徹底化することは極めて難しいわけです。運用を開始する前に、文書の構成の仕方や、文書を構成している特定の部分を指し示すルールなどを厳密に明確化し、組織で合意・共有化しなければ属人的でばらばらな表現で溢(あふ)れかえる結果になるからです。このような事態を防ぐ事前の手間や工数自体がすでに大きなコストとなってしまうところが文書ベースの問題である、とFriedenthalら[6]は説明しています。(ただし、筆者の考えではモデルベースにしたら、この問題が全て解決するかのような説明は不誠実だと思います。やはり運用ルールを明確化し、組織で合意・共有しなければならない部分はあります。そうしないと、属人的でばらばらな表現の誰の役にも立たないモデルが量産される問題が起きるからです。)そのためFriedenthalら[6]は、文書ベースでは、いくつもの文書にわたって存在している情報間のトレースは粗くて曖昧なものになり、要求,設計,エンジニアリング解析,そしてテスト情報間の「完全性」,「一貫性」および「関係性」を評価することを難しくする、と指摘しています。結果として、システムの変更や進化を妨げる懸念を表明しています。このシステムズエンジニアリングの問題意識も、BDDとかなり共通していると言えます。文書では粒度が粗過ぎるため、片やモデルに解決策を求め、片やシナリオに解決策を求めていると見ることができます。そうは言っても、BDDがモデルの有効性を否定しているわけではありません。むしろ、必要に応じてモデルも作成することを推奨しています。自然言語として読めるシナリオをベースとすべきですが、そのシナリオの理解を補強するものとして伝統的な手法の中で有効なものは積極的に使っていくべきだとしています。
モデルベースの側でも、例えば要求に対するテストケースを結び付けてモデルに描き込めるようになっていて[6][7]、そこを自動化していこうという動きもあります。そうすると同じように、こちらはリビング(生きている)モデルが実現することになるはずです。
注
※1) 設計を経験していて勘の良い方は、もうここで気付かれたと思います。これは複数のルールや条件を組み合わせる前のデシジョンテーブルや状態遷移表の各1ケースに相当すると考えてよいでしょう。到達ゴールがそこにあることをイメージしながら以降を読んでいただくと、理解が早いと思います。
※2) 例えば、1⊕1=2, 10⊕15=25, 25⊕32=57, 41⊕56=97のように実例が示されていると、「なるほど、⊕はアディション(足し算)のことだな」と理解する人がいてもおかしくありません。しかし、それで68⊕57は125だろうと思っていたら、68⊕57=5だということが起こり得ます。そこで改めてルールを確認すると、「もしxとyがどちらも57以下の場合、通常のアディション(足し算)を適用しますが、もしxまたはyのどちらかが57より大きい場合、結果は常に5になる」のがルール、⊕はクワディション(クワス算)と判明したりするのです。そういう問題の発生を防ぐ必要があります。
※3) ルールの表現形式について、BDDの推進者は曖昧な態度を取っていることが多いようです。 後で自動化に使われるのは実例の方なので、実例については機械処理可能な定式化を求める一方で、ルールについては自由記述になっている例示をよく見ます。 筆者は、特に理由がない限り、ルールの表現形式についても実例と同じように、状況 (Context)、操作 (Action)、結果 (Outcome) の3項目で定義するのがよいと考えます。 ルールの表現形式を自由にすると、誤解を招き入れることになりかねないからです。
※4) 本連載では、他の文献で説明されていることは本稿の趣旨に必要な最小限にとどめ、繰り返さないことにしています。文献に書かれていないが補足しておくべきこと、文献と文献の間を埋めたりつなげたりするような内容に絞っていますので、包括的な理解を求める方は、参考文献に示したものを併せて読んでください。
参考文献
[1] Jeff Patton (著), 川口 恭伸 (監修), 長尾 高弘 (翻訳)『ユーザーストーリーマッピング』オライリージャパン
[2] プロダクトマネージャーカンファレンス ビジネスから開発まで、チーム全員で要件を磨く!今日から使える「実例マッピング」 - #pmconf2022, https://www.youtube.com/watch?v=Mo-JeOwmhWQ, Accessed Feb 2, 2025.
[3] Gáspár Nagy and Seb Rose, Discovery: Explore behaviour using examples, BDD Books
[4] Seb Rose and Gáspár Nagy, Formulation: Document examples with Given/When/Then, BDD Books
[5] Liz Keogh, Acceptance Criteria vs. Scenarios, https://lizkeogh.com/2011/06/20/acceptance-criteria-vs-scenarios/, Accessed Feb 2, 2025.
[6] サンフォード・フリーデンタール, アラン・ムーア, リック・スタイナー 著,西村秀和 監訳, 『システムズモデリング言語SysML』, 東京電機大学出版局
[7] MaruLabo Micro Media 浅海ゼミ 基本編 第33回「テスト」, https://www.youtube.com/watch?v=IxxoPwlL1gw, Accessed Feb 2, 2025.
この記事は面白かったですか?
今後の改善の参考にさせていただきます!