「リファクタリング 既存のコードを安全に改善する」を読んだ
(※この記事は、会社の勉強会での発表を元に起こしたものです。そのため、若干端折って書いております)
内容
こちらの本の紹介です。
今なら、第2版が出ています。言語がJavaからJavascriptに変更になりました。
読んだ動機
- 「リファクタリング」って言うけど、やってることは人それぞれだよね
- もやっとする
- 体系的におさらいする方がいいのでは?
- 「リファクタリング」の基本を学びたい
- 長い間積ん読であったが、コロナ自粛期間中に読んでしまおうと思った
そもそもリファクタリングとは
この本の定義では、リファクタリングとは↓
リファクタリング(名詞) 外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること
動詞バージョンはこちら↓
リファクタリングする(動詞) 一連のリファクタリングを適用して、外部から見た振る舞いの変更なしに、ソフトウェアを再構築すること
リファクタリングを行う理由
- ソフトウェア設計を改善する
- ソフトウェアを理解しやすくする
- バグを見つけ出す
- より早くプログラミングできる
いつリファクタリングをすべきか
- 3度めの法則
- 似たようなコードを3回書いたら、まとめる
- 機能追加の時
- 理由1. 既存機能を理解するため
- 理由2. 容易に機能追加出来ない設計を治す→機能追加作業
- バグフィクスの時
- 理由1. 既存機能を理解するため
- コードレビューの時
リファクタリングの注意事項
- 対象のユニットテストを書いてからリファクタリングすること
- リファクタリングはバグの原因になりうる (これは、私の実体験でも多々あります...)
リファクタリング例
6章〜12章、270ページに渡りリファクタリングのパターンが紹介されているが、その中で 自分的にびっくりした手法 をご紹介します。
リファクタリング前のコード
※本に載っていた例を簡略化したものです。
// レンタルビデオ店で、レンタル商品の合計金額と獲得ポイントを計算・表示する機能 int amount = 0; // 合計金額 int points = 0; // 獲得ポイント while(rentals.hasMoreElements()) { Rental each = rentals.nextElement(); amount += each.getPrice(); points++; } // 画面に表示 amountTextField = "合計金額は" + amount + "円です。"; pointTextField = "獲得ポイントは" + point + "ptです。" ;
上のコードの改善点はどこでしょうか...?
(1分間考えてみてください)
.
.
.
.
.
.
リファクタリング後のコード
// レンタルビデオ店で、レンタル商品の合計金額と獲得ポイントを計算・表示する機能 // 画面に表示 amountTextField = "合計金額は" + getAmount(rentals) + "円です。" pointTextField = "獲得ポイントは" + getPoints(rentals) + "ptです。" /// 合計金額を求める func getAmount(rentals[Rental]) { int amount = 0; // 合計金額 while(rentals.hasMoreElements()) { Rental each = rentals.nextElement(); amount += each.getPrice(); } return amount; } /// 獲得ポイントを求める func getPoints(rentals[Rental]) { int points = 0; // 獲得ポイント while(rentals.hasMoreElements()) { Rental each = rentals.nextElement(); points++; } return points; }
こういうコードは、「ループ回数が増えるので、良くない」と思っていたので、このように修正するのは意外でした...。
なぜこうすると良いのか?
- ユニットテストが書ける
- 修正前は、結果を直接UI要素に入れているので、テストは基本的に手動で行うしかない
- 修正後は、計算処理がメソッドになっていて、入力と出力があるので、ユニットテストが書ける
- 今回のような単純計算なら良いが、ポイントが複雑になってくると、いちいち手動テストするのはしんどい(* 例えば、「旧作映画を10本同時レンタルしたら+100ポイントキャンペーン」とか...)
- 最近の計算機は十分速いので、この程度のループが増えても影響は少ない
- 「1億本レンタルする人がいる」とかなら、大変そうですが...。
まとめ
- リファクタリングのもやもやがスッキリ
- なぜ行うのか?などの理由付けになる
- 定番の技術書を読むのも良い
- 「一般的に、こういうコードが良いコード」という安心感が得られる
- 今回の例のようなコードは、自分は良くないコードと思っていたが...と気づくきっかけ。この本を読んでいなければ、気づかなかった