21
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

そのController、太ってませんか?Fat Controllerとは何かと解決法

Last updated at Posted at 2025-04-03

0.はじめに

こんにちは!KIYO Learningでスタディングの開発をしている @gawa32 です!

「MVCでControllerは薄くしましょう」――よく聞く言葉ですが、実際の開発現場ではどうでしょうか?
気がつけばDB処理や複雑な業務ロジック、さらには多くのバリデーションまでもが詰め込まれて、“だんだん太っていくコントローラ”が出来上がっている…そんな経験、ありませんか?

本記事では、そんな「Fat Controller(ファットコントローラ)」問題をPHPを用いた実例とともに掘り下げ、なぜ起きるのか・どう解決すればいいのかを解説します。

1. 序章:設計思想と現実のギャップ

アプリケーション開発を行う中で、誰しも一度は「MVC」という言葉を聞いたことがあると思います。
Model(モデル)、View(ビュー)、Controller(コントローラー)という役割に責任を分け、コードを整理しやすくする設計思想です。

理想的なMVCの世界では、Controllerはシンプルで、「リクエストを受け取り → Modelに処理を委譲 → Viewに結果を渡す」という流れを担います。つまり、Controllerは“薄く”あるべきというのが基本的な考え方です。

しかし、現実の開発現場ではどうでしょうか?

  • 「まずは動くものを優先しよう」
  • 「1画面だけだし、ここに全部書いちゃえ」
  • 「急ぎの対応だから、後でリファクタリングしよう(←されない)」

…そんな日々の積み重ねによって、Controllerはだんだんと肥大化していきます。
入力チェック、データの整形、条件分岐、例外処理、DBアクセスなど、
さまざまな処理が積み重なり、気がつけば「Controllerがほとんどの処理を担っている」ような状態に。

このような状態のControllerは、Fat Controller(太ったコントローラ) と呼ばれ、保守性・再利用性・テストのしやすさなど、様々な面で問題を引き起こします。

2. Fat Controllerとは?

Fat Controller(太ったコントローラ) とは、その名の通り「太りすぎたコントローラー」のことです。
本来、Controllerはリクエストとレスポンスの橋渡し役に徹するべきですが、現場では処理がどんどんControllerに集まりがちです。

class UserController extends AbstractController
{
    public function register(Request $request)
    {
        $user = new User();
        $user->setName($request->get('name'));
        $user->setEmail($request->get('email'));

        if (!filter_var($user->getEmail(), FILTER_VALIDATE_EMAIL)) {
            throw new \Exception('Invalid email');
        }

        if ($this->userRepository->exists($user->getEmail())) {
            throw new \Exception('Already exists');
        }

        $this->userRepository->save($user);

        return new JsonResponse(['message' => 'OK']);
    }
}

このControllerでは、リクエストの取得からオブジェクトの生成、入力チェック(バリデーション)、重複チェック、永続化、例外処理までをすべて担っています。
一見シンプルにも見えますが、処理が集中しすぎてしまうと、テストがしづらくなったり、保守性が低下しやすくなるといった課題も生まれてきます。

3. リファクタリングしてみる

この問題を解決するためには、「責務の分離」が重要です。
たとえば、業務ロジックは Service層 に切り出し、Controllerは呼び出しだけに専念します。

class UserController extends AbstractController
{
    public function register(Request $request)
    {
        $this->userService->register(
            $request->get('name'),
            $request->get('email')
        );

        return new JsonResponse(['message' => 'OK']);
    }
}
class UserService
{
    public function __construct(private UserRepository $userRepository)
    {
    }

    public function register(string $name, string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \Exception('Invalid email');
        }

        if ($this->userRepository->exists($email)) {
            throw new \Exception('Already exists');
        }

        $user = new User();
        $user->setName($name);
        $user->setEmail($email);

        $this->userRepository->save($user);
    }
}

これにより、Controllerは薄くなり、テスト・再利用・保守が格段にしやすくなります。

4. よくある悩みと対策

✔ どこまで分ければいいのか?
目安:

分けるべき処理 Controllerに残してもOK
DBチェック、業務ロジック パラメータ受け取り、バリデーション、レスポンス処理

✔ バリデーションの置き場所

バリデーションをどこに書くかは、チームの方針や設計思想によって分かれるポイントです。
以下はあくまで一例ですが、状況に応じて判断するのが良いと思います。

  • Controllerでまとめて書くと、入力とバリデーションの対応が見やすくなる
  • Serviceに書くことで、Controllerをスリムに保てる
  • 再利用性を考えるなら、バリデーションクラスに切り出すのも選択肢
class RegisterUserValidator
{
    public function validate(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \Exception('Invalid email');
        }
    }
}

✔ Serviceが肥大化してきたら?

  • 処理内容ごとにServiceを分割(例:UserService → UserRegistrationService)
  • 呼び出し口と処理本体を切り分けるのも有効

✔ 設計ルールはチームで決めよう

  • Controller何行超えたら分割?
  • Service名や設置場所どうする?
  • バリデーションの統一方針は?

設計は「チームの共通認識」があると迷いが減ります。

5. 現場でのバランス感覚

現実の現場では、すべてを理想通りに分離するのが難しい場面もあります。

  • 🔥 スピード重視:あとでリファクタしやすいようにだけしておく
  • 🧩 小規模ツール:無理に分離せず、将来的な再利用性で判断
  • 👥 メンバー構成:スキルや理解度に合わせて、段階的に分離
  • ✅ 設計方針の共有:チーム内で「どこまで分けるか」ルール化する

大事なのは完璧な設計ではなく、あとで育てやすいコードを書くことです。

6.まとめ

  • Fat Controllerは、設計思想と現実のギャップから生まれる
  • サービス層導入で責務を分離することで、保守性・テスト性が大きく改善
  • 設計は“バランス感覚”が大事。割り切るところは割り切ってOK
  • チームで方針を揃えることで、コードの品質とスピードが両立できる

「気づいたらControllerが太ってる…」というのは誰にでも起こり得ます。
だからこそ、少しずつでも責務の整理を意識していくことが大切です。

KIYOラーニング株式会社について

当社のビジョンは『世界一「学びやすく、分かりやすく、続けやすい」学習手段を提供する』ことです。革新的な教育サービスを作り成長させていく事で、オンライン教育分野でナンバーワンの存在となり、世界に展開していくことを目指しています。

プロダクト

  • スタディング:「学びやすく・わかりやすく・続けやすい」オンライン資格対策講座
  • スタディングキャリア:資格取得者の仕事探しやキャリア形成を支援する転職サービス
  • AirCourse:受け放題の動画研修がついたeラーニングシステム(LMS)

KIYOラーニング株式会社では一緒に働く仲間を募集しています

21
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?