以下の内容はhttps://aizack.hatenablog.com/entry/2025/09/02/191604より取得しました。


ポートフォリオのリファクタリング〜Controller肥大化をRepositoryパターンで解消を目指す〜

1. はじめに

現在、データエンジニアやそれに類するデータ基盤関連のお仕事を目指してポートフォリオを作成しています。
その制作過程でぶつかった設計の失敗とリファクタリングについて今回はまとめていきたいと思います。 自分の技術・知識不足を晒すことになり恥ずかしい限りですが、ご容赦ください。

前提となるポートフォリオについては以下の記事を参照ください。

aizack.hatenablog.com

2. Controller層の肥大化の原因

原因は、Controller層にDB操作、トランザクション、そしてビジネスロジックも全て実装していたことです。

MVCパターンを「ViewにUI、ModelにDBモデル、残りは全てController」という形で私は解釈していたため、以下のような処理を全てControllerに詰め込んでいました。

  • データ取得のためのAPI呼び出し
  • APIから取得したCSVデータのダウンロード
  • CSVデータをDataFrameに変換
  • 変換したデータを加工し、分析可能な形に整形

結果、Contorollerが複雑になり、可読性やテスト性が低下していました。

【追記】2025.09.03 そもそもの上記MVCパターンの理解が間違っていたことが発覚しました… Modelを DB接続担当 という雑な理解をしていた結果、Contorollerが肥大化していたようです… 設計の基礎・基本から学び直す良い機会になりました。

以下、引用元はRECRUITさんの新卒研修資料の「実践アプリケーション設計①データモデルとドメインモデル」です。

モデル (Model) ビジネスロジックやデータ処理を担当(p.20)

speakerdeck.com

3. 問題発覚の経緯

この設計ミスに気がついたのはGemini CLIポートフォリオの機能拡張について相談したときです。

現在の設計の問題点を、以下のようにフィードバックされました。

  • Controller層に責務を渡しすぎている
  • Controllerから責務を分離し、テスト容易性が高まる疎結合な設計に変更すべき
  • Repositoryパターンというデザインパターンを利用することで責務を以下のように分離できる

このフィードバックから自身の実装がContollerの肥大化という設計上のアンチパターンになっていることを把握しました。 この経験から、Controller層、Service層、Repository層の正しい責務について学び直すことにしました。


以下、実際のContorollerのコードです。API呼び出しと取得したデータの加工ロジックが同居しています。 この記事では以下のような私の設計に対する間違った理解を正し、戒めるために書いています。

  • API呼び出し

  • データの標準化加工


3-1. Contorollerの責務

  • 責務: ユーザーからの入力をServiceに渡し、Serviceからの出力をユーザーに応答する。
  • 関心事: HTTP、リクエスト、レスポンス。
  • 意識しないこと: ビジネスルール、DB。

上記の整理から、ControllerはDBやテーブルの存在を意識することないこと。Serviceから受け取ったData ObjectやDataFrameをView(UI)にわたすだけで十分であることを理解しました。

3-2. Service層の責務

これまでのControllerが行っていた分析の準備やトランザクションを移植する必要があると理解しました。

ここで重要なのは、ビジネスロジックという概念です。 私は当初、これを単なる「複雑な計算」だと考えていましたが、そうではありませんでした。

「プレゼンテーションでもデータアクセスでもない部分がビジネスロジック

私のポートフォリオで言えば、「財務データを登録する」というユースケースがこれにあたります。このユースケースを完遂するには、DBに対して「会社情報を登録」「財務諸表のマスターデータを登録」「財務レポートの数値を登録」という一連の処理が必要です。このように、複数のRepositoryを組み合わせて一貫した業務処理を完成させるのが、Service層の役割です。

3-3. Repository層の責務

  • 責務: データの永続化(CRUD操作)。
  • 関心事: モデルオブジェクトとDBテーブルのマッピング、クエリ。
  • 意識しないこと: ビジネスルール、トランザクションの範囲。

ここが今回の一番重要なポイントです。これまでContoroller層の中心機能として考えていたCRUDをこちらに移植します。 これにより、ControllerやServiceは「データを保存して」「データを取得して」とRepositoryに依頼するだけで済み、データベースの具体的な実装(SQL文)などを知る必要がなくなります。

4. まとめ

今回のリファクタリングを通じて、私は「設計パターンは、その真の意図を理解して使うべき」という大きな教訓を得ました。

  • Controller: ユーザーの入力窓口に徹する。
  • Service: ビジネスロジックを担い、アプリケーションのユースケースを定義する。
  • Repository: データ永続化の抽象化に特化し、DBの実装に依存しない。

自分の失敗を公開するのは恥ずかしいことですが、この経験が、同じような問題に直面している誰かの助けになれば幸いです。




以上の内容はhttps://aizack.hatenablog.com/entry/2025/09/02/191604より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14