【Ruby】未経験でエンジニアになって感じたスクール学習と実務の違い

こんにちは。
デザイン・システム室の以後です。
私はプログラミングスクールを経て、未経験でエンジニアになりました。

未経験者向けのスクールではRubyはよくある言語の一つだと思います。
私もRubyをスクールで学んでから入社しました。
そんな私が入社してから実務に携わり始めて感じたことを共有します。

特に現在Rubyを学習されていて、これから未経験でエンジニアを目指している方の参考になればと思います。


前提としまして、私は4ヶ月間のスクールでRuby on Railsのポートフォリオ作成まで行えるスクールに通っていました。

スクールでは、主にRuby on RailsのMVCフレームワークを使ってアプリを作る学習をしていました。
基本的な構造や条件分岐の方法などは感覚的にわかりやすく、Railsの文法に慣れることやアプリ作成の流れを学ぶことにはとても適していると感じます。

ですが、実務ではアプリを「作って終わり」ではありません。

  • 維持
  • 管理
  • 改修

これらを必要とします。

1番の違いは、完成がゴールではないということです。
未来を考えた設計をしなければならないということが、私が初めて実務を行う中で感じた未経験での学習時との違いです。

そのためにスクールで学んだ知識を前提として、スタンスを変える必要があると感じました。


FATコントローラーとは?

もちろんスクールと実務の違いはたくさんありますが、最初に感じたのはこの「FATコントローラー」の問題でした。

「FATコントローラー」とは、コントローラーに処理が集中しすぎて長く複雑になった状態を指します。
初学者がMVCで学ぶ段階では気づきにくい(私はそもそもFATコントローラーという概念すらスクール学習時には知りませんでした)ですが、実務においてコードが成長すると以下の問題が出ます。

  • テストがしにくい
    コントローラーはHTTPリクエスト・レスポンスを扱うため、テストを書くと複雑になりやすい。
  • 再利用性が低い
    同じ処理を別の箇所でも使いたくても、コントローラー内のコードでは呼び出せない。
  • 変更に弱い
    複数の処理が1箇所に混ざると、変更の影響範囲が大きくなる。

FATコントローラーの例

class OrdersController < ApplicationController
  def create
    # 注文作成
    @order = Order.new(order_params.merge(user: current_user))
    if @order.save
      # 在庫を減らす
      @order.items.each do |item|
        Inventory.decrease(item)
      end

      # ポイント付与
      RewardPoint.add_for_order(current_user, @order)

      # メール送信
      OrderMailer.confirmation_email(@order).deliver_later

      # 外部API連携
      ShippingService.create_shipment(@order)

      # 成功時リダイレクト
      redirect_to @order
    else
      # 失敗時は再表示
      render :new
    end
  rescue StandardError => e
    Rails.logger.error("注文作成に失敗しました: #{e.message}")
    redirect_to new_order_path, alert: "注文処理中にエラーが発生しました"
  end

  private

  def order_params
    params.require(:order).permit(:address, items_attributes: [:product_id, :quantity])
  end
end

上記コードは上から順に追っていくには読みやすいものだと思います。ですが、

  • 「注文作成」「在庫減少」「ポイント付与」「メール送信」「外部API連携」など、複数の処理が混ざっている
  • コントローラーが長く、読むだけでも大変

幾つものifが重なったコードの中の1部分を改修したいとなった時、

if X
 ①
elsif xxx
 ②
elsif xxxx
 ③
elsif xxxxx
 ④
else xxxxxx
 ⑤
end

上記のような分岐のコードが出来上がったとして、③だけ内容を変えたいとなった際にXを呼んでいる影響範囲が大きくなり改修難易度が格段にあがります。

また、1つのアクションでこれぐらいのボリュームになってしまいますが、これが1つのコントローラーにいくつも定義され、そのようなファイルが数十も格納された状態から、特定の動きを編集、修正することは容易ではありません。

ではどうすればいいのか。

サービスとは何か?

Railsでは「Service」という専用のフォルダを作って、コントローラーでもモデルでもない、ビジネスロジックをまとめる場所として使うことが多いです。

  • コントローラーは「受け取る・返す」だけ
  • モデルは「データの管理やバリデーション」だけ
  • 複雑な処理や複数モデルをまたぐ操作はサービスにまとめる

サービスに切り出すことで、テストしやすく、メソッドの再利用が簡単になります。


モデル・サービス・コントローラーの使い分け

要するに、MVCのCに書きがちなものを、MとS(サービス)フォルダにも分けて書けるということです。

役割書く内容の例
コントローラーリクエストを受け取ってレスポンスを返すパラメータ取得、サービス呼び出し、レンダリング
モデルデータやそのルールを扱うバリデーション、関連付け、単純な集計や計算
サービスビジネスロジック、複数モデルをまたぐ処理注文作成フロー、メール送信、外部API連携、トランザクション管理

FATコントローラーをモデルとサービスに切り分けた例

モデルに切り出す処理


class Order < ApplicationRecord
  has_many :items

  def decrease_inventory
    items.each { |item| Inventory.decrease(item) }
  end
end

サービスに切り出す処理

class CreateOrderService
  def initialize(user, order_params)
    @user = user
    @order_params = order_params
  end

  def call
    ActiveRecord::Base.transaction do
      order = Order.create!(@order_params.merge(user: @user))
      order.decrease_inventory
      RewardPointService.new(@user, order).apply_points
      OrderMailer.confirmation_email(order).deliver_later
      ShippingService.new(order).create_shipment
      order
    end
  end
end

コントローラーは呼ぶだけ

class OrdersController < ApplicationController
  def create
    @order = CreateOrderService.new(current_user, order_params).call
    if @order
      redirect_to @order
    else
      render :new, alert: "注文処理中にエラーが発生しました"
    end
  end

  private

  def order_params
    params.require(:order).permit(:address, items_attributes: [:product_id, :quantity])
  end
end

どうでしょう。内容は同じですが、3つのファイルに分けて記述できました。

先ほど簡易的に書いたコードで言うと、①〜⑤それぞれを別のメソッドX1、X2、X3、X4、X5のように名前をつけてバラバラにして保存しておけば良いということです。


こうすることで、ロジックに変更があった際の影響範囲がわかりやすくなったりと、維持・管理性が上がります。

しかし、これは一概に細かくすればいいというわけでもなく、正解はありません。
企業ごと、プロジェクトごとにそれぞれにあった粒度での記述が求められます。

答えがない以上、私も何が最適かを考える力を鍛え続けていく必要があると感じています。


まとめ

  • スクールと実務ではスタンスが違う
  • MVCだけで完結する作り方は、初学者にとって学びやすく、RubyやRailsの理解に役立つ
  • しかし、実務では維持・管理・改修を考えるとFATコントローラーは避けるべき
  • モデルとサービスに責務を切り分けることで、テストしやすく、再利用性も高い、見通しの将来性の高いコードになる
  • 答えがない問題である以上、思考力の鍛錬は続いていく





さいごに

現在デザイン・システム室では、新しいメンバーを募集しています。少しでも興味を持たれた方は、ぜひご応募ください✨💻
皆様からのご応募、心よりお待ちしております。