AIコーディングで要件は書けているのにUXがずれる違和感から出発し、Uncle BobとIvan Tokarのやり取りを通じてDDDとBDDを組み合わせた前提資料のワークフローを思いついた話。

AIにコードを書かせるとき、前提をどこまで固めてから渡しているか。

自分は grill-with-docs でドメインを詰め、to-prd で要件をまとめ、to-issues でタスクに割って実装に進む、という流れを回している。この流れ自体は悪くない。ドメインの用語も整理されているし、要件も書けている。

でも完成品を見ると、UXの部分でずれることがあった。「このボタンを押したら、このタブを閉じて、このアクションを実行する」みたいな、複雑な条件付きの振る舞い。こういう部分が要件に書ききれておらず、実装者が解釈で埋めることになる。結果として、意図と違うUXができあがる。

要件は書けているのに、振る舞いが正確に表現できていなかった。

この違和感を抱えていたとき、Xのタイムラインに偶然流れてきたのがきっかけだった。

Uncle Bob MartinがGherkinという単語を使っている投稿を見かけた。「Given / When / Then」がどうのこうのと書いている。意味がわからなかったので、GoogleでGherkinを検索してみた。

そこで初めて知った。GherkinはBDD(Behavior-Driven Development)という設計手法で使われる、振る舞いを記述するための言語だった。TDDが「テスト」の粒度でコードを設計するのに対し、BDDは「ユーザーの振る舞い」の粒度で要件を設計する。Gherkinの Given / When / Then は、その振る舞いを自然言語で書くための書式だ。

なるほど、と思いながら元のツイートを読み返したら、話が繋がった。

Uncle Bobが言っていたこと

あらためて、Uncle Bobがその投稿で何を言っていたのかを整理する。

Gherkinの Given / When / Then は、有限状態機械(FSM)の状態遷移と同じ構造だという主張。

言われてみれば確かにそうだ。「状態Xにあるとき、イベントYが起きたら、状態Zになる」。Given / When / Then はそのまま、前提・イベント・結果に対応している。

Gherkinは単なるテストの書式ではなく、ソフトウェアの振る舞いを状態遷移として記述するための言語、と見なせる。なるほど、と思った。

「でも」という返信

その投稿に対して、Ivan Tokarという人がこう返していた。

要するに、「Gherkinは遷移の契約としては優秀だけど、前提となる状態モデル・イベント・不変条件・意味論が先に明確になっていないと、ただのきれいに整えた文章にすぎない」という指摘。

Uncle Bobの「Gherkinは万能」という主張に対する、実務的なブレーキ。

ここで腑に落ちた。Gherkinを書くこと自体は難しくない。難しいのは、書く前に何を固めておくかだ。

DDDで内側を、BDDで外側を

ここでDDDとBDDの関係が見えてきた。

DDDは、プロダクトの内側の世界を固める。何を何と呼ぶのか。どこまでが同じ概念なのか。どこから別の文脈なのか。いわば、世界の辞書を作る作業。

一方でBDDは、外側から触ったときの振る舞いを固める。ユーザーが何をしたらシステムがどう反応するのか。成功すると何が変わるのか。失敗すると何が見えるのか。こちらは、その世界で起きる物語を書く作業。

Ivanの指摘をDDDの視点で読み直すと:

  • 状態モデル → Aggregate や Entity のライフサイクル
  • イベント → Domain Event
  • 不変条件 → Business Rule
  • 意味論 → Ubiquitous Language

つまり、DDDでIvanが言う「前提」を固めてから、BDDで振る舞いを書くという順番が自然になる。

1. DDDで用語・境界・前提を固める
2. 要求としてまとめる(ユーザーストーリーの洗い出し)
3. BDDで振る舞いをGherkinとして書く
4. 書いて気づいたことを要求に戻す
5. 実装できる単位に割る

大事なのは、Gherkinを書くこと自体が目的ではないこと。目的は、行動を洗い出すこと。ユーザーが何をするのか、システムが何を変えるのか、何は変えてはいけないのか。それを詰問して、結果としてGherkinの形で残す。

例えばこんな感じ:

Scenario: アクティブなワークアウトを完了する
  Given ユーザーがアクティブなワークアウトセッションを持っている
  When ユーザーがワークアウトを完了する
  Then ワークアウトは完了済みとして保存される
  And アクティブなワークアウトセッションは存在しなくなる

DDDで「ワークアウトセッションとは何か」「完了とはどういう状態遷移か」を先に決めておけば、このGherkinは「きれいな文章」ではなく「事前に合意したドメインモデルの実行可能契約」になる。

これをAIエージェントのワークフローに置くと

自分はAI codingで開発を回している。このDDD+BDDの組み合わせを、AIエージェントに前提資料として食わせるワークフローに組み込めないかと考えた。

DDDで固めた辞書と、BDDで固めた振る舞いを、実装前の前提資料として置いておく。そうすると、実装前の会話も、要求定義も、issue分解も、レビューも、かなりブレにくくなるはず。

ちなみに、最近Matt Pocockが公開したAIコーディング用のスキル集(mattpocock/skills)が94kスターを集めている。その中にある grill-with-docs は、ドメインの用語や前提を詰めていくグリルスキルで、まさにDDD側の用途にぴったりだ。

DDD側にはこの grill-with-docs を使い、BDD側には自分でオリジナルの grill-with-gherkin を作った。これに to-prd でユーザーストーリーを洗い出して要求にまとめるステップを挟めば、DDDで辞書を作り、BDDで物語を書くという流れをスキルの組み合わせで実現できる。

まだ試していない

このワークフロー、まだ実戦では試していない。「こういうの作ったらどうなんだろう」というふとした考えのレベル。

ただ、「DDDで辞書を作って、BDDで物語を書く」というこの2ステップを、AI codingの前提として置くという視点は、自分の中でかなり腑に落ちている。

次のプロジェクトで試してみようと思っている。