はじめに
最近『リファクタリング 既存のコードを安全に改善する』(Martin Fowler (著))をちょっとずつ読み始めました。
まだ読み切れていませんが、読んでいて「うまいこと言うわ~」と思った法則についてメモしておこうと思います。
二つの帽子
リファクタリングをやりたくなる時というのは(本来リファクタリングは常にやるべきなのですが)、機能追加しようとしたら元のコードがいまいちで機能追加が難しい! というときなのではないかな、と思います。
実際、書籍の中でも『いつリファクタリングをすべきか』という項目で、『準備のためのリファクタリング』として、いの一番に挙げられています。
こういった場合、機能追加をするためには『機能追加』と『元のコードのリファクタリング』の、二つのことをやる必要がありますが、これら二つは同時にやってはなりません。
機能追加をしようとしていて、「おや? このコードはちょっと直さないと機能追加がやりづらいな」と気づいたら、『機能追加の帽子をリファクタリングの帽子にかぶり直して』 リファクタリングを行います。この時はコードのリファクタリングに専念し、機能追加は行いません。
コードを修正して、機能追加がしやすい状態になったら、今度は 『リファクタリングの帽子を機能追加の帽子にかぶり直して』 、改めて機能の追加を行います。
その後、もしも機能追加したコードに再び改善点が見つかったら、また帽子をかぶり直してリファクタリングをするのです。
リファクタリングと機能追加を区別することで、機能追加がしやすい状態にリファクタリングされたコードに効率よく機能を追加できますし、万が一バグを埋め込んだ時にリファクタリングで埋め込んだのか、機能追加で埋め込んだのかを切り分けやすくなります。
個人的に、この法則を知って以降、機能追加でリファクタが必要になったときには意識するようにしています。
ただ、うっかりリファクタ・機能追加までやり切ってからデバッグをしたせいで、リファクタと機能追加のどちらでバグを埋め込んだかわからなくなってしまったこともあるんですが……(ちゃんと逐一デバッグしましょう)。
三度目の法則
わたし「コード書くぞ!」
//...
foreach(var item in items)
{
var a = item.MethodA();
a.MethodXX();
// ...
}
(しばらくコーディングする・・・)
//...
foreach(var item in items)
{
var a = item.MethodA();
a.MethodXX();
a.MethodB();
// ...
}
わたし「あれ、この処理さっきも書いたかも?」
わたし「でも、似て非なる処理で共通化できないかもしれないし……」
(引き続きしばらくコーディングする・・・)
//...
foreach(var item in items)
{
var a = item.MethodA();
a.MethodXX();
if(a == YYY)
{
a.MethodC();
}
// ...
}
わたし「あれ、また似たような処理かも?」
わたし「三回も同じことするのはさすがに変だね。リファクタしよう!」
三度めの法則とは、『二度目に以前と似たようなことをしていると気付いたら、重複を意識しつつも作業を続行していいが、三度目に似たようなことをしていると気付いたらリファクタリングをする』 という法則です。
デザインスタミナ仮説
ソフトウェア内部の設計を入念に行うことで、ソフトウェア開発のためのスタミナをつけていくことができるので、その後の開発をより長い期間、よりスピーディに行えるという仮説です。
まずい設計のまま爆速実装すると、一見素早く開発できるように見えます。
しかし、ぐちゃぐちゃのコードは理解に時間がかかりますし、バグも埋め込みやすいです。最初は速く開発できていても、徐々に開発スピードが遅くなっていきます。
きちんと設計しながら、そして適宜設計をより良くリファクタリングしながら開発を進めていくことで、既存のコードは機能追加に立ちはだかる壁ではなく、新機能追加のしやすいプラットフォームになるのです。
さいごに
当たり前といえば当たり前ですが、大事なことだと思います。改めて意識するきっかけになりました。
『リファクタリング』、個人的にはページ数のわりに読みやすいというか、開発経験が少しあれば「なるほど!」「あるある!」と思える内容だと思います。