〇〇駆動開発が多すぎる。ルーツと「どの階層に効くか」で整理してみた
〇〇駆動開発が多すぎる。ルーツと「どの階層に効くか」で整理してみた

〇〇駆動開発が多すぎる。ルーツと「どの階層に効くか」で整理してみた

はい、どうもこんにちは佐藤です!

巷では AI 駆動開発だ、ドメイン駆動設計だ、テスト駆動開発だと色々出てきて、正直かなり混乱していました。

そこにきて、つい先日です。

振る舞い駆動開発。

もうお手上げ侍。

でも、落ち着いて並べてみたら見えてきたことがあります。それぞれの駆動開発にはルーツがあって、派生系でしかないのです。鬼滅の刃の呼吸みたいなものですね。日の呼吸があって、そこから炎や水が生えている。あの構造とよく似ています。

というわけで今回は、現時点の私の認識をまとめた鳥瞰図をお届けします。個別の手法の深い解説はしません。どこから生えて、どの階層に効くのか。その地図を描くことに集中しますね!


根源にあるのは「分割統治」

まず押さえておきたいのが、すべての源流です。

システム開発の根っこにあるのは、大きすぎて手に負えないものを分けて統べるという発想でした。古くは Parnas が 1972 年に情報隠蔽を論じていますし、高凝集・低結合という言葉も長く使われていますよね。

ここから枝が分かれていきます。

ソースコードをどう分けるかに注目したのが、マイクロサービスやモジュラーモノリスの流れ。ビジネス側との認識のズレをどう消すかに注目したのが、ドメイン駆動設計です。

ここで一つ、私が長らく順序を勘違いしていた話をさせてください。

「まずマイクロサービスがあって、その内側の話としてドメイン駆動設計が生まれた」と思っていたのですが、これは逆でした。ドメイン駆動設計( Evans )が 2003 年、マイクロサービスという言葉が広まったのが 2014 年頃です。

しかも、ドメイン駆動設計の境界づけられたコンテキストという概念こそが、「じゃあサービスをどの単位で切るのか」という問いに理論的な支柱を与えました。つまり DDD がマイクロサービスを生んだ側なのです。さらにその反省として、2010 年代後半にモジュラーモノリスが出てきました。

順番を間違えると、系譜そのものが崩れます。ここは覚えておいて損はないですよ。


テストから生えた枝、ドキュメントから生えた枝

もう一つ、別の方向に伸びた枝があります。

テストから作っていくという流れ。これがテスト駆動開発( TDD )ですね。そこから振る舞い駆動開発( BDD )が出てきます。

ここも私は誤解していました。「 TDD だと 1 メソッド単位の検証になって大局が見えない。だから BDD が生まれた」と思っていたのですが、Dan North が BDD を言い出した動機は少し違います。**「 TDD をどう教えるか、何からテストを書けばいいのかが伝わらない」**という、教育上の問題意識が出発点でした。テストという言葉が誤解を生むので、振る舞いと言い換えたわけです。

そしてもう一方に、日本の SI で長くやってきたウォーターフォールからのアプローチがあります。要件定義を書いて、画面設計を書いて、システムに落としていく。いわゆるドキュメント駆動開発ですね。

ただ、これはフロントとバックが分かれる今の作り方と相性が悪いんです。1 冊の設計書で全部を統べる、という前提が崩れていますから。

そこで、境界をまたぐところだけを先に固める発想が出てきます。OpenAPI や JSON Schema といった API 設計書を中心に据える、API ファースト(スキーマファースト)です。

なお機能駆動開発( FDD )ですが、これは 1997 年、De Luca がシンガポールの銀行案件で使ったのが始まりです。ドメイン駆動設計より古いんですね。なので「 DDD の土台の上に立つ」わけではありません。どちらも「先にドメインのモデルを作る」という点で、同じ源流から別々に生えた枝と見るのが正確でしょう。


システムの階層に重ねてみる

ここからが本題です。それぞれの手法は、システムのどこに効くのか。

システムはざっくり、こう分かれますよね。

  • モジュール
  • プレゼンテーション層
  • アプリケーション層
  • ドメイン層
  • インフラストラクチャ層

モジュールという入れ物があって、その中に層があるイメージです。インフラストラクチャ層は永続化や外部連携の担当で、今回の駆動開発の話とはあまり絡まないのですが、層の話として一応挙げておきます。

そしてドメイン層の中身。ここがさらに分かれます。

  • アグリゲート
  • エンティティ
  • バリューオブジェクト( VO )
  • ドメインイベント

システムアーキテクチャの構成。システムの中にモジュールがあり、その中にプレゼンテーション層・アプリケーション層・ドメイン層・インフラストラクチャ層が重なり合う。ドメイン層の内側にアグリゲート、エンティティ、バリューオブジェクト、ドメインイベントが入っている

こうして図にすると、層はきれいに積み上がっているのではなく、重なり合っているのがわかりますよね。特にアプリケーション層とドメイン層の境目は、現場だといつも揉めるところです。

ドメイン駆動設計の進め方は、この粒度に沿って降りていきます。

まず VO で、ビジネス側との言葉のズレを潰します。氏名とは何か、電話番号とは何か。ここを揃えるだけで認識相違はかなり減りますよね。

次に エンティティ。VO との違いは包含関係ではありません。同一性で識別するのがエンティティ、値で等価判定するのが VO という、別の軸の話です。ここ、私はずっと「エンティティが VO をまとめるもの」だと思っていました。

そして アグリゲート。実務でいちばん効く定義はこれです。

アグリゲートとは、トランザクション整合性の境界である。

どこまでを 1 つの塊として一貫性を保つのか。それを決める線引きなのです。この塊がどんな状態を持ち、どんなイベントを発生させるのか。それを洗い出すのがイベントストーミングですね。


取引先管理システムで考えてみる

抽象的なので、具体で見てみましょう。基幹システムに取引先管理システムがあったとします。

モジュールは、こんな分かれ方をしますよね。

  • 認証
  • 名刺管理
  • 案件

このうち名刺管理モジュールを開いてみます。アグリゲートは連絡先と会社の 2 つ。連絡先アグリゲートの中には、連絡先・状態・会社紐付けといったエンティティが入ります。そして氏名や電話番号がバリューオブジェクトです。

ここで一つ、昔やらかした話をさせてください。

トランザクションテーブルのエンティティ層のモデリングが甘かった案件がありました。何が起きたか。トランザクションの状態が増えるたびに、SQL がどんどん太っていったのです。

状態が 1 つ増えるたびに条件が増える。条件が増えるたびに結合が増える。誰も全体を読めなくなる。あれは本当にしんどかったですね……。

ドメイン層のモデリングが甘いと、そのツケは必ず後工程で返ってきます。しかも返ってくるのは、いちばん直しにくいところ。これが「なぜドメイン層から考えるのか」の、私にとっての答えです。


どの駆動開発が、どの階層に効くのか

ここまでを 1 枚にまとめます。

駆動開発主に効く階層先に決めるもの
マイクロサービス / モジュラーモノリスモジュール分割の境界
ドメイン駆動設計( DDD )ドメイン層言葉とモデル
機能駆動開発( FDD )アプリケーション層機能の一覧
テスト駆動開発( TDD )ドメイン層( VO・エンティティ )検証したい値
振る舞い駆動開発( BDD )アプリケーション層・アグリゲート業務のシナリオ
API ファーストプレゼンテーション層とアプリケーション層の間境界をまたぐ契約
ドキュメント駆動開発各層設計書
仕様駆動開発( SDD )各層( AI への入力 )仕様と決定の記録
AI 駆動開発全体まだ模索中

こうして並べると、別々の宗派が争っているのではなく、それぞれが別の階層を担当しているのがわかりますよね。

ドキュメントの話も同じ構造です。プレゼンテーション層には画面設計書や帳票設計書がある。アプリケーション層には機能(ユースケース)設計書がある。そしてプレゼンテーション層とアプリケーション層のあいだを埋めるのが、OpenAPI を使った API ファーストというわけです。

機能駆動開発は、この文脈だとアプリケーション層の設計を考える手法。ドメイン駆動設計とドキュメント駆動開発の中間あたりに置くと収まりが良いですね。


テストも階層で分かれる

テストの話に戻ります。

まず前提として、テスト駆動開発は「テストを先に書く」という順番の話です。粒度の話ではありません。理屈の上では、どんな粒度でも TDD はできます。

ただ、実際にやってみるとどうでしょうか。

私の経験上、TDD はどうしても細かい粒度の検証に寄っていきます。この VO の最大値と最小値は。この正規化は。この境界値は。枝葉はきれいに見えるのですが、業務としてこの機能が成立しているのかは、そこからは見えてこないんですよね。

だからこそ、振る舞い駆動開発で考えると良いのだと思っています。

見るのはアグリゲートとアプリケーション層です。「この業務シナリオを流したとき、アグリゲートは意図した状態に遷移するか」を検証する。ここまで上げると、ビジネス側との整合性をチェックできるようになります。

TDD で足元を固めて、BDD で全体を見る。対立ではなく、担当している階層が違うだけなのです。


AI 駆動開発と、仕様駆動開発

そして近年の AI 駆動開発です。

正直なところ、ここはみんなまだ手探りですよね。従来のどの手法と組み合わせるのが良いのか。それとも AI にざっくり作らせてからイメージを固めた方が速いのか。議論が続いています。

現時点の私の考えは、ドメイン駆動・テスト駆動・ドキュメント駆動とのコラボレーションが大事、というものです。

そのうえで、仕様駆動開発( SDD )は AI 駆動開発と特に相性が良いと思っていて、私は推奨する立場を取っています。

理由はシンプルです。AI に渡すべき入力は、コードの断片ではなく仕様と、そこに至った決定だからです。何を作るのかが曖昧なまま AI に投げると、動くけれど意図と違うものが高速で積み上がっていきます。

私が自作している要望管理ツール kanae も、まさにこのために作っています。仕様を Markdown で 1 件 1 ファイルとして管理して、ADR(アーキテクチャ決定記録)も同時に作れるようにしてあります。仕様と決定が同じ場所に揃っていれば、AI はそれを読んで動けますからね。


まとめ

というわけで、〇〇駆動開発は派生系でしかないよ!って話でした!

ここまで読んで、「あれ、実は現場でもう〇〇駆動開発していたのでは?」と思った方、多いんじゃないでしょうか。そうなんです。名前を知らなかっただけで、みなさんもう半分くらいはやっているはずですよ。

そして正直に言うと、厳密に切り分けることはできません。DDD だけで完結する現場もなければ、BDD だけで回る現場もない。結局のところ、それぞれをつまみ食いしていくのが現実的な落とし所になります。私の現場感覚では、これがいちばん正直な結論です。

ただ、つまみ食いにも上手い下手があります。今やっている仕事が、どのルーツから来ていて、どの階層を対象にしているのか。それを意識してカテゴリ分けできるようになると、設計の精度は確実に上がっていきます。

最後に一つだけ。私はこの領域の議論を追い始めて数年なので、間違っているところがあれば連絡をいただけると助かります。 認識をアップデートしていきたいので、ぜひ教えてください。

考えながら、目の前の仕事をやっていきましょう!

この記事をシェアする