はじめに

多層アーキテクチャ(Layered Architecture)は、機能の関心ごとを層ごとに分離することで、変更に強く再利用しやすい設計を実現する手法である。
MVCやDDD、クリーンアーキテクチャなどはその代表的な応用例だ。

しかし、実際の現場ではこの層の責務が曖昧になり、コードの属人化や保守困難性を招く事例が後を絶たない。

レビューアーはこのような構造に対し、機能コードではなくアーキテクチャ的責務配置の妥当性を評価する立場にある。
本稿では、その際に用いる視点・指摘方法・典型的な失敗パターンを明確にする。

層構造の役割を再確認する

まず基本的な構造と役割を押さえておく。以下は典型的な3層構造(Controller / UseCase / Repository)をモデル化したものだ。

UML Diagram

各層の責務は次のように定義される。

主な責務
Controller層 リクエストの受信と入力バリデーション
UseCase層 業務ロジック(アプリケーションの振る舞い)
Repository層 DB・外部APIアクセスなどの永続化処理

この役割分担を崩さないことが、構造保守性の鍵となる。

典型的な責務混在パターンとレビュー観点

Controller肥大化:ユースケースが侵食される構造

Controller内に複雑なビジネスロジックが記述されている場合、それはユースケース層が設計上存在していても機能的に不在であることを意味する。

悪い例:ロジックがControllerに集中
def register_user():
    data = request.json
    if not validate_email(data['email']):
        return {"error": "Invalid email"}, 400
    hashed = hash_password(data['password'])
    db.insert_user(data['name'], data['email'], hashed)
    return {"status": "ok"}, 201
コントローラ責務逸脱
@Reviewer: 入力検証・ハッシュ化・DB登録と、複数の責務が1関数に混在しています。ユースケース層への分離が必要です。

レビュー視点:

  • DBや暗号処理など、アプリケーション全体で再利用可能なロジックがControllerに直書きされていないか?
  • Controllerが複数の関心事を持ち始めていないか?

UseCase層の中立性喪失:ドメインを持たないサービスの乱立

UseCase層がただのServiceクラスの集合になり、ロジックを受け渡すだけのパイプと化している構造も危険である。
本来この層は「なぜその処理をするか」「どんな条件で失敗するか」といった業務上の振る舞い判断を行う責任がある。

単なる転送
class UserService:
    def create_user(self, data):
        return self.repo.save(data)
ユースケース機能喪失
@Reviewer: 本クラスはデータ転送に終始しており、ユースケース層の判断責務が存在していません。エラー条件やルール処理を定義すべき箇所です。

レビュー視点:

  • ユースケースが単なるCRUD操作の中継点になっていないか?
  • 処理の判断(バリデーション、条件分岐、例外補足)は適切にここで担われているか?

Repository越境:外部アクセスロジックの漏れ

Repository層が担うべき外部データ取得や永続化処理が、ユースケース層やControllerに無意識に分散して記述されているケースも多い。

API呼び出しがUseCaseに漏れている例
class RegisterUserUseCase:
    def execute(self, data):
        user = create_user_entity(data)
        if not check_blacklist(user.email):  # 外部API呼び出し
            raise ValueError("Blocked")
        self.repo.save(user)
外部I/O責務漏れ
@Reviewer: ブラックリストチェックは外部システム依存であり、RepositoryまたはGateway層での実装が適切です。

レビュー視点:

  • I/O処理(DB・API・メール送信など)が責務を越えて書かれていないか?
  • ユースケース層に「知っているべきでない技術的詳細」が混入していないか?

層の分離が破綻する原因と背景

責務の混在は偶発的に起こるのではなく、以下のような開発文脈の中で発生しやすい。

  • 開発初期にアーキテクチャ設計が明文化されていない
  • ユースケースが形骸化し、単なるService呼び出し層となる
  • フレームワーク主導の構造に過剰依存している(Django, Railsなど)
  • レビュー時に層の役割まで踏み込んで議論されていない

設計ルールが共有されていない場合、どこに処理を置くべきかが属人判断になり、チームの構造的な品質が揺らぐ。

レビュー時に見るべき層構造チェック観点

レビュー観点リスト
  • Controllerがユースケースを通さず、直接DBやAPI呼び出ししていないか?
  • UseCaseにルール判断・状態管理・例外処理が書かれているか?
  • Repository層が単なるラッパーに終わらず、I/Oと抽象層をきちんと分離しているか?
  • 「層」の粒度が一定か?(層間でコード量や密度の極端な偏りはないか?)
  • 逆依存(ドメイン層がインフラ層に依存するなど)が混入していないか?

補助視点:ドメインの方向性と構造への介入度

レビューアーとしては、コード単体ではなく設計思想や責務配置の意図を感じ取る必要がある。
たとえば以下のような判断を行うことで、コードの「違和感」に論理的根拠を与えることができる。

  • この処理は「いつでも変わるもの」か、それとも「安定した業務仕様」か?
  • このコードは「ビジネス判断」か、それとも「技術的手段」か?
  • 今後他のユースケースでも使われる抽象か?

おわりに

多層アーキテクチャをレビューするとは、単に層の存在を確認することではない
それぞれの層に与えられた責務が守られているか、越境が発生していないか、設計意図が構造に宿っているかを読み取る行為である。

コードの中に設計図があるとは限らない。
レビューアーはその構造を読み解き、必要であれば設計そのものにフィードバックを返す視点を持つことが求められる。