9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】モジュール強度の視点で考える、Fat Modelを避ける責務の分離

9
Posted at

こんにちは。

基本情報技術者試験の範囲にもある「モジュール強度」ってこういうものなのかと整理できたので、記事にしたいと思います。

※Railsをメインに勉強をしているため、扱うコード例はRubyやRailsをベースにしています。

記事の内容に誤りがありましたら、コメントでご指摘いただけますと幸いです。

モジュール

まず、「モジュール強度」の「モジュール」ってなんのことでしょう。

Rubyの勉強をしていると、「モジュール」という用語がでてきます。
こんな風に定義するものです。

module モジュール名
  # モジュールの定義(メソッドや定数)
end

一方で、「モジュール強度」がいう「モジュール」は、もう少し広い意味をもっていて、
クラスやメソッドなど、ひとまとまりの機能単位(部品) のことをいいます。

モジュール強度

基本情報の参考書をみると、モジュール強度の説明はこんな感じです。

  • モジュール内の構成要素間の関連性の強さを示すもの
  • 強度は7種類あり、強度が強いほど、モジュールの独立性は高くなる
    (強度は、弱い順で以下のとおり)
強度 説明 特徴
暗号的強度 無関係な処理の寄せ集め 全く関連性がない
論理的強度 似た種類の処理をまとめたもの フラグで処理を切り替える
時間的強度 同じタイミングで実行する処理 初期化処理など
手順的強度 順番に実行する必要がある処理 ステップ1→2→3
連絡的強度 データを共有する処理 前の結果を次に渡す
情報的強度 同じデータを操作する処理 CRUD操作
機能的強度 単一の明確な目的を持つ処理 1つのことだけをする

初めて見たときは、「で、これがなに?」って思っていました。

いつかわかるときがくるだろうから、「モジュール強度は強い方がいい」とだけ覚えておこうと。

単一責任の原則

ここで、モジュール強度を理解するうえでの重要な考え方として、単一責任の原則を確認しておきます。

プログラムを設計するときの基本理念の一つに、単一責任の原則があります。

(基本理念とは、プログラムを書いていくときに、こういう考えをベースにしようねっていうものです。)

単一責任の原則は、
モジュール(メソッドやクラスなど)が、「たった一つの理由」で変更されるべきである。
という考え方です。

変更の理由が一つに絞られているモジュールは、何を責務としているのかが明確になり、その結果、コードの保守性や可読性が向上します。

逆に、変更の理由が複数あるモジュールは、責務が曖昧になりやすく、保守性や可読性が低下します。

モジュール強度と単一責任の原則の関係

では、モジュール強度と単一責任の原則はどう関係しているのでしょうか。
 

モジュール強度が高い場合

モジュール内の処理が"強く"関連
    ↓
モジュールは「ひとつのこと」をしている
    ↓
責務が明確で、変更の理由が一つ
    ↓
単一責任の原則に従っている

モジュール強度が低い場合

モジュール内の処理が"弱く"関連
    ↓
モジュールは「複数のこと」をしている(何をしているかはっきり言えない)
    ↓
責務が曖昧で、変更理由が複数
    ↓
単一責任の原則から逸れている

つまり、モジュール強度が低い = 責務が曖昧 = 単一責任の原則から逸れている ということができます。


ここまで、モジュール強度と単一責任の原則について、一般的な説明をしてきました。

では、実際の開発では、どのようにモジュール強度が低くなってしまうのでしょうか。
Railsアプリの開発コードを例に見ていきます。

Fat Model

Railsは、MVCパターンを採用していて、それぞれが役割を持っています。

たとえばモデルは、扱うリソース(UserやArticleなど)のルールやロジックを担っています。

単一責任の原則からいうと、Userモデル(user.rb)が変更されるときの理由は、
「Userのルールやロジックに関すること」であるべきです。

しかし開発していくと、
「とりあえず定義したメソッド」、
「ビューで表示するためのメソッド」など、
本来のモデルの役割とは違うメソッドも増えていってしまいます。

その状態が、Fat Modelです。
 

では、「どれくらいFatなのか」を客観的に判断するにはどうすればよいでしょうか。

そこで使えるのがモジュール強度です。

モジュール強度は、モジュール内の処理同士の関連性を評価する指標です。
強度が弱いほど、「関係の薄い処理が寄せ集められている」状態を意味します。

つまり、モジュール強度が弱い = Fat Model の可能性があると判断できるわけです。

モジュール強度が弱いコード例

モジュール強度が弱い状態のモデルを見てみます。

※イメージをつかむ例としてわかりやすくするためにコードの量は少なくしています。

user.rb
class User < ApplicationRecord
  
  # 表示用ロジック
  def display_name
    nickname.presence || email
  end

  # 状態判定
  def active?
    deleted_at.nil?
  end

  # 表示用ロジック
  def welcome_message
    "ようこそ、#{display_name}さん"
  end
  
end

これらは「Userに関する処理」という漠然とした共通点だけでまとめられており、処理同士の関連性は弱いです。

このような「似たような雰囲気」でまとめられた状態を、論理的強度といいます。
(2番目にモジュール強度が弱い状態です。)

 
では、このUserモデルの何が問題なのでしょうか。

責務を一言で説明できない

こちらのUserモデルは、責務を一言で説明できません。

  • active?メソッドで、Userの状態を管理する
  • display_nameメソッドで、Userの表示名を決める
  • welcome_messageメソッドで、表示用の文言を生成する

「これら3つのメソッドが含まれる、Userモデルの責務は...。」

本来のUserモデルは、Userというリソースの状態やルールを表すものです。

 
表示に関するメソッドが増えてしまったことで、責務が曖昧となってしまいました。

「Userに関する処理」という、なんか似ているような雰囲気のある集まりになっています。

変更理由を考える

先ほどは「Userモデルの責務は何か」から見て、責務が曖昧になっていることがわかりました。

今度は、このモデルの変更理由を見てみます。

単一責任の原則からいえば、モジュールの変更理由はひとつであるべきでした。

しかし、表示に関する処理がUserモデルに含まれていることで、
「Userの状態・ルールの変更」だけでなく「表示の仕様変更」という異なる理由で、Userモデルが変更されることになります。

つまり、単一責任の原則がいう「変更の理由が一つ」から逸脱していることがわかります。

改善案

では、このUserモデルはどのような改善ができるでしょうか。
 

Userモデル
class User < ApplicationRecord
  # Userの状態判定のみを責務とする
  def active?
    deleted_at.nil?
  end
end
UserPresenter
class UserPresenter
  def initialize(user)
    @user = user
  end

  def display_name
    @user.nickname.presence || @user.email
  end

  def welcome_message
    "ようこそ、#{display_name}さん"
  end
end

このように分離することで、それぞれのモジュールが、明確な責務を持つようになりました。

分離したモジュールの責務と変更理由を整理すると、次のようになります。

Userモデル
責務:Userの状態やルールを管理
変更理由:Userのビジネスルールの変更
モジュール強度:機能的強度(高い)

UserPresenter
責務:Userの表示ロジック
変更理由:表示仕様の変更
モジュール強度:情報的強度〜機能的強度(高い)

おわりに

  • モジュールの責務を一言で説明できなくなったとき
  • モジュールの変更理由が複数思い浮かぶようになったとき

それは設計を見直すサインです。

意識して設計していても、開発が進むにつれて、責務が少しずつ曖昧になることは避けられません。

そのときに、
「なぜ分かりにくくなってきたのか」
「どのような理由で単一責任の原則から逸れているのか」
を整理するための視点が、モジュール強度です。

モジュール強度は、「コードの良い・悪いを決めるための絶対的なルール」ではありません。

しかし、モジュールの状態を客観的に説明するための共通言語として役立ちます。

モジュール強度を理解していると、
「なぜこのコードは分かりにくいのか」が言語化できて、
他の人とも共有しやすくなるんだろうなと思います(チーム開発は未経験なのでイメージですが)。

 
最後まで読んでいただき、ありがとうございました。

9
1
0

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
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?