スコープを狭くしよう、というコラムです。
変数には1度だけ書き込むほうがいい
かのリーダブルコードに以下のような記述がある
本章では「生きている」変数が多いとコードが理解しにくくなることを説明した。でももっと理解し難いのは、変数が絶えず変更され続けることだ。値を追跡する難易度が格段に上がってしまう。 この問題と戦うために、ちょっと変わったものを提案したい。それは、変数は一度だけ書き込むというものだ。
- リーダブルコード 9.3 変数は一度だけ書き込む より
変数というのは可変の数値ではあるが、なるべく変更されるのは少なくあってほしい。理由をあげるとすれば…
- 変数が書き換わることがあればその書き換わる前後で差分を比較する必要がある
- 値が変わらなければ、意図違いで使うことは減る。
という部分である。ここらへんは詳しくはリーダブルコードを読んでください。。
この「変数は1度だけ書き込むことが望ましい」ということを踏まえて「オブジェクトはできるだけ不変とする」という話をしたい。
オブジェクトはできるだけ生成後に変わる部分を少なく
たとえば下記のようなクラスがあったとする。
class Human attr_accessor :first_name, :last_name, :age def output_profile_text "Hello! My name is #{first_name} #{last_name}, #{age} old." end end
これをオブジェクト化して使おうとすると以下のようになると思います。
taro = Human.new taro.first_name = "Taro" taro.last_name = "Suzuki" taro.age = "20" p taro.output_profile_text
このようになった場合に、 taro
オブジェクトは生成後に必要な値をセットしないと output_profile_text
が正しく書き出せない。
taro = Human.new taro.first_name = "Taro" taro.last_name = "Suzuki" p taro.output_profile_text #=>"Hello! My name is Taro Suzuki, old."
また名前のようなものは、一度設定したら変わることはないので、外から変更可能というのも別に必要性がない。
taro = Human.new taro.first_name = "Taro" taro.last_name = "Suzuki" # おそらくこのような書き換えは正常ケースでは不要 taro.last_name = "Sato"
このように
- 最初から使うことが約束されている
- 途中から書き換えることが無い
というような情報はインスタンスが作られる時点でセットしてあげるようにしたほうが、変な書き換えを心配しなくていいし、見るべきスコープを狭くすることができる。ここの考え方は最初の変数の話と似た部分となる。
class Human # 初期化で絶対必要になる情報をセット,利便性を考えて名前付き引数 def initialize(first_name:, last_name:, age:) @first_name = first_name @last_name = last_name @age = age end def output_profile_text "Hello! My name is #{@first_name} #{@last_name}, #{@age} old." end end
taro = Human.new(first_name: "Taro", last_name: "Suzuki", age: 20) p taro.output_profile_text
このようにして書き換えてあげれば途中で書き換える使われ方も減るはずだし、スコープも狭くなるので見通しは遠くなるはずです。
参考リンク
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
- 作者: Dustin Boswell,Trevor Foucher,須藤功平,角征典
- 出版社/メーカー: オライリージャパン
- 発売日: 2012/06/23
- メディア: 単行本(ソフトカバー)
- 購入: 68人 クリック: 1,802回
- この商品を含むブログ (140件) を見る