リファクタリング Ruby エディションを読んだ

読んだ理由

Ruby を使い始めて間もない頃に(3ヶ月ほど前)、隣の席にいた同じチームの同僚が「これいいよ」って教えてくれたのがきっかけで、以下のような思いを持って読むことになった。

ちなみに昨日、その同僚はブログでもっといろんな本を紹介していた。

Rails で "とりあえず動くコード" を書けるようになった人が次に遭遇する問題とそれを解決してくれる本まとめ - 彼女からは、おいちゃんと呼ばれています

この本に書いてあること

まだ肝心のリファクタリングのカタログ部分は読んでいない。 読んだのは以下の3章まで。

第1章 リファクタリング――最初のサンプル
第2章 リファクタリングの原則
第3章 コードの臭い

なぜかというと、ここまで読めばリファクタリングに取り組む上での考え方を学ぶことができるから。残りは気が向いたらじっくり読めばいいかな、と思った。あとは単に時間がかかりそうだったし、飽きそうだったから、というのもある。 P.18 にも、

実際にリファクタリングをしたいのなら、最初の4章を全部読んでから、カタログ部分を飛ばし読みすること

と書いてあるから、この方法でいいと思う。

では、ここまでで何が書いてあったか。気に留まったことをメモしておく。

リファクタリングとパフォーマンスは分けて考える

P.41 にこう書いてあった。

リファクタリングしているときはわかりやすくすることに集中すべきで、パフォーマンスを上げることについてはその後で別の仕事として行うのが正しい方法だ

ここではリファクタリングの最初のサンプルの中で「一時変数から問い合わせメソッドへ(Replace Temp with Query)」という方法を行った。この方法を行うと、メソッド呼び出しの回数が増えるので、パフォーマンスが気になり、このような変更を避けたがる人がいるということが書いてある。

この続きは「2.11 リファクタリングとパフォーマンス」の章に書いてあって、この章に書いてあること全部重要だと思った。つまり、絶えずパフォーマンスに注意を払うアプローチはあまり成功しない。なぜなら、

  • そのようなコードは一般的に読んだり変更したりしにくくなる
  • その最適化が全体から見て効果があるかわからない

ということ。よく言われていることだけど、ここでは全体の 90% の最適化は無駄になると書いてある。したがって、まずはパフォーマンスに注意を払わずに、全体が細かい部品に分割されるようにプログラムを作るのがよい。その後でプロファイラを使って残りの 10% を探して最適化する。この時に、プログラムが細かい部品に分割できるように作ってあると、

  • 変更しやすい。機能追加にかかる時間が短くすむので、パフォーマンスに集中する時間を確保できる
  • より細かい粒度でパフォーマンスを分析できる。最適化をかけやすくなる

というメリットがある。

本当に「パフォーマンスに集中する時間を確保できる」かどうかまではわからないけど、そのように心がけていこうと思った。

事前設計をしすぎない

「2.9 リファクタリングと設計」という章があるのだけど、ここも全て重要だと思った。必読。

ちょっとまとまったプログラムを書くときは、たいていの場合は何かしら設計をすると思うけど、その設計の妥協点で悩むことは多い。「こうすれば柔軟性が高くなる、でもやりすぎかも・・」とか、「そもそも柔軟な設計とは・・」とか、そういう悩みだ。この章にはこう書いてある。

リファクタリングを導入すると、強調点が変わる。事前設計をすることに変わりはないが、完璧な解を探そうとはしなくなる。まずまず妥当な解であればよい。

つまり、後の方が問題に対する知識が増えているはずなので、最初に考えるよりも最適な解が見つかりやすい。そのため、最初はリファクタリングできるように単純な設計にしておくのがよいということだ。予測できる変化に耐えられるような柔軟な解の難点は、その柔軟さのためにコストがかかるという点で、つまり、

  • 柔軟な解は複雑になる
  • メンテナンスが難しい
  • 予測できない変化には対応できない

という難点がある。一方、リファクタリングを導入している場合でも、将来どのような変更が加えられる可能性があるか、柔軟な解とは何か、考えるが、それをすぐに実装しないと書いてあった。

「それらの柔軟な解をすぐに実装するのではなく、「リファクタリングで単純な解を柔軟な解に変えるのはどの程度難しいだろうか」ということを考える。答が「かなり簡単」であれば(ほとんどの場合はそうなるが)、単純な解を実装すればよい。

と、ここまで書いてこれは YAGNI 原則だと気がついた。不必要な柔軟さは実装しない。シンプルに保つ。このへんのことは常に頭においておきたいと思う。

実は以前「オブジェクト指向のこころ」を読んだときにも同じようなことを書いていた

でも一方で、これはやりすぎに注意しないとな、と思った。将来の変更時に既存コードに手を入れずにすむようにするというのは大変なことなので、考えすぎて必要以上に複雑にならないようにしたい。そういうのも大事だけど、シンプルさも大事だと思う。

このときはオブジェクト指向設計をするときの話、今回も事前設計についての話なので、まあ、現時点の設計に対する自分の思いとしてはこういうことなのだなあ、と思った。

まとめ

コードのどこが、なぜよくなくて、どうすればもっとよくなるのか

この本の第1章は、設計があまりよくないコードをリファクタリングしていくという内容なのだが、そのよくないコードを見て最初に思ったことは、あるコードを見た時に、それのどこが、なぜダメで、どうすればよくなるのか、具体的に言えるようになる必要がある。ということだった。ダメなコードを見て「これはダメだ」というのは簡単だし、いいコードを見て「これはよい」というのも簡単。だけど、ダメな理由と、よくする方法、またその方法の何がいいのか、というのをちゃんと言うのは、もうちょっと難しいと思う。でも、それを言えないと実践では役に立たない。そのコードを書いた人や、その他の人を納得させることもできない。

なので、リファクタリングとは直接関係ないのだけど、そのようなことをできる人になりたい。

リファクタリングのカタログはこつこつ読む。

リファクタリング:Rubyエディション

リファクタリング:Rubyエディション