😄

Railsにおけるモジュール設計

2024/12/31に公開

プロジェクトが大きくなるにつれてコードの重複や責務の分散が課題になることがあります。それらを解決するためにモジュールを活用することは効果的です。

モジュールとは?

Rubyのモジュールは、名前空間の整理やコードの再利用を目的としたツールです。以下のように利用します。

module Payment
  class StripeService
    def process
      # Stripeによる支払い処理
    end
  end
end

上記のように名前空間を整理しすることで役割が明確化し、複数のモデルやクラスで同じ処理を必要とする場合にモジュールを利用できます。

再利用可能なモジュールの設計

モジュールを使う際は単一責任の原則を守ることが重要です。一つのモジュールが複数の責務を持つとメンテナンスが難しくなります。

例: ユーザー通知をモジュール化

module Notifiable
  def send_notification(message)
    NotificationService.send(user: self, message: message)
  end
end

class User < ApplicationRecord
  include Notifiable
end

user = User.first
user.send_notification("こんにちは!")

ActiveSupport::Concernの活用

Concernを使うと、インスタンスメソッドとクラスメソッドを整理しやすくなります。

下記の例ではincludedブロックでスコープを定義し、クラスメソッドをclass_methodsで追加しています。

module Archivable
  extend ActiveSupport::Concern

  included do
    scope :archived, -> { where(archived: true) }
  end

  def archive
    update(archived: true)
  end

  class_methods do
    def bulk_archive(ids)
      where(id: ids).update_all(archived: true)
    end
  end
end

class Post < ApplicationRecord
  include Archivable
end

Post.archived  # アーカイブ済みの投稿を取得
Post.bulk_archive([1, 2, 3])  # 複数の投稿を一括アーカイブ

モジュール設計のアンチパターン

何でもモジュール化しすぎる
モジュールが増えすぎると責務が不明確になります。例えば、以下のような肥大化したモジュールは注意が必要です。

module UserHelper
  def send_email
    # メール送信処理
  end

  def calculate_age
    # 年齢計算処理
  end

  def archive_user
    # ユーザーアーカイブ処理
  end
end

まとめ

  • モジュールはコードの再利用や名前空間の整理に効果的
  • 単一責任の原則を守り、必要に応じてActiveSupport::Concernを活用する
  • モジュール設計では責務を明確化し、依存関係を最小限に抑えることが重要

Discussion