レイヤードとクリーンアーキテクチャ — ケーキの層か、芯を守る玉ねぎか
アプリのコードは、役割ごとに層に分けて書くのが基本です。画面を担当する層、注文や割引といったビジネスのルールを担当する層、データベースに読み書きする層。問題は、層と層がどちら向きに頼り合っているかです。
よくあるレイヤードアーキテクチャは、ケーキの層のように上の層が下の層に乗っています。上は下を使い、下は上を知らない。だから一番下を引き抜くと、上の層がつられて崩れます。クリーンアーキテクチャは玉ねぎです。いちばん大事なビジネスのルールを芯に置き、画面もデータベースも外側の皮にして、外から内へしか頼らないようにします。図1で、同じ変更を2つの作りに起こしてみてください。
mysql.query("INSERT …") | 変更 | 🍰 レイヤード | 🧅 クリーン |
|---|---|---|
| 画面を替える | — | — |
| DBを替える | — | — |
| DBなしでテスト | — | — |
ケーキは、下を引き抜くと上が崩れる
レイヤードで「画面を替える」と、書き換えるのは一番上の層だけです。上の層を知っている層はないので、変更はどこにも広がりません。ところが「DBを替える」と、ビジネスルールの層までつられて崩れます。ビジネスルールのコードの中に mysql.query(…) のようなMySQL専用の書き方が直接入り込んでいるからです。
変更は、依存の矢印を逆向きにたどって広がります。下の層ほど、たくさんの層に「使われて」いるので、変えたときの被害が大きい。そしてレイヤードでは、一番下にあるのがデータベースという、いちばん替わりやすい部品なのです。
玉ねぎは、芯を守るバリアを張る
クリーンアーキテクチャでは、芯の割引ルールは「注文をどこかに保存できること」という約束(インターフェース)だけを知っています。MySQLに保存する部品は、外側の皮の中でその約束を守るように作ります。これで矢印の向きがDBから芯へとひっくり返ります(依存性逆転)。
だからDBを替えても、書き換えるのは外側の部品1つ。芯にはバリアが張られたまま、一文字も変わりません。同じ理由で、テストのときは約束を守る偽物のDBを差し込めば、本物のデータベースを用意せずに割引ルールだけを確かめられます。そのかわり、約束(インターフェース)と差し込む仕組みのぶん、ファイルと手間は増えます。小さなアプリでは、レイヤードで十分なこともよくあります。
- レイヤード
- 画面・ビジネスルール・データのように層に分け、上の層が下の層を使う作り方。
- クリーンアーキテクチャ
- ビジネスのルールを中心に置き、画面やDBなどの外側が内側に頼るように作る考え方。
- 依存
- あるコードが、別のコードを使っている(知っている)こと。使われる側が変わると、使う側も直す必要が出る。
- インターフェース
- 「こういう操作ができる」という約束だけを決めたもの。中身の作り方は決めない。
- 依存性逆転
- 内側が約束を決め、外側がそれを守る形にして、依存の矢印の向きをひっくり返すこと。
まとめ
層に分けるだけでは足りず、どちら向きに頼るかが大事です。ケーキのように替わりやすいDBを一番下に敷くと、引き抜いたときに大事なルールまで崩れます。玉ねぎのように大事なルールを芯に置き、外から内へだけ頼らせれば、画面やDBを替えても芯は守られ、テストも芯だけで回せます。