/note/tech

UseCaseレイヤーって要るの?

要約:

■ 1. 問題提起と背景

  • レイヤリングへの疑問:
    • Controller -> UseCase -> Domainsというドメイン駆動なレイヤリングに対して本当にUseCaseは必要なのかという問いに向き合う
    • どちらもロジックを持ち得るレイヤーでどう棲み分けするのが良いのか
  • 以前のアーキテクチャ:
    • MVCというレイヤー分けをしてそれ以外にレイヤーを増やさないという誤ったRails Wayへの則り方だった
    • 前任者の当時の判断は環境や状況にあったものだったかもしれないので悪いことだとは思っていない
  • アーキテクチャの修正:
    • CQRSの考え方を導入しレイヤーを一枚増やした
    • controllerがdomainsに依存する構成に修正した

■ 2. 新たな課題の発生

  • domainsの依存問題:
    • domainsがdomainsに依存してしまう状況が発生した
    • 複雑なロジックを共通化するにあたりdomainsがdomainsを呼び出す箇所が生まれた
    • ロジックを書く場所がdomainsもしくはmodelsしか現状無いため
    • 依存させたくないdomainsが依存を持ってしまうことになりアーキテクチャの破綻になってしまう
  • UseCaseの必要性への疑問:
    • UseCaseはやはり必要なのではないかという考えが生まれた
    • しかしUseCaseを挟んだところで今Controller -> Domainsでうまくいっている箇所においてはただdomainsを呼ぶだけのUseCaseができる
    • あまりにそういうのが増えて冗長なのではないかという疑問が生まれた

■ 3. DomainsとUseCaseの役割

  • Domainsの役割:
    • 主な役割はビジネスロジックの実装
    • 操作するものはDomainsオブジェクト
    • ビジネスルールはドメイン固有のルールを実装する
  • UseCaseの役割:
    • 主な役割はユースケースの実装
    • 操作するものはDomainsクラス
    • ビジネスルールはユースケースに沿った手順を実装する
  • 本質的な違い:
    • DomainsとUseCaseは全く異なるもの
    • Domainsはサービスを展開するビジネス上におけるドメイン知識を含む
    • Domainsがアプリケーションの知識を持つ必要は全く無い
    • Domainsのコードそのものがドメイン知識を持つドキュメントとしても在るべき
    • UseCaseはドメイン知識を纏ったDomainsをユーザーストーリーにあったユースケースの手順に合わせて実装されるもの
    • UseCaseがドメイン知識を知る必要はなくユースケースにあったDomainsを利用するだけで良い
    • だいぶ抽象化されたドメインという概念を扱うだけの裏の苦労を知らないお客さん的なイメージ

■ 4. UseCaseの必要性の検討

  • 現状の構成:
    • ControllerがDomainsに直接依存しているアプリケーションという状況
    • UseCaseの導入による弊害もある
  • UseCaseの弊害:
    • Controller -> Domainsでうまくいっている箇所においてはただdomainsを呼ぶだけのUseCaseができてしまう
    • 呼ばれたらdomainsを呼び出すだけという冗長なクラスが増えていってしまう
  • 段階的導入の困難さ:
    • 全体にUseCaseを挟むというルールにするにはエンドポイント数的にも不可能なので段階的にはなる
    • そもそもUseCaseはoptionでいいんじゃないかという疑問が生まれた
  • 相談結果:
    • 冗長なUseCaseは増やさずとも良い
    • Controllerから直接Domainsに依存したところで問題はない気がする
    • もし他の手続きが必要になったならUseCaseを挟むのはそこまで大変な作業ではない

■ 5. まとめ

  • UseCaseの必要性:
    • UseCaseがなくても問題はない
  • 役割の明確化の重要性:
    • Domainsにはドメインとなるロジックを抽出する
    • UseCaseはユースケースを実現するためのドメインを利用した手続きを書く
    • それぞれの役割を明確に意識することが重要
    • これはもちろんアプリケーションの実装ルール次第
    • それぞれの役割を明確に意識することでUseCaseにドメインロジックが生まれるなどの破綻を回避することができる

MEMO: