will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

レガシーコード改善ガイド21章〜24章

21.同じコードをいたるところで変更しています。
目的:共通化へのノウハウを学ぶ
(安心して重複を取り除く為にはテストが必要。今回もテストがある前提で進めている)
結論:同じコードが書いてあるところは親クラスに抽出、同じメソッドが並んでいるところはループに抽出することができる。
そうすることで、追加の仕様やデータが変わった場合はクラスを追加・オーバーライドで既存の振る舞いをベースとして拡張していくことができる。

a.ラップメソッド よく使う処理をまとめて1つのメソッドにまとめる
void c() { a(); a(); b(); a(); b(); b();}
この場合1
void c() {aa() b(); a(); bb();}
void c() {a {}; ab(); ab(); b(); }
この2つに分解できる。
aa,bbとabどちらが処理で筋が通っているか?を見極めよう。

b.親クラスへの抽出。
類似部分が多く見られる場合は底を抽出して親クラスを作ると良い。
継承のために作られたメソッド以外は子クラスでオーバーライドする。

c.繰り返しの処理をリストとして変数に持ってループで処理する。
リストのジェネリックとして抽象化できればうまく親クラスにメソッドを移すことがデキる

d.サブクラス間に差異がある変数でも繰り返しっぽいところは、抽象getメソッドによって、親クラスで処理できる。
サブクラスでは親クラスでデータが使えるようにコンストラクタでデータを生成するだけで住む。

e.共通化したらサブクラスの名前、親クラスの名前に一貫性をもたせる。
命名規則へ省略形はなるべく使わない。省略形は人によって別に捉えたり、類似語もあるためおすすめは出来ない。
Implement <-> Impl



22.モンスターメソッドを変更する必要がありますがテストを書くことができません。
目的:1つのメソッドで多くのことをしている時、どのように変更すればいいか
結論:小さい所から手を付ける。小さい所から改修すれば自分も理解できる。理解が進めばおおきいリファクタもできる。

モンスターその1:箇条書きメソッド
トランザクションで処理したいがために大きくなってしまったメソッド
処理毎に空白行が入ってたりするが、そのセクションを安直に抽出してはいけない。別セクションで生成されたローカル変数にアクセスしてる可能性がある。


モンスターその2:錯乱メソッド
インデントされた1つの大きなセクションから構成されるメソッド

リファクタリングツールで立ち向かう
ツールを使ってとにかくメソッドの抽出のみを行う。
元のメソッドの単純化だけを行う。並び替えや式の分解など、振る舞いに影響しそうなところは一切手を付けない。

抽出の目的は
1.厄介な依存関係からロジックを切り離す。
2.接合部となりうるメソッドを抽出する。→メソッド化すればオーバーライドできる。(=接合点ができた!)

手動によるリファクタリングの失敗有る有る
・抽出したメソッドに変数をわたしわすれる。
・メソッド名がかぶる
・戻り値を間違える

検出用変数を仕込んで、テストを書いて、リファクタする
・正常と異常のテストを用意
・そのデータで分岐している所、振る舞いが変わるポイントを抽出する。

結合カウントの小さいメソッドの抽出
結合カウントとは、シグニチャの引数の数+戻り値=いわゆる本線とサブルーチンの依存関係
0の場合はvoid hoge()・・・メンバ変数ゴリゴリとか外部をハンドリングするとか。

依存関係のおち穂拾い
簡単にロジック変えられそう・・・でも変えられないという時に。
1.重要部分のテストを書く。テスト対象になってないところを別メソッドに抽出する。

メソッドオブジェクトの取り出し
そのメソッドが係るオブジェクトを引数にもつコンストラクタと、元の処理を行うexecuteメソッドを持つクラスを新たにつくる。
後は呼ぶだけ。関連するデータやオブジェクトはメンバ変数にできるため、検出も行いやすい

骨組みと処理シーケンス
メソッド抽出はこの2つの視点ですることができる。
骨組み→処理だけを抽出する。分岐条件は本線で。
処理シーケンス→分岐と処理をセットで抽出する。その条件の時まさに何をしているか?がわかる。
処理シーケンスの場合、抽出したメソッド名がローカル/メンバ変数名に似ていた場合、その変数のクラスにロジックをぶち込める


抽出するメソッドは極力クエリによせる。コマンドにはしない。


23.どうすれば何も壊していないことを確認できるでしょうか?
目的:変更し忘れや凡ミスを減らす
結論:TDD。テストがあれば壊れてないことが確認できるので余計な心配に駆られることが少なくなる

単一目的の編集
TDDと組み合わせる。一度に多くの変更を加えないこと。変更→テスト→変更→テスト・・・

シグネチャの維持
シグネチャを維持することでメソッド呼び出しでの凡ミスがへらせる。

コンパイラ任せ
変更点をコンパイラに探してもらう。エラーをうまく使う。
ただし、インタフェースに抽出しているメソッド呼び出しや、
スーパークラスでメソッドが定義済みである場合はコンパイラエラーにならないので気をつけるべし。

ペアプロ
ペアプロはいいですよ



24.もうウンザリです。何も改善できません。
リファクタは重要です。