「やりたい処理もできる」機能ではなく「やりたい処理用」の機能を使うことで、書いた人の意図が伝わるコードになるという話です。「動く」コードは書けるけど「意図が伝わる」コードはまだ書けない、という初級者向けの話です。
「動く」だけだとどんな機能を使って実装しても同じですが、「意図が伝わる」という観点では使う機能によって違いがあります。これは読む人が期待することとコードが意図することが異なるからです。
例
繰り返し機能が必要なケースを考えます。ここでは次のように1から5まで出力したいとします。
% ruby output-numbers.rb
1
2
3
4
5
Rubyには繰り返し機能を提供するeach
というメソッド1があります。これを使って実装すると「繰り返して処理をしたい」という「意図」が伝わるコードになります。
numbers = [1, 2, 3, 4, 5]
numbers.each do |number|
puts(number)
end
Rubyには「繰り返し」機能と「それぞれの繰り返しの結果を集める」機能を提供するmap
というメソッド2もあります。map
にも「繰り返し」機能があるので、map
を使っても「動く」コードを書けます。
numbers = [1, 2, 3, 4, 5]
numbers.map do |number|
puts(number)
end
これら2つのコードは同じ「動き」になりますが、「意図が伝わる」という点では違います。
map
には「それぞれの繰り返しの結果を集める」機能があるので、プログラムを読む人は「map
で集めた結果をどう使うのだろう」と考えながら読みます。しかし、このプログラムではmap
の「それぞれの繰り返しの結果を集める」機能を使っていないので、次のコードのようにmap
の結果を代入していません。
converted_numbers = numbers.map do |number|
puts(number)
end
今回のコードは単に結果を捨てています。
map
のことを知っている注意深く読む人3ならここで次のように考えます。
「それぞれの繰り返しの結果を集める」機能を提供する
map
の結果を使っていないということは…これは代入忘れのバグじゃないか?
しかし、コード全体を読んでみるとmap
の「それぞれの繰り返しの結果を集める」機能は使っていなくて、単に「繰り返し」機能だけを使っていることがわかります。そしてこう思います。
なんだ、「それぞれの繰り返しの結果を集める」機能を使っていないのか。じゃあ、バグじゃないか。まぎらわしいな。。。
map
ではなく「繰り返し」機能だけを提供するeach
を使っていれば、読む人はまぎらわしく思わずに書いた人が何をしたかったかを理解できます。このようなコードが「意図が伝わる」コードです。
「意図が伝わる」コードは読む人が理解する時間が短くなりますし、間違って理解されにくくなります。これはコードの修正や改良に役に立ちます。多くのコードは一度書いたら終わりではなく、動くようになったあとにメンテナンスされます。そのため、修正や改良に役立つことは重要です。
「動く」コードを書けるようになったら「意図が伝わる」コードを目指してください。
まとめ
each
とmap
を例にして「動く」だけのコードと「意図が伝わる」コードの違いを説明しました。ちなみに、each
でよいところにmap
を使っているコードはわりとよく見るコードです。いつもの癖でmap
を使ったり、最初は「それぞれの繰り返しの結果を集める」機能が必要だったけど途中で必要なくなったのにmap
を使い続けてしまっている、ということなのかもしれません。
「動く」コードを書けるようになったら、「動く」だけではなく「意図が伝わる」コードを目指してください。「意図が伝わる」コードは改良や修正などメンテナンスがしやすいからです。「とりあえず動くもの」の次を目指すときに参考にしてください。
あわせて読みたい:
お知らせ:
- 2015年3月6日(金)に実践リーダブルコードという有料セミナーを開催します。
- 2015年4月3日(金)に名著『リーダブルコード』を解説者と一緒に読み解こう
7章 制御フローを読みやすくするという無料のWeb授業を開催します。- 前回のWeb授業: 名著『リーダブルコード』を解説者と一緒に読み解こう
3章 誤解されない名前
- 前回のWeb授業: 名著『リーダブルコード』を解説者と一緒に読み解こう