Rubyプログラミング:明確なコードですか、それとも簡潔で洗練されたコードですか.

1722 ワード

Pier Cawleyは、遅延初期化のプロパティを紹介するブログ記事で発見された潜在的な問題を検討した.問題が発生したコードは次のとおりです.
def content
@content ||= []
end

このコードの目的は、クラスの遅延初期化プロパティをサポートすることです.この例では、@contentというインスタンス変数が初期化されていない限り、そのアクセサメソッドcontentメソッドが呼び出されると初期化されます.||=このオペレータは、「左の変数値がnilの場合、その値を右の式に割り当てます.そうしないと、左の変数値のみが返されます」という意味です.
しかし、Piersは、Rubyがブール値とnilを処理する方法が特殊であるため、いくつかの値にとって問題が発生すると指摘した.次の例を見てみましょう.
a = false
a ||= "Ruby"

このようなコードの結果はどうなりますか?aはすでに第1行で初期化されているので、第2行は何の効果も生じてはならない.しかし、コードの実行後、aの現在の値はfalseではなく「Ruby」であることがわかります.
Rubyでnilを記述して汎用方式をチェックすると、問題は非常に明らかになります.
if name
puts name.capitalize
end

Rubyではnilがブール値falseと解釈されるため、if句のコードはnameの値がnilに等しくない場合にのみ実行される.
これは通常の意味では問題にならないが、初期化属性を遅延させるコードでは、属性に付与される正当な値がnilまたはfalseである場合、問題となる.この場合、プロパティにアクセスすると、プロパティ値がデフォルト値にリセットされます.
もちろん、これは境界状況ですが、このような問題は、デバッグに長い時間を費やし、なぜいくつかの方法がリセットされる場合があり、他の方法が再設定されないのかを見つけようとします.
Piersはこのコードに対してより明確なコードを与えた.
def content
unless instance_variable_defined? :@content
@content = []
end
return @content
end

これにより、コードは変数が定義されていない場合にのみ変数を初期化します.
この小さな例では、Rubyとその一部の言語特性のせいにすることができますが、どのプログラマーが彼ら自身ではなくツールのせいにするかはよく知られています.Rubyコードの簡潔さは非常に有用であるが,意図をより明確に表現する式を用いるとより安全になる場合がある.この例では、||=は正しい解決策ではなく、逆に初期化コードは変数が定義されているかどうかを確認しなければならない.
親愛なる読者、あなたも以前このような問題に頭を叩かれたことがありますか?Rubyは、上記の発見しにくい問題を予防するために避けたい言語特性がありますか?
原文:Explicit vs.concise code in Ruby