関心の分離(Separation of Concerns)は、変更理由が異なるコードを混ぜないという設計原則です。
入力、業務判断、DB保存、画面表示、ログには別々の変更理由があります。1つの関数に詰め込むと、小さな仕様変更でも全体へ影響します。
混ざった例
async function createOrder(request: Request) {
const body = await request.json();
if (body.quantity < 1) throw new Error("Invalid quantity");
const total = body.price * body.quantity;
await db.query("INSERT INTO orders ...");
console.log("order created");
return new Response(JSON.stringify({ total }));
}
この関数はHTTP、入力検証、価格計算、DB、ログ、応答形式を同時に扱います。
変更理由で分ける

class PlaceOrder {
constructor(private readonly orders: OrderRepository) {}
async execute(input: PlaceOrderInput) {
const order = Order.place(input);
await this.orders.save(order);
return order;
}
}
ControllerはHTTPとの変換、Orderは業務ルール、Repositoryは永続化を担当します。DB変更はRepository、価格ルール変更はDomainへ閉じ込めやすくなります。
凝集度と結合度
- 凝集度: 同じ目的の処理が1か所へまとまっている度合い
- 結合度: ある部品が別の部品の詳細へ依存する度合い
良い分離は、同じ変更理由をまとめて凝集度を高め、明示的なinterfaceで結合度を下げます。ファイルを分けても、互いの内部状態へ直接触れていれば分離できていません。
分けすぎを避ける
1行ごとに関数やclassを作ることが目的ではありません。分割しすぎると、処理を追うために多くのファイルを移動することになります。
次の質問で境界を探します。
- このコードは何のために変わるか
- 一緒に変わる処理はまとまっているか
- 別の理由で変わる処理が混ざっていないか
- 境界を越える値と依存関係が明確か
- 分割によって変更やテストが実際に簡単になるか
重複コードがあるだけで、すぐ共通化もしません。見た目が同じでも変更理由が異なる処理をまとめると、片方の変更がもう片方を壊します。
まとめ
- 関心とはコードの目的や変更理由
- 変更理由が異なる処理を境界で分ける
- 同じ目的をまとめ、内部詳細への依存を減らす
- ファイル数ではなく、変更とテストが局所化したかで判断する
- 分けすぎや早すぎる共通化も避ける
層として分ける例はレイヤードアーキテクチャ、依存方向まで含む構成はクリーンアーキテクチャを参照してください。