リファクタリング - 絶えざる改善でソフトウェアの品質を向上させる
まずは、自動テストを活用してソフトウェアの内部品質を向上させる方法を紹介します。この手法はリファクタリングと呼ばれています。
ソフトウェアのリファクタリングとは何か
ソフトウェアにおけるリファクタリングとは、ソフトウェアの振る舞い(外部から見た時の挙動)を変更せずに内部の実装を変更することです。ここでいう外部とはリファクタリング対象の処理を呼び出す箇所のことです。
例えば、あるメソッドをリファクタリングすることとは、そのメソッドの命名を変更したり実装を書き換えたりすることです。そのメソッドを呼び出した側にとって、リファクタリングの前後で入力値と返り値の組み合わせが同じままであれば挙動(振る舞い)は変わっていないと言えます。
リファクタリングはソフトウェア開発において重要な位置を占めています。次に、リファクタリングを実施する主な理由を紹介していきます。
なぜリファクタリングを実施するのか
ソフトウェアにおいて一度書かれたコードは永遠に固定されたものではなく、常に変更の可能性に晒されます。
変更要求の例として、技術方面からはプログラミング言語やフレームワークのバージョンアップデート、ビジネス方面からはユーザーに対する価値向上のための新仕様の実現、またソフトウェアの対象領域(ドメイン)に対する技術者自身の理解の深化といったケースが挙げられます。
極端な例ですが、ソフトウェアの品質が低いなら、ある小さな仕様の変更に1か月の工数を要する場合もあるでしょう。当然ながら、そのソフトウェアは変更に強い柔軟な状態であるとは言えません。小さな変更が高コストであるのはソフトウェアが硬直化したサインだからです。
反対に、リファクタリングを適切に実施していれば内部品質を高く保つことができます。コードの可読性、保守性が担保されており開発者が容易に実装できる場合、たった3日で同じ変更に対応できることも十分ありえます。
リファクタリングとはソフトウェアを柔軟な状態に保つための手段です。ソフトウェアが柔軟な状態であるということは、内部品質が高いということに他なりません。品質が高いと、変更に強いソフトウェアであり続けることができ、ビジネス環境の突然の変化にも素早く対応できます。良いソフトウェアとは、本来的な意味での柔軟さ(soft)を備えたソフトウェアなのです[1]。
リファクタリングの元々の意味
リファクタリングの意義を紹介したところで、この言葉の原義に触れておきましょう。
この章の冒頭で「ソフトウェアのリファクタリング」という言い回しをしました。リファクタリング(refactoring)という言葉は数学の分野で因数分解と訳され、「数学のリファクタリング」といえば因数分解を指すからです。ちなみにfactorizationとも言われます[2]。
例えば、x^3 + 2x^2 - x - 2
という式を(x + 1)(x + 2)(x - 1)
という因数同士の積の形に変形するのが因数分解です。仮に「上記の式をf(x)
と定義したとき、f(x) = 0
となるxを求めよ」という問題が出題されたらf(x) = x^3 + 2x^2 - x - 2
よりf(x) = (x + 1)(x + 2)(x - 1)
と書かれている方がすぐに答えが出せます(答えはx = -1, -2, 1
です)。式がわかりやすくなったのは、因数分解(リファクタリング)を実施して式の可読性が向上したからと言えるかもしれません。
数学のリファクタリングの対象は数式である一方、ソフトウェアのリファクタリングの対象はクラスやメソッドといった処理の定義です。対象はそれぞれ異なるものの、上述のようにリファクタリングという言葉で指している内容には多くの共通点があります。数学の因数分解という元の意味に立ち返れば、ソフトウェアのリファクタリングについても深く理解することができるでしょう。
リファクタリングと自動テストの関係とは
さて、ここからが本題です。自動テストはリファクタリングとどのような関係にあるのでしょうか。両者の関係が端的にわかるエピソードを紹介します。
今から何年も前のことです。雑談の中で、バックエンドエンジニアの先輩が転職の面接で実際に聞かれた質問をいくつか教えてくれました(もちろん企業名は伏せた形でです)。
その一つが「あなたは、雑然としているがビジネス上重要なレガシーコードを改修する機能追加を任されました。さて、どうしますか」というものでした。
その質問に対して先輩は「もしテストがないのであればその処理に対して自動テストを書きます。次に自動テストを使って安全にリファクタリングをし、質を高めた上で機能を追加します」と答えた結果、次の面接に進めたそうです。
この受け答えからわかるように自動テストはリファクタリングにとって必須の関係です。なぜならリファクタリングとは上述のように「外部から見た振る舞いを変えず」に内部の実装を書き換えることであり、外部から見た振る舞いを検証するには手動テストより低コストで実施できる自動テストが必須だからです。
良い開発者になるためには自動テストをしっかり書いた上でリファクタリングを実施し、ソフトウェアの品質を維持し続けることが重要なのです。
- [1]『Clean Architecture 達人に学ぶソフトウェアの構造と設計』(p.42)に「ソフトウェアはソフトでなければいけない。つまり、簡単に変更できなければならない」という一文があります。
- [2]Wikipedia「Factorization」より。