
説明
第1回はバックエンド担当のしゅんがリード。Clean Architectureの考え方を「なぜ層を分けるのか」「依存の方向ってどういうこと?」という切り口で解説。ゆいがフロント視点から「コンポーネント設計と似てる?違う?」と切り込みます。
登場人物
水野 ゆい
30歳、スタートアップでフロントエンドリードをやっている。React/Next.js/CSSが得意領域で、UIやUXの話になると熱くなる。身近な体験に紐づけて説明するのがうまく、テンポよく話す。バックエンドの話は素直に感心しながら聞くタイプ。堅すぎず、友達と話すような自然な口調。
桐山 しゅん
33歳、SaaS企業でバックエンドエンジニアとして働いている。Go/Node.js/DB設計・インフラが得意領域。論理的だけど穏やかに話し、たまにマニアックな深掘りに走る。フロントの話には新鮮なリアクションを返す。落ち着いたトーンだが親しみやすい。
会話テキスト
- 水野 ゆい
こんにちは、ゆるふわプログラミングラジオへようこそ。
- 桐山 しゅん
どうも、桐山しゅんです。
- 水野 ゆい
水野ゆいです。このポッドキャストは、フロントとバックエンド、それぞれ得意分野の違う2人のエンジニアが、設計パターンやアーキテクチャをゆるく、でも中身はちゃんと話していく番組です。
- 桐山 しゅん
エンジニア中級者の人が「あー、そういうことか」って腹落ちできるような内容を目指してます。よろしくお願いします。
- 水野 ゆい
よろしくお願いします。第1回なので軽く自己紹介すると、私はスタートアップでフロントエンドのリードをやっていて、React、Next.jsあたりが専門です。UIとかUXの話になると止まらなくなるタイプです。
- 桐山 しゅん
僕はSaaS企業でバックエンドエンジニアをしています。GoとかNode.jsとか、DB設計やインフラも担当していて、たまにマニアックな方向に深掘りしすぎるって言われます。
- 水野 ゆい
今日はしゅんがリードで、Clean Architectureの話をしてもらう回です。
- 桐山 しゅん
そうですね。名前は聞いたことあるけど結局なに、みたいな人が多いテーマだと思うので、今日はそこを一緒に整理したいなと思ってます。
- 水野 ゆい
正直に言うと、最初に「今回Clean Architectureやろう」って言われたとき、バックエンドの話でしょって思ってたんですよ。
- 桐山 しゅん
それよく聞く反応です。でも話していくと、意外とフロントにも刺さる部分があると思うので毛嫌いせず話してみましょう。
- 水野 ゆい
ちょっと楽しみになってきました。あと、今日これをやろうと思ったのって、最近仕事で痛感したことがあって。APIのレスポンス形式が1個変わっただけで、5ファイル同時に修正しなきゃいけなくて、しかも全部コンポーネントに直書きされてるから追うのが大変で。
- 桐山 しゅん
それ、まさにそれです。「この変更、なんでこんなに広範囲に壊れるんだっけ」ってなる瞬間こそ、Clean Architectureが効いてくるタイミングなんですよ。
- 水野 ゆい
じゃあ今日はそこから話してもらいましょう。
- 桐山 しゅん
Clean Architectureをひと言で言うと、ビジネスの中核、つまり業務のルールを中心に置いて、データベースやフレームワークみたいな「詳細」を外側に追い出す設計の考え方です。
- 水野 ゆい
「詳細」って、具体的にどういうものが詳細に入るんですか。
- 桐山 しゅん
たとえばWebフレームワーク、データベース、外部のAPIとか決済サービスとか。要は「変わりやすいもの」ですね。
- 水野 ゆい
変わりやすいものを外に追い出す。それって、変わっても中心が壊れないようにするためってこと?
- 桐山 しゅん
そうです。有名な同心円の図があって、中心から順に、エンティティ、ユースケース、インターフェースアダプター、フレームワークとドライバーという4つの輪で表現されます。
- 水野 ゆい
中心ほど本質的で、外側ほど実装の詳細、みたいなイメージ?
- 桐山 しゅん
そのイメージで合ってます。で、ルールは1個だけで、依存は外側から内側に向ける。内側は外側のことを知らない。
- 水野 ゆい
ちょっと待って、層を分けるって話、私の仕事だとコンポーネント設計でも似たことやってる気がするんですよ。プレゼンテーションコンポーネントとコンテナコンポーネントを分けるやつとか。UIの見た目だけ担当するやつと、データ取得や状態管理を担当する部分を分ける発想で。
- 桐山 しゅん
似てる部分はありますよ。確かに通じてる。
- 水野 ゆい
でも何か違う?
- 桐山 しゅん
粒度と、「何を守るか」が違うかな。フロントのコンポーネント分割はUIの再利用性や見通しのよさが主目的になりやすい。Clean Architectureは業務ルールを外側の都合から守るのが目的です。
- 水野 ゆい
目的が違うのか。見た目の整理じゃなくて、業務ルールを守るための設計なんですね。
- 桐山 しゅん
ゆいが最初に言ってた、APIのレスポンスが変わって5ファイル修正になった話、あれって何が起きてたかというと、1つのコンポーネントがAPI通信も状態管理も表示ロジックも全部抱えてたんじゃないですか。
- 水野 ゆい
図星です。500行のコンポーネントが存在してました。
- 桐山 しゅん
バックエンドでも全く同じことが起きて、「注文確定」みたいな処理がコントローラーにベタ書きされてると、割引ルールを1個追加したいだけで影響範囲が10ファイル以上になったりするんですよ。
- 水野 ゆい
それ、修正のたびにどこまで壊れるかわからなくて怖いやつだ。テストも全部通るか不安になるやつ。
- 桐山 しゅん
そう、怖いんですよ。だから層を分けることで「変更が波及しない守るべき中心」を作るのが本質で、きれいに見せるためじゃないんです。
- 水野 ゆい
そこ大事ですね。きれいに見せるためじゃない。
- 桐山 しゅん
ここで一個よくある誤解を言うと、Clean Architectureイコールフォルダを4層に分ければ完成、って思ってる人が多い。
- 水野 ゆい
私もそのイメージだったかも。ディレクトリ構造の話だと思ってた。domain、usecase、infrastructure、みたいなフォルダ作れば完成みたいな。
- 桐山 しゅん
フォルダ分けだけだと、中心が外側の型や都合に汚染されて結局崩れるんですよね。本質は依存の向きと、中心を守ることの2つです。
- 水野 ゆい
フォルダ分けは手段であって目的じゃない、か。
- 桐山 しゅん
そうです。で、フロントには関係ないってよく言われるんですけど、UIと内側のロジックを分ける発想はコンポーネント設計でも効くんですよね。ただ、バックエンドの層の切り方をそのままフロントに移植しようとするとうまくいかないので、そこは注意が必要で。
- 水野 ゆい
発想は借りるけど、実装はそのままコピーしない、ということですね。Reactにバックエンドのレイヤー構造を無理やり持ち込んでも、かえって読みにくくなりそう。
- 桐山 しゅん
まさに。だから今日できる一歩として、自分のプロダクトで「変わりやすい詳細」を3つ挙げてみてほしくて。Webフレームワーク、データベース、外部APIとか。それが業務ルールのコードに直接入り込んでないか点検するだけでも見えてくるものがある。
- 水野 ゆい
フロントなら、APIレスポンスの整形処理がコンポーネントに直書きされてないか確認する、みたいなことですよね。
- 桐山 しゅん
そうそう。変換処理を1箇所に集めるだけで、さっきの5ファイル修正みたいな問題はだいぶ減る。
- 水野 ゆい
実感があります。じゃあ次は「依存の方向を守る」って具体的にどういうことか、聞いていいですか。
- 桐山 しゅん
そこが一番ピンとこない部分だと思うので、ちゃんと話しますね。
- 水野 ゆい
お願いします。
- 桐山 しゅん
「依存の方向を外から内へ」って言うと、「でも内側からデータベースを呼び出してるんじゃないの?」ってなりますよね。
- 水野 ゆい
なります。呼び出してる側が依存してるんじゃないの、って思う。
- 桐山 しゅん
そこが大事なポイントで、「呼び出す方向」と「依存の方向」は別物なんです。
- 水野 ゆい
ちょっと整理して。どう違うの?
- 桐山 しゅん
ユースケースがデータを保存したいとき、直接データベースを呼び出すんじゃなくて、内側で「保存する」というインターフェース、これをポートと呼ぶんですが、そのポートを定義する。
- 水野 ゆい
ポートが窓口みたいなイメージ?
- 桐山 しゅん
そうです。「こういうことをやってほしい」という窓口を内側が定義して、外側のデータベース実装がそれに合わせに行く。これをアダプターと呼んで、ポートとアダプターで一対になってる。
- 水野 ゆい
内側が「こういう形で頼む」って言って、外側がそれに従う、みたいな。なんかReactのカスタムフックで内部処理を隠蔽して、コンポーネントはそのフックのインターフェースだけ知ってればいい、みたいな感覚に近いかも。
- 桐山 しゅん
あー、それ近いかもしれない。コンポーネントがフックの中身を知らなくていい、という構造は確かに似てますね。
- 水野 ゆい
だから依存の矢印は外側から内側に向いてるんですね。内側はデータベースの存在を知らない。
- 桐山 しゅん
そうそう。それが「依存性逆転の原則」ってやつで、上位の方針、つまり重要なビジネスルールが、下位の詳細に依存しないように、詳細側がインターフェースに合わせる考え方。依存の方向をひっくり返すから「逆転」なんです。
- 水野 ゆい
名前の意味がやっとわかった気がします。ひっくり返す、か。
- 桐山 しゅん
これを守れてないと何が起きるかというと、ユースケースにSQLを直書きしちゃうんですよ。
- 水野 ゆい
あー、やりがちそう。「ここだけだから」って書き始めるやつ。
- 桐山 しゅん
やりがちなんですよ。で、そうなるとテストで本物のデータベースが必要になって、起動に3分から5分かかって、テストが不安定でたまに落ちる、みたいな状態になる。
- 水野 ゆい
CIが赤くなるやつ。あれ精神的につらいんですよね。「また落ちてる、自分のせいじゃないと思うけどなー」ってなる。
- 桐山 しゅん
つらいですよね。ポートとアダプターが分かれてれば、テスト用のダミーアダプターを差し込めるから、データベースなしで一瞬でテストが通るんです。
- 水野 ゆい
それは確かに嬉しい。あと、外部サービスが増えてきたときの話もしてほしくて。決済とかメール送信とか。
- 桐山 しゅん
それもまさに同じ問題で、メール送信のSDKや決済SDKの型や例外がユースケースに直接漏れてくると、業務ルールのコードが読めなくなるんですよね。
- 水野 ゆい
SDKの都合がビジネスロジックに混じってくる感じ。フロントでもサードパーティのライブラリをコンポーネントに直接呼び出してて、ライブラリ変えたら全部書き直しになった経験があって、それと同じ匂いがする。
- 桐山 しゅん
まさにそれです。だからメール送信も「メールを送る」というポートを内側で定義して、SDKの実装はアダプター側に閉じ込める。
- 水野 ゆい
ちょっと待って、それって全部インターフェースにするってこと?全部抽象化するの?
- 桐山 しゅん
これもよくある誤解で、全部インターフェースを増やせばいいわけじゃないんですよ。
- 水野 ゆい
あ、違うんですね。
- 桐山 しゅん
抽象化の目的は「変化しやすい詳細を差し替えられるようにする」こと。差し替えない部分まで抽象化すると、読みにくさと実装コストだけ増える。
- 水野 ゆい
抽象化のしすぎもよくないのか。過剰設計ってやつですね。前に「将来のために」って全部抽象化したら、誰も読めないコードになったって話を聞いたことがあります。
- 桐山 しゅん
あるあるです。「これ本当に変わる?差し替えたい?」って問いに答えられるものだけインターフェースにするのが現実的ですね。
- 水野 ゆい
じゃあ実務でどう判断するかが大事になってくるんですね。
- 桐山 しゅん
今日できる一歩として、「データベースに保存する」「メールを送る」をユースケースに直書きしてるところを1個だけ選んで、「やりたいことの窓口」を内側で定義して、外側で実装する形に置き換えてみる。それだけでもかなり変わります。
- 水野 ゆい
1個だけ、というのが大事ですよね。全部やろうとすると手が止まる。
- 桐山 しゅん
そうなんですよ。じゃあユースケースの入出力の話もしておきますか。
- 水野 ゆい
お願いします。
- 桐山 しゅん
ユースケースの入出力って、フレームワーク由来の型をそのまま受け取らない形にするのが基本で。
- 水野 ゆい
フレームワーク由来の型って、たとえば?
- 桐山 しゅん
Webのリクエストオブジェクトとか、セッション情報とか。それをユースケースが直接受け取ってると、同じユースケースをバッチ処理から呼びたいときに詰む。
- 水野 ゆい
あー、バッチにはリクエストオブジェクトなんてないから、ダミーを入れないといけなくなる。
- 桐山 しゅん
まさにその状態になってるプロジェクト、わりとあるんですよ。Webのリクエストやセッション前提の引数になってて、バッチ側はダミー値を入れないと動かないみたいな。
- 水野 ゆい
それはひどい。気づかずにやりそう。最初は「Webからしか呼ばないから」って思ってるんだろうな。
- 桐山 しゅん
そう、最初はそうなんですよ。だから入出力は文字とか数値とか配列みたいなプリミティブな型か、小さなデータ構造に寄せると、ユースケースがどこからでも呼べるようになるんですよ。
- 水野 ゆい
ユースケースが再利用できるようになるんですね。Reactでも、コンポーネントに渡すpropsをシンプルな型にしておくと使いまわしやすくなる、みたいな感覚と近い気がする。
- 桐山 しゅん
それ近いですね。ユースケースは「アプリの目的を達成する手順」に集中して、入出力の調整とかSDKの癖みたいな細かい手続きはアダプター側に寄せる。
- 水野 ゆい
ユースケースは何でもやっていいサービスクラスじゃない、ということか。
- 桐山 しゅん
そこ大事です。サービスクラスって名前でなんでも詰め込まれてるのよく見るんですよね。
- 水野 ゆい
わかる。気づいたら肥大化してる。うちのフロントでも、カスタムフックが「とりあえずここに書いとけ」の場所になってることあるんですよ。
- 桐山 しゅん
あー、それも同じ構造の問題ですよ。じゃあ最後のテーマに行きましょうか。Clean Architectureっていつ導入するの、小さいプロダクトでも最初から必要なの、って話。
- 水野 ゆい
これ気になってた。最初からやろうとすると重くない?スタートアップとか、スピード優先の現場だと特に。
- 桐山 しゅん
重いですよ。だから「全適用」より「局所導入」が強い、というのが僕の考えで。
- 水野 ゆい
局所導入か。
- 桐山 しゅん
重要なユースケースを1個だけ選んで、そこをテスト可能な形にする。そこから始めるのが現実的です。
- 水野 ゆい
重要なユースケースって、どう選ぶんですか。
- 桐山 しゅん
変更頻度が高いもの、または将来変わることがわかってるもの。「割引ルールが変わる可能性がある」とか「新しいUIが追加される」とか。
- 水野 ゆい
ビジネス的に核心に近い部分から、みたいなイメージ。
- 桐山 しゅん
そうです。さっきの「注文確定」みたいな処理がコントローラーにベタ書きされてて、割引ルールを追加するだけで10ファイル以上に影響が出た話、あれを防ぐためにまずそこだけ整理する。
- 水野 ゆい
全部一気に直そうとしない。
- 桐山 しゅん
そう。一気にやろうとして途中で挫折するのが一番もったいないんですよ。
- 水野 ゆい
あと、エンティティの話も聞いておきたくて。エンティティってデータベースのテーブルと1対1じゃないの?
- 桐山 しゅん
これよくある誤解で、エンティティはデータベースのテーブルじゃなくて、業務上の概念なんですよ。ビジネスルールを持つもの。
- 水野 ゆい
テーブルの形に引きずられちゃうと、データベースの変更がそのまま中核を壊すのか。
- 桐山 しゅん
そうなんです。テーブル都合でエンティティの形を決めると、データベースのスキーマが変わったときに業務ルールのコードまで変えないといけなくなる。
- 水野 ゆい
中心が汚染される感じ。フロントで言うと、APIのレスポンス形式に合わせてコンポーネントの型を作ってると、APIが変わるたびにコンポーネント側も全部変えないといけなくなる、あれと同じ構造ですね。
- 桐山 しゅん
まさに同じ構造です。だからエンティティは「この業務においてどういう概念か」から設計して、テーブルへのマッピングは外側のアダプターが担当する。
- 水野 ゆい
テーブルとエンティティは別物として設計する、か。最初は違和感ありそうだけど、慣れると強そう。
- 桐山 しゅん
最初は確かに違和感あります。でも一度やると「あー、こういうことか」ってなる。
- 水野 ゆい
今日できる一歩として、何をすればいいですか。
- 桐山 しゅん
テストを1本だけ改善するのがおすすめで。データベースや外部APIなしで動くユースケースの自動テストを1本作ってみる。実行時間と安定性を体感すると、「これが守られてる状態か」ってわかるので。
- 水野 ゆい
体感が大事なんですね。頭でわかるより。
- 桐山 しゅん
そう。速く動いて落ちないテストを1本体験すると、設計の意味が腹落ちする。
- 水野 ゆい
私もフロントで試してみようかな。APIレスポンスの整形処理をコンポーネントから剥がして、変換層を1箇所に集めるのを1画面だけやってみる。
- 桐山 しゅん
それ、まさに今日の話の実践ですよ。ゆいのケースだと、さっきの5ファイル修正問題がかなり解消されると思う。
- 水野 ゆい
やってみます。
- 桐山 しゅん
今日の話をまとめると、Clean Architectureは層そのものより、中心にある業務ルールを守るための「依存の向き」のルールが本質。内側でポートを定義して、外側の詳細が合わせに行くと、変更とテストがラクになる。
- 水野 ゆい
フォルダ分けだけじゃダメで、依存の向きが大事、ということですね。
- 桐山 しゅん
そうです。あと、全部一気にやらなくていい。まず変わりやすい詳細が中核に漏れてないか棚卸しして、1ユースケースだけデータベースなしでテストできる形にしてみる。
- 水野 ゆい
聞いてて、バックエンドの話だと思ってたけど、フロントにも普通に使える考え方だとわかりました。コンポーネント設計と発想がつながってる部分があって、それがわかったのが今日一番の収穫かも。
- 桐山 しゅん
それ言ってもらえてよかった。「フロントには関係ない」って思われがちなんですよね、Clean Architecture。
- 水野 ゆい
最初の私がそうでした。
- 桐山 しゅん
発想は共通で、実装の粒度や層の切り方はそれぞれの文脈に合わせる、というのが大事なポイントですね。
- 水野 ゆい
今日の話、聞いてくれているみなさんはどうでしたか。「自分のプロジェクトでこういう状態になってる」とか「試してみた」とか、ぜひコメントや感想を送ってほしいです。
- 桐山 しゅん
概要欄にお便りフォームのリンクを載せているので、ぜひ使ってください。「こういうテーマ聞きたい」というリクエストも大歓迎です。
- 水野 ゆい
番組が気に入ったら、フォローと高評価もよろしくお願いします。続けるモチベーションになります。
- 桐山 しゅん
次回はゆいがリードで、フロントエンドのテーマを話してもらう予定です。
- 水野 ゆい
何にしようかまだ悩んでるんですけど、状態管理まわりの話にしようかなと思っています。ReduxとかZustandとか、どう使い分けるかみたいな。
- 桐山 しゅん
それ聞きたい。フロント側の設計の話、楽しみにしてます。
- 水野 ゆい
では、また次回お会いしましょう。
- 桐山 しゅん
またねー、バイバイ。
- 水野 ゆい
またねー。
こちらのエピソードもおすすめ

ゆるふわプログラミングラジオ
フロントエンドの状態管理ライブラリについて深掘りします。ReduxとかZustand、Jotaiとか、どう使い分ければいいのかを解説します。
