はじめに
現在プログラミングスクールRUNTEQ
に通っています。
久々にリーダブルコードを読んだので、改めて読みやすいコードを書くためにはどう意識すればよいか少しまとめていきます。
名前に情報を詰め込む
変数は名前に情報を詰め込む必要があります。
例えば、2時間後に締め切りによって条件分岐させるプログラムを考えるとします。
# 現在時刻を取得
now = Time.now
# 2時間後を計算
two_hours_later = now + (60 * 60 * 2)
# 締め切りが2時間後かどうかを判断
if now < two_hours_later
puts "まだ締め切りまで時間があります。"
else
puts "締め切り時間を過ぎています。"
end
上記ですが、2時間後をtwo_hours_later
という変数に代入していますが、これは意味がありません。
このnow + (60 * 60 * 2)
をどんな目的で用いるのかを考える必要があります。
# 現在時刻を取得
now = Time.now
# 締め切りを設定(現在時刻から2時間後)
study_deadline = Time.now + (60 * 60 * 2)
# 締め切りが2時間後かどうかを判断
if study_deadline > now
puts "まだ締め切りまで時間があります。"
else
puts "締め切り時間を過ぎています。"
end
今回は2時間後が勉強の締め切りだったので、study_deadline
という変数名にする事でより文脈が分かりやすくなります。
要約する
例えば、こんなコードがあるとします。
if request.user.id == document.owner_id
# ドキュメントを編集できる
end
この例だと、簡単に読めそうですが変数を5つ使って条件を判定しています。
request
のuser
のid
とdocument
のowner_id
が一致している時、という分岐から、「これは何を意味してるんだ、、?」と少し考えるのに時間がかかります。
この分岐は何を意味しているかというと、自分のドキュメントかどうか
ということを意味しているので、一度要約変数に代入することで、読み手の負荷を下げることにも繋がります。
user_owns_document = (request.user.id == document.owner_id)
if user_owns_document
# ドキュメントを編集できる
end
条件分岐の並び順
条件分岐は単純な条件、かつ肯定形から分岐をさせていく事が良いです。
if a != b
#aとbが「合致しない時」の処理
else
#aとbが「合致する時」の処理
end
if a = b
#aとbが「合致する時」の処理
else
#aとbが「合致しない時」の処理
end
一致してない場合の条件分岐を書く場合はRubyではunless
を用いる事が良さそうです。
print "数値を入力してください: "
num = gets.to_i
puts "#{num}は負の数です。" unless num >= 0
無関係の下位問題を抽出する
コードには単一責任の原則
という原則があり、クラスや関数への責任は一つにしましょうという原則です。
例えば、ユーザーの年齢を計算し、その結果に基づいてメッセージを出力するメソッドがあるとします。
def calculate_age_and_display_name(birth_year, name)
current_year = Time.now.year
age = current_year - birth_year
if age >= 20
puts "#{name}さん、あなたは成人です。"
else
puts "#{name}さん、あなたは未成年です。"
end
puts "あなたの名前は#{name}です。"
end
calculate_age_and_display_name(2000, 'Yamada')
このプログラムでは、年齢の計算
と名前の表示
という2つの責任(役割)
を持っています。
責任(役割)
が増えるごとに見通しが悪くなり、思わぬバグを生み出す温床になります。
また、関数名と実際の処理の内容が乖離してしまうことも考えられるので、責任(役割)
事にメソッドに切り出す事が良いでしょう。
def calculate_age(birth_year)
current_year = Time.now.year
age = current_year - birth_year
end
def display_message(age, name)
if age >= 20
puts "#{name}さん、あなたは成人です。"
else
puts "#{name}さん、あなたは未成年です。"
end
puts "あなたの名前は#{name}です。"
end
age = calculate_age(2000)
display_message(age, 'Yamada')