helper/decorator/serviceについてまとめてみた

# はじめに
helperは、viewの冗長化を防いだり、コードの再利用性を高めるために使用します。
この後、説明するdecoratorもviewの改善に役立つので、何となく似ていますが、

helperはあくまでも「viewに依存している」ものです。
一方で、decoratorはモデルに依存します。

とりあえず、helperから見ていきましょう。

# helper

まず、大切なことはhelperはmoduleです。クラスだと勘違いしている人がいるみたいなので注意しましょう。で、適当なhelperファイルをhelpersディレクトリ配下に作成し、以下のように独自のヘルパーを定義していきます。

```helpers/user_helper.rb
module UserHelper
    def hello(name)
        "こんにちは! #{name}さん。"
    end

    def full_name
        self.last_name + " " + self.first_name
    end
end
```
基本的にはhelperはどのビューからでも呼び出すことができます。裏を返せば、helperに同じ名前で定義するとどれが呼び出されるか分からないので、要注意です。

例えば、以下のようにビューで書くと

```test.html.erb
<%= hello("太郎") %>
<%= @user.full_name %>
```
以下のようにビューで表示されます。
```
こんにちは! 太郎さん。
太郎田中
```

# decorator
helperが分かったところで、次はdecoratorです。

これは"draper"というgemをインストールする必要があります。
1.'draper'をインストール
```
# Gemfile
gem 'draper'
```
で、bundle installしましょう。

2.デコレーターを作成
```
$ rails ge decorator User
```

今回はフルネームを呼び出すメソッドを作っていきます。

```app/decorators/user_decorator.rb

class UserDecorator < Draper::Decorator
  delegate_all

  def full_name
    "#{object.first_name} #{object.last_name}"
  end
end
```

例えば、Userモデルにfull_nameメソッドを定義するのではなく、
UserDecoratorを作成して以下のように実装することができます。

そして、ビューで以下のように使用することができます。
```app/views/users/show.html.erb
<h1><%= @user.decorate.full_name %></h1>
```

こうすることで、Userモデルにロジックを持たせずに、ビューで必要な情報を提供することができます。

:::note
ただし、decoratorを使用する場合は、新しいオブジェクトが生成されるため、パフォーマンスに少し影響が出る可能性があります。
:::


__ここでふと疑問が...__


「helperとdecoratorのどっちでも良くない？」と。

確かに、どちらも同じようなことをやっているので、どちらもいい気がします。
ただし、使い分けは冒頭でも伝えた通り、以下の通りです。

* __helperは「ビューに依存」__
* __decoratorは「モデルに依存」__

:::note info
個人の見解

helperはあくまでもビューでよく使われる繰り返し処理や条件分岐などの定義をするもので、モデルには依存させない方が良いです。その方がdecoratorとの境界線をひけるので、開発でも「どこに書いたらいいかな？」という疑問が生まれにくくなると思います。

例えば、今回、full_nameメソッドをhelperとdecoratorのどちらでも定義しましたが、このメソッドはモデルに依存しているので、decoratorに書くのが良いと個人的には思います。

また、helperはどこからでも呼び出せてしまうので、decoratorに書くことで、「このモデルのメソッドだよ！」と共通理解がしやすいかと思います。個人開発なら良いですが、チーム開発をしているとhelperの名前を被せないようにすることは無駄な労力です。

ただ、調べていると、結局のところチームや個人の方針によるところも大きいみたいなので、その運用方針に合わせていけば良いんじゃないかなと思いました。
:::

# service
続いては、Serviceについてです。
これまで見てきたように、helperとdecoratorはビューの補助的存在でした。
要は、ビューがぐちゃぐちゃになって読みづらい！という状況をなくすために、使用するわけですね。
（極論を言えばビューの中に全て書いてもいいわけです...）

一方で、このserviceはcontrollerの補助的存在と言えます。

主にControllerから呼び出されます。また、複数のモデルにまたがる処理を実行する必要がある場合や、外部APIを呼び出す必要がある場合にも使用されます。

書き方は以下の通りです。今回はUserServiceを作成してみました。
```app/services/user_service.rb
class UserService
  def initialize(param1, param2)
    @param1 = param1
    @param2 = param2
  end

  def execute
    # ビジネスロジックを実装
  end
end
```

で、このサービスをcontrollerで呼び出して使います。
```app/decorators/user_decorator.rb
class UserController < ApplicationController
  def create
    service = UserService.new(param1, param2)
    service.execute
    # リダイレクトなどの処理
  end
end
```

UserServiceに書いているロジックをcontrollerに直接書くとあまりにも酷いことになりそうですね...
ということで、controllerを補助するためにServiceを使いましょう。ということです。

調べてみると、以下のような書き方もするみたいですが、基本的にcontrollerでnewする方が多い感じがします。個人的にもわざわざ

```app/services/user_service.rb
class UserService
  class << self
    def call(param1, param2)
      new(param1, param2).execute
    end
  end

  def initialize(param1, param2)
    @param1 = param1
    @param2 = param2
  end

  def execute
     # ビジネスロジックを実装
  end
end
```

```app/decorators/user_decorator.rb
class UserController < ApplicationController
  def create
    service.call(param1, param2)
    # リダイレクトなどの処理
  end
end
```

次は、上記に絡んでくるconcernとjobについてまとめてみたいと思います！
何か修正等や改善等あればぜひ教えてください！