レビューで指摘されたリファクタリングベスト5【まだ短く・分かりやすくできる】

「このリファクタリングは思いつかなかった。。。 😲😲 」

# はじめに
こんにちは、[まつけん](https://twitter.com/matsuken_web314)です。渋谷の[サウナ道場](https://sauna-ikitai.com/saunas/78191)によくいます。
最近エンジニアになって、1年が経ちました。

実装で、手も足も出ないことが無くなってきて、成長を感じてます。
ですが、「もっと短く・分かりやすくできる」というリファクタリングの観点でレビューをもらうことが割とあります。
その中でも「これは、、、気づかなかった。あざます！」となるリファクタリングのベスト5を紹介します。


:::note info
この記事が参考になりそうな読者

- RubyのリファクタリングTipsを知りたい方
- エンジニア1年目がレビューで指摘されたリファクタリングを知りたい方
:::

※こちらの記事に出てくるコードに関しては全て`Ruby`です。実務で学んだことなので、出てくるコードは全てフィクションです。(実際のサービスのコードではないです)

#  【第5位】whereを2回以上使うときはこんな感じにできる

> ある条件をwhereを使って、2回絞り込んでた時

先輩「whereを2回使って絞り込みをしている箇所の、`.where(条件1).where(条件2)` のところは `.where(条件1, 条件2)` のように書けます。」
僕「and条件のリファクタリングはそういう感じでできるんですね、」

### 【Before】
whereメソッドを2回使っている状態。
```diff_ruby
-  query.where(name: 'Alice')
-      .where(detail: { age: 25 })
```
### 【After】
whereメソッドの使用を1回に抑えてます。
```diff_ruby
+ query.where(name: 'Alice', detail: { age: 25 })
```
### 理解の参考になる記事

https://www.sejuku.net/blog/13363

#  【第4位】ブロックを使う
>　each文を使ってたとき

先輩「ブロックの書き方を{}を使った書き方にすれば、より短くできるかもです！」
僕「`do～end`は、`{}` を使うことでスッキリ書くことができるんですね！勉強になります！」

### 【Before】

```diff_ruby
numbers = [1, 2, 3, 4, 5]

sum = 0
- numbers.each do |num|
-   sum += num
- end
```
### 【After】
`do~end`→`{}`に修正。3行が1行に。
余談ですが、ちょうどrubocopの「メソッドの行数多いねん！（`Method has too many lines.`）」というエラーに引っかかってたので、助かりました。
```diff_ruby
numbers = [1, 2, 3, 4, 5]

sum = 0
+ numbers.each { |num| sum += num }
```


### 理解の参考になる記事
https://qiita.com/suzu12/items/c1239c28a3b25335eb8c#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9



#  【第3位】早期リターン
> ある変数に値が入っているかどうかで条件分岐が発生する処理のレビュー

先輩「if文の条件を逆にして、`return default_response if some_type.nil?`とするとネストが深くならずに済みます。**早期リターン**という手法です」
僕「早期リターン？？」

### 【Before】
変数some_typeの中身によって、条件分岐させていました
```diff_ruby
- if some_type.present?
-   # 処理
- else
-   default_response
- end
```

### 【After】
こうすることで、以下のメリットがあります。
- 可読性の向上：階層が深くならず、かつ少ない行数で読みやすい
- パフォーマンスの向上：条件が`false`の場合、早期にリターンすることで、不要な処理をスキップできる
```diff_ruby
+ return default_response if some_type.nil?
+ # 処理
```
### 理解の参考になる記事
▼この記事が早期リターンについて、分かりやすく書かれてあります。
- 早期リターンを使うことで、ネストが深くならずに済むところがはっきりとわかります

https://zenn.dev/media_engine/articles/early_return#%E6%97%A9%E6%9C%9F%E3%83%AA%E3%82%BF%E3%83%BC%E3%83%B3%E3%81%AE%E4%BE%8B



#  【第2位】長い処理はメソッドにできないか

> 〜〜〜ある数値を超えると条件が切り替わる分岐を作ってた時〜〜〜

先輩「この条件分岐、`.min`使ったら1行にできると思います」
僕「1行？　それはやるべきですね。やり方ググります。」



### 【Before】
```diff_ruby
- if (ruby_start..ruby_end).count > 10
-    abc = 10
- elsif (ruby_start..ruby_end).count <= 10
-    abc = (ruby_start..ruby_end).count
- end
```

### 【After1】
`min`メソッドを使う例。5行が１行に。
```diff_ruby
+ abc = [(ruby_start..ruby_end).count, 10].min
```

### 【After2】
`clamp`メソッドを使う例。以前書いた記事についた[こちらのコメント](https://qiita.com/matsuken314/items/45430995ae0fa8d34231#comment-ce3148fe6bfedd4216d3)で初めて知りました。最大・最小値をまとめて制約できるメソッド。（[詳細](https://techracho.bpsinc.jp/hachi8833/2019_10_24/81812)）
```diff_ruby
+ abc = (ruby_start..ruby_end).count.clamp(..10)
```


### 理解の参考になる記事
▼ 以前書いた下記の記事でも`min`メソッドを用いた長い処理のメソッド化については触れています。

https://qiita.com/matsuken314/items/45430995ae0fa8d34231#%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC4-min%E4%BD%BF%E3%81%A3%E3%81%9F%E3%82%895%E8%A1%8C%E3%82%921%E8%A1%8C%E3%81%AB%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%82%88

▼ `clamp`メソッドの分かりやすい記事

https://techracho.bpsinc.jp/hachi8833/2019_10_24/81812

#  【第1位】ロケールファイルを使う
映えある第1位です。これだけ覚えて、ブラウザバックしてください。

> 引数によって返り値の条件分岐が発生するメソッドのレビュー

先輩「ロケールファイルに定義しとくと簡単に取れるのかなとも思いました。ホニャララホニャララ〜」
僕「 :open_mouth:！！！！！ 」
これは圧巻でした。
レビューで指摘されるまで、絶対にこのリファクタリングは思いつきませんでした。
### 【Before】
status_labelメソッドの中で引数status_codeの中身によって、`case`文を使って、条件分岐させています
```diff_ruby
def status_label(status_code)
-  case status_code
-  when 'typeA'
-    'ラベルA'
-  when 'typeB'
-    'ラベルB'
-  when 'typeC'
-    'ラベルC'
-  end
end
```

### 【After】
`locale.yml`（ロケールファイル）を使うことで、表示の切り替えを柔軟にできる実装になりました。
`locale.yml`（ロケールファイル）に定義しておくことで、今後「ラベルA」などの名前を変更する必要が生じた場合でもlocale.ymlの該当部分だけを編集すれば良いです。

```diff_ruby
def status_label(status_code)
+  Detail.human_attribute_name("status_label.#{status_code}") if status_code.present?
end
```

```ruby:locale.yml
detail:
  status_label:
    typeA: ラベルA
    typeB: ラベルB
    typeC: ラベルC
```
### 理解の参考になる記事
▼この記事がロケールファイルについて、分かりやすく書いてありました

https://qiita.com/d0ne1s/items/89846ebe97c9114865ca

# 終わりに

こうやって記事にして、先輩からいただいたリファクタリングを振り返ることで
- 復習として**自分**のため(成長）にもなるし、
- 分かりやすい説明は**読者**のためにもなるし、
- 自分が記事を書いて成長することで周りの**チームメンバー**に利益を与えるためにもなるし、

三報よし。そんな感じの意識高いことを思っております。

「まず動くコードを書く」という意識が先行したエンジニア1年目だったと思います。
「これ、リファクタリングできるよね？」という目線もエンジニア2年目は意識していきたいなあと思ってたので、今回記事を書きました。

意識高いこと書いてたら、少し疲れたのでこれからサウナに行きます。

▼他にもつよつよエンジニアさんから頂いたガチレビューの記事を書いてます。

https://qiita.com/matsuken314/items/45430995ae0fa8d34231