621 Views
February 27, 23
スライド概要
輪読会用の資料です。
輪読書は「リファクタリング(第2版) Martin Fowler (著)」です。
サーバーサイドエンジニア Webアプリケーションの開発・運用業務を行なっています。 PHP, Node.jsなど。
2022/03/03 リファクタリング 第2章(社内勉強会用資料) 矢島 達朗 第2版
自己紹介 名前 矢島 達朗(Tatsuro Yajima) 趣味 ● 写真 ○ ● 散歩ついでに、雲とかビルとかを撮影してます。 ベース ○ YouTube の音楽に合わせて弾いたりしてます。 最近やってること ● ● GraphQL の勉強 Next.js でブログ作成
第2章 リファクタリングの原則
リファクタリングとは何か?
リファクタリングの定義 1 リファクタリング(名詞) 外部から見た時の振る舞いを保ちつつ、理解や修正が簡単になるように、 ソフトウェアの内部構造を変化させること。 2 リファクタリングする(動詞) リファクタリングを適用して、外部から見た振る舞いの変化なしに、ソフトウェ アを再構築すること。
Q. なぜリファクタリングが必要なのか?
A. コードの理解や修正を容易にするため
振る舞いは変えず、コードの質を上げる!
振る舞いが変わらない、とはどういうことか? ● インプット & アウトプット ○ 変わらない ● 処理速度 ○ 変わるかもしれない ○ 速くなったり、遅くなったりする ● バグ ○ 修正しない
開発とリファクタリングは、分けて行う 『2つの帽子』 開発時 リファクタリング時
理想の流れ ① 機能Aの開発 (テストまで実装する) ② リファクタリング (テストOK) ③ 機能Bの開発 (テストまで実装する) ④ リファクタリング (テストOK) ・・・
Q. 誰のためにリファクタリングするのか?
A. 将来の開発者のため
将来の開発者の負担を減らす 将来コードを触る開発者のために、例え少しだけ処理速度が落ちたとして も、わかりやすい記述をすべき。 ※ 開発者の中には、自分自身も含まれます!
リファクタリングのメリット
リファクタリングのメリット① バグの発見を助けられる! コードが理解しやすい = バグを見つけやすい
リファクタリングのメリット② 開発速度が上がる! 詳細は次ページ →
リファクタリングをすると開発速度が上がる https://martinfowler.com/bliki/DesignStaminaHypothesis.html
いつリファクタリングすべきか
三度目の法則 1. 開発する 2. 「この処理、前も書いたな」と気付く 3. 「この処理書くの、3回目だな」と気付く a. ↑ここでリファクタリング開始!
3種類のリファクタリング
1. 準備のためのリファクタリング
1. 準備のためのリファクタリング 将来的な変更に備えるためのリファクタリング。 【例】 ● リテラル、マジックナンバーを排除 ● 重複している処理をメソッド化
Before(メインルーチン内で処理が重複している)
switch ($result) {
case self::TYPE_1:
$result[message] .= "({$result['message_for_type_1']})";
break;
case self::TYPE_2:
$result[message] .= "({$result['message_for_type_2']})";
break;
}
After(メソッドを定義することで、処理を分離)
$result['message'] = $this->getMessage($result['result_code'], $result['messages']);
// ----- 中略
-----
private function getMessage(int $resultCode, array $messages):string {
switch ($resultCode) {
case self::TYPE_1:
return "({$messages['message_for_type_1']})";
break;
case self::TYPE_2:
return "({$messages['message_for_type_2']})";
break;
}
}
2. 理解のためのリファクタリング
2. 理解のためのリファクタリング そこでどんな処理をしているかを理解するためのリファクタ リング。 【例】 ● 適切な変数名をつける ● 長いメソッドを分割する
Before(変数名、メソッド名がわかりづらい) $data = fetchData($id); $isExists = false; $count = 0;
After $orderDataArray = fetchOrderData($orderId); $isExistsInvalidOrder = false; $invalidOrderCount = 0; 注文データを取得し、想定通りの値かをチェックする処理を行う、と予想できる。
3. ゴミ拾いのためのリファクタリング
3. ゴミ拾いのためのリファクタリング 手をつけたコードの周辺を少しでも綺麗にしておく ためのリファクタリング。 【例】 ● タイポ修正 ● 入り組んだロジックをシンプルに書き直す
Before(タイポあり。処理もわかりづらい)
$this->setConfition($conditions, $postedData);
private function setConfition(&$conditions, $postedData)
{
foreach ($postedData['orderIdArray'] as $orderId) {
$conditions[][$orderId] = $postedData['conditions'];
}
}
After(タイポ修正&処理をわかりやすくした)
$conditions[] = $this->setCondition($postedData);
private function setCondition(array $postedData): array
{
foreach ($postedData['orderIdArray'] as $orderId) {
$conditions[$orderId] = $postedData['conditions'];
}
return $conditions;
}
ここまでのまとめ ソフトウェアが「完成」することはない。 いつか修正する日のために、 変更しやすい状態を保つことが大事。
リファクタリングの問題点
リファクタリングは、(短期的な)開発 時間とのトレードオフが発生する。
リファクタリングを後回しにしても良いケース 1. 些細な機能追加 2. めったに触らない & 不便さを感じていない箇所 かけた時間と効果が見合わないことが想定される。
注意点 リファクタリングは、純粋に経済的な基準で測られるもので ある。 下記のような思考はNG ● 美しいコードを書くためにリファクタリングする ● リファクタリングはエンジニアの責務である
リファクタリングとテスト
リファクタリングは、 自動テスト と深い関わりがあります。
リファクタリングの前にテストを書くことが大事。 テストがあれば、振る舞いの変化にすぐ気付ける。
リファクタリングとアーキテクチャ、Yagni
その昔 設計・アーキテクチャを完成させてから、開発を行う。
現代 リファクタリングにより、設計・アーキテクチャは 柔軟に変更可能
ウォーターフォールの問題点 「ソフトウェアの要求は事前に把握できる」 という前提に立ってしまうこと! 実際に作ってみないとわからないことも多い。
Yagni
Yagni (You aren’t going to need it! ) ● 要求は変わる ● 必要になったら作る ● シンプルに、必要なものだけ作る
関連ワード ● アジャイル開発 ● CI/CD ● KISS原則(Keep it simple, stupid.)
リファクタリングとパフォーマンス
パフォーマンスとの関連 リファクタリングは、パフォーマンスを落とす可能性もある。 リファクタリングとチューニングは、分けて考えること。 リファクタリングしておけば、チューニングもやりやすくなる。
パフォーマンスで大事なこと 推測ではなく、計測すべき! ↓の流れがおすすめ パフォーマンスは気にしない! 1. 開発 2. リファクタリング 3. 計測しながら、チューニング リファクタリング後なので、 チューニングしやすい!
まとめ
第2章 リファクタリングの原則 まとめ ● なぜリファクタリングをするの? ○ 処理をわかりやすく、変更を容易にするため ● 2つの帽子を交互にかぶる ● リファクタリングのためには自動テストが必要 ● チューニングは別途行う
ご静聴ありがとうございました! Martin Fowler氏 (Wikipedia)