変数の代入を複数回行う、すなわち変数の再代入をすることは何が辛いか、また変数の代入を1回にすると何が嬉しいかを書く。
今回の題材
例えばRubyで以下のようなメソッドがあるとする
def make_aisatsu_text(people_name: "Suzuki", is_san: false) text = is_san ? "さん" : "" text = people_name + text text = text + "、こんにちわ!" return text end
この記述を例に辛い部分は大きく以下の2つ
- 変数の状態がメソッドの最初から最後まで変わり続けるので変更に弱い
- (型付き言語だと発生しないが)途中の状態が削除されると読み取り難易度が増す
1つずつ簡単に説明していく
変数の状態がメソッドの最初から最後まで変わり続けるので変更に弱い
上記の例だと text
という内容が行によって変わり続ける。
最後にreturnする内容をするのを text
にしたいという意図はあるかもしれないが
この方法は今後拡張したときに厳しくなる。
例えば
- Satoさんへの挨拶の場合は、「久しぶり」という言葉を、そうでない人には「はじめまして」を挟む
- 天気がいいかを調べる、
sunny?
メソッドがtrueなら「天気がいいですね」という言葉を挟む
という変更が加わるとすると以下のようになる
def make_aisatsu_text(people_name: "Suzuki", is_san: false) text = is_san ? "さん" : "" text = people_name + text if people_name == "Sato" text = text + "、久しぶり" else text = text + "、はじめまして" end if sunny? text = text * "、天気がいいですね" end text = text + "、こんにちわ!" return text end
このようになるが、この時点でかなり読みづらくなっている(と私は思っている) さらに「こんにちわ!の位置は文の最初の方に…」などの変更が入ったら更にカオスになる。
途中の状態が削除されると読み取り難易度が増す
上に書いた仕様追加されたコードで更に「Tanakaさんの場合は名前を呼ぶ部分はいらなくなりました」といって削除を行うとする。 単純にやると以下のような事が起きる。
def make_aisatsu_text(people_name: "Suzuki", is_san: false) text = is_san ? "さん" : "" text = people_name + text if people_name == "Tanaka" text = "" end if people_name == "Sato" text = text + "、久しぶり" else text = text + "、はじめまして" end if sunny? text = text * "、天気がいいですね" end text = text + "、こんにちわ!" return text end
textを ""
してリセットするという処理を入れたが、増々読みにくくなった。
このように継ぎ足していく処理とまっさらにする処理が混在する状況になると「この行における text
は何が入っているのか?」というのがよりわかりにくくなる。
改善例
シンプルに再代入をやめることだけでかなりスッキリさせることができる。
def make_aisatsu_text(people_name: "Suzuki", is_san: false) san_text = is_san ? "さん" : "" full_name_text = people_name + san_text return full_name_text + "、こんにちわ!" end
盛々の仕様変更も耐えやすい
def make_aisatsu_text(people_name: "Suzuki", is_san: false) san_text = is_san ? "さん、" : "、" full_name_text = people_name + san_text meet_text = people_name == "Sato" ? "久しぶり、" : "はじめまして、" weather_text = sunny? ? "天気がいいですね、" : "" main_text = meet_text + weather_text + "こんにちわ!" return main_text if people_name == "Sato" return full_name_text + main_text end