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

# 0.はじめに
こんにちは！KIYO Learningでスタディングの開発をしている @gawa32 です！

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

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3996813/cbfa1f62-0b21-422f-b054-8a35004ccc97.png" width=50%>

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

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

しかし、現実の開発現場ではどうでしょうか？
* 「まずは動くものを優先しよう」
* 「1画面だけだし、ここに全部書いちゃえ」
* 「急ぎの対応だから、後でリファクタリングしよう（←されない）」

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

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

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

```php
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は呼び出しだけに専念します。
```php
class UserController extends AbstractController
{
    public function register(Request $request)
    {
        $this->userService->register(
            $request->get('name'),
            $request->get('email')
        );

        return new JsonResponse(['message' => 'OK']);
    }
}
```
```php
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をスリムに保てる
* 再利用性を考えるなら、バリデーションクラスに切り出すのも選択肢


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

https://kiyo-learning.com/

### プロダクト

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

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

https://www.wantedly.com/companies/kiyo-learning/projects

https://herp.careers/v1/kiyolearning