リファクタリングのポイント ( Java ) 研修コースに参加してみた
今回参加した研修コースは、 リファクタリングのポイント です。
私は今まで 「リファクタリング」 という言葉からは漠然と、レガシーコードの改善、パフォーマンスの改善、リファクタリング職人といった、限られた人がやる職人技といったイメージを持ってました。
参加してみると、人にわかりやすく、自分も楽できるコーディングのテクニックを、IDEのパワーでカジュアルに取り組めるものだったことがわかり、とても心地よい体験でした !!
教室でも、とても多くのメモを書いていた方が多く、よいリファクタリング体験をされていたのではと思っています。
プログラミングをもっと上手くなりたい、伝わりやすいリーダブルなコードを書きたいという方にはとてもオススメです !!
では、コース内容をレポートします!
コース情報
想定している受講者 |
|
---|---|
受講目標 | リファクタリングが必要なバッド・コードを識別し、適切なリファクタリングを施すことができるようになる |
講師紹介
講師紹介のようなものはなくコースがスタートしましたが、このレポートでは講師を紹介します。
Java はもちろん Python / PHP などスクリプト言語、 Vue / React など JS だってなんだってテックが大好き。原点をおさえた実践演習で人気
過去にはオブジェクト指向を使った開発や多くの書籍を執筆されていましたが、今はもっぱら講師としてご活躍で、SEカレッジではハイエンドな技術コースを主に担当されています。
また、年間の 1 / 3 以上を海外遠征も含め山登りされています。
リファクタリングとは
マーチン・ファウラーが生み出した “リファクタリング” という本がきっかけ
リファクタリングという言葉が登場する前から、リファクタリングで挙げられたやり方などは存在していたのですが、リファクタリングという言葉とやり方をまとめて書籍としてパッケージしたのは マーチン・ファウラー でした。
マーチン・ファウラーというと、今回のリファクタリングをはじめ、アジャイルソフトウェア開発宣言 や最近では “Microservices” (マイクロサービス) の生みの親の 1 人でもあります。 テック業界におけるトレンドセッターにも見えてきますね。
今回のコースはマーチン・ファウラーが書いた原著、 Refactoring: Improving the Design of Existing Code の翻訳を引用しながら進めます。
リファクタリングとは?
まずはリファクタリングを行う背景から解説いただきました。
コードそのものは機能拡張したり、スピードを優先して「とりあえず動くもの」を追加するたび、劣化していきます。
定期的にリファクタリングすることで、コードを改善できます。
リファクタリングのメリット
- ソフトウェアの設計を改善する
- コードをわかりやすくする
- バグを見つけやすくする
- より速くプログラミングできる
コードをわかりやすく改善する中でバグを見つけたり、追加しやすくなったり、それらによってスピードも速くなります。
最近話題の DX (Developer Experience) というものに通じるものかも知れませんね。
DX: Developer Experience (開発体験)は重要だ – Islands in the byte stream
いつリファクタリングをやるのか
この「いつやるのか」がとても多くの示唆に富んでいました !! (耳が痛いとも思いました..)
- 三度目の法則
- 同じような処理を3回書いたとき
- 機能を追加する
- バグフィックス
- コードレビュー
- 気付いたらいつやってもよいよとは言っている
- コードの不吉な臭いを感じたらやるべき
- “Bad Smells in Code” という言葉はケント・ベックと話していたときに出てきた
- コードの不吉な臭いカタログがある (!!)
ググるといっぱい出てくるので、興味がある方は調べてみましよう !
リファクタリング 手法
- 必ずテストを書く
- Javaであれば JUnit を使いましょう
- テストしないと、外の振る舞いが全く変わってないのか分かりません
- リファクタリング後にテストを通して、振る舞いが変わってないことを保証しましょう
そうなんです。テストを書いてないとリファクタリング出来ないんです。
なお、テストを自然と書けるようになりたい、テストが 1 つもないのでどこから始めるかわからない、と思う方は SEカレッジで 「 JUnit ではじめる単体テスト入門」( 1 日コース) も開催されていますので、ぜひご参加下さい。
(私もレポートを書きながら学びます!)
では、テストを書いて、どのようにリファクタリングを進めるのか、マーチン・ファウラーの本ではリファクタリングのテクニックを 6 つのカテゴリに分け、 72 個のテクニックを紹介しています。
1 時間程度の解説をへて、ここからはその72のテクニックから幾つかピックアップし、実際にIDE (Eclipse) を使って実際にリファクタリングに取り組みました。
リファクタリング演習
ここからは Refactoring にあるサンプルコードをもとに実際にリファクタリングに取り組みます。
なお、米山さんがこのコースで使えるように、
- 書かれているコードが10年前なので、ちょっと古く、今回書き直したりしてます
- コードが抜粋されているので、実行できるようにしてます
予めコードに手を入れたものを用意いただきました。サンプルが動かなかったり、実行できないと勉強しにくいので、とても助かります。
演習内容とツール
- Eclipse にはリファクタリング支援機能がある (!!) ので、それを使いましょう
- 原著はもちろん特定のIDEに依存しないやり方を紹介しているので、目を通すことをオススメします
- よく使うテクニック、目からウロコなテクニックなどを紹介いただきました
- 取り組んだリファクタリングのテクニックは下の通りです
- Extract Method (メソッドの抽出)
- Introduce Explaining Variable (説明用変数の導入)
- Replace Parameter with Method(メソッドによるパラメーターの置き換え)
- Introduce Parameter Object(パラメーターオブジェクトの導入)
- Replace Error Code with Exception(例外によるエラーコードの置き換え)
ここからは実際にどのようにリファクタリングしたのか、紹介します!
Extract Method メソッドの抽出
Before
package composing_methods.extract_method.before;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] sampleData = {9, 2, 7, 3, 6, 1, 5, 4, 8};
System.out.println("[Before sorting]");
for(int data : sampleData) {
System.out.println(data);
}
Arrays.sort(sampleData);
System.out.println("[After sorting]");
for(int data : sampleData) {
System.out.println(data);
}
}
}
リファクタリングのポイント
- 不吉な臭いはどこから?
for(int data: sampleData) {}
が重複している- 1 つにまとめてしまいましょう
- ここで Eclipse の機能を使いましょう
- 修正したいところをドラッグ
- もしくは
alt + shift + m
でダイアログ表示 - 新しいメソッドの名前をつけましょう
- 関連していて、わかりやすいものにしましょう
- OKを押します
- リファクタリング完了 (!!)
after
package composing_methods.extract_method.after;
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] sampleData = {9, 2, 7, 3, 6, 1, 5, 4, 8};
System.out.println("[Before sorting]");
printArray(sampleData);
Arrays.sort(sampleData);
System.out.println("[After sorting]");
printArray(sampleData);
}
for(int data : sampleData) {
System.out.println(data);
}
}
}
IDE のパワーはすごいです。とても優秀ですね。
このことを社内のエンジニアに言うと「IDEを体験してしまうと、もうエディタとプラグインだけでは開発できない」とコメントしてました。
Java系のIDEというと、今回使用しているフリーソフトウェアの Eclipse がありますが、有料のIDEだと IntelliJ が人気ですね。 最近では Atom や Visual Studio Code などモダンなエディタでも高機能なものがあります。
と余談しているとどんどん話が広がるので、IDEの機能を紹介するだけでもコースが一つ作れそうです。
Replace Temp with Query メソッドによるパラメーターの置き換え
Before
package composing_methods.replace_temp_with_query.after;
public class Example {
private int quantity;
private int itemPrice;
public double getPrice() {
int basePrice = quantity * itemPrice;
double discountFactor;
if(basePrice > 1000) {
discountFactor = 0.95;
} else {
discountFactor = 0.98;
}
return basePrice * discountFactor;
}
}
リファクタリング1
- コードの不吉な臭いはどこから?
- 一次変数があることでメソッドが長くなっている
- 変数が 1 回しか使われてない = 再代入されていない
- 一次変数があることでメソッドが長くなっている
- 不要に長くならないようにしましょう
- まず
final
宣言をして一次変数にします
リファクタリング2
- メソッドを抽出しましょう
- インライン化しましょう
basePrice
- ドラッグして
alt + shift + i
でダイアログを表示
- ドラッグして
- メソッドもあるのでこれも抽出しましょう
discountFactor
- さらにインライン化しましょう
discountFactor
- これによって他のコードで必要になった場合、他からメソッド呼び出しできるようになりました
リファクタリング3
- さらに discountFactor が重複しているので
return
にします
リファクタリングのコツ
basePrice()
discountFactor()
のようなものは問い合わせメソッドと呼ばれます- 上からまず全体を書き、見通しをつきやすくして、詳細は下位のメソッドに書くようにしていくことがコツです
After
package composing_methods.replace_temp_with_query.after;
public class Example {
private int quantity;
private int itemPrice;
public double getPrice() {
return basePrice() * discountFactor();
}
private double discountFactor() {
if(basePrice() > 1000) {
return = 0.95;
} else {
return = 0.98;
}
}
private int basePrice() {
return quantity * itemPrice;
}
}
他にもサンプルコードをもとにリファクタリングのテクニックを体験して、最後に米山さんが “必ずテストを書くこと” を強調して、コースは修了となりました。
まとめ
この研修コースではマーチン・ファウラーの原著にあるサンプルコードをもとに、実際にリファクタリングに取り組みました。
途中で体験したリファクタリングテクニックはやはり知っていないと出来ませんが、”コードの不吉な臭い” がどのようなものかわかりはじめてきました。読みやさ = リーダブルにも通ずるものがありますね。
また、サンプルコードを米山さんの見よう見まねでやってみましたが、リファクタリングのポイントをおさえて、IDEの機能を使えば、とてもカジュアルに取り組めるように感じられました。
プログラミングをもっと上手くなりたい、読みやすいコードを書きたい、という方にはとてもオススメです !!
SEプラスにしかないコンテンツや、研修サービスの運営情報を発信しています。