概要
下記のような単純なメソッドがあります。
def user_name
user.name
end
上記メソッド内に登場する user は、 「User オブジェクトまたは nil を返却するメソッド」だと仮定してください。
User オブジェクトには name というメソッドが実行できます。
nilの可能性があるので、NoMethodErrorが発生する可能性があります。
なので、 nilの場合の処理 を書く必要があります。
どのように書くのが1番読みやすいか悩んでいた時に4人の方に相談したのですが、
メソッドの内容によって、どれを読みやすいと思うかが変わる結果になりました。
同じような単純なメソッドだけど結果が変わってくるのが面白く思ったので、その時の結果を記事にします。
-
注意
- この場合はこの書き方が絶対いい!!ということを主張する記事ではないです。
- そもそも上記のような単純なメソッドの場合は、わざわざメソッドを書かずに他の方法が使えるケースも多いと思いますが、今回はその辺りには踏み込まないです。
ケース1: メソッドで処理さえできればいい時
下記のような条件のメソッドの場合は、どのように書くのが読みやすいでしょうか。
メソッドの条件
- メソッドの名前は
delete_user! - メソッド内では変数
userが使える - メソッド内の変数
userがnilではない場合は、userをレシーバーとしてdestroy!メソッドを実行する - メソッドの戻り値は利用しないので気にしなくていい
考えられるパターン
下記の2パターンを作成してみました。
パターン1: 早期リターン
def delete_user!
return unless user
user.destroy!
end
「やることないならとにかく早期リターンやろ」という考えを元に作成しました。
パターン2: &. を使う
def delete_user!
user&.destroy!
end
「1行で書けるんやから &. を使うべきやろ」という考えを元に作成しました。
相談の結果
4人とも、 「パターン2: &. を使う」 が読みやすいとのことでした。
やはり、ここまで単純だとわざわざ早期リターンしてメソッド内を3行にするより、
1行で書けるメリットの方が大きく感じられるようでした。
ケース2: メソッドの戻り値が必要な時
下記のような条件のメソッドの場合は、どのように書くのが読みやすいでしょうか。
メソッドの条件
- メソッドの名前は
user_name - メソッド内では変数
userが使える -
userがnilではない場合は、userをレシーバーとしてnameメソッドを実行する - メソッドの戻り値を、呼び出し元で利用する
-
userがnilの場合は、'no name'という文字列を返す
考えられるパターン
下記の2パターンを作成してみました。
(早期リターンは、ケース1で評判が悪かったので最初から選択肢に入れませんでした
)
パターン1: 三項演算子
def user_name
user ? user.name : 'no name'
end
「三項演算子がパッと見で読みやすいかな〜」と思って作成しました。
パターン2: &. を使う
def user_name
user&.name || 'no name'
end
ケース1では全員が読みやすいと考えた &. を使った書き方です。
三項演算子を使うより短く書けます。
三項演算子が好きではない人向けに作成しました。
個人的には、今回の場合は || を書く必要があるので、
ちょっとパッと見では読みづらい気がしました。
結果
投票結果は2対2に割れました。
「うーんどうしたものか。好みの問題かな・・・」と思っていると、
**「早期リターンを使った書き方がよいのでは?」**との提案をいただきました。
def user_name
return 'no name' unless user
user.name
end
確かに・・・1番分かりやすい気がする・・・!!
ケース1では不評だった早期リターンが、今回は1番読みやすい気がします。
今回のケースの場合は早期リターンを使うと、
「user がnilの場合は 'no name' を返す」
というのが1番パッと見で伝わりやすいし、メソッドの意図が伝わりやすい感じがします。
メソッドの戻り値が重要なときは、こちらの書き方を採用しようと思いました。
おわりに
Railsは、いろいろ自由な書き方が出来る分、書き方にこだわったり悩んだりする必要が多いと思います。
今回考えた内容は「好みの問題」で片付けられてしまうことも多いですが、
人にも聞いてみると、「こういうとき、1番読みやすいのはこれじゃないか」という傾向が見えてきて面白かったです。
一緒に考えてくれた4名のみなさんありがとうございました![]()