フィールドの移動
動機
データ構造が正しくないとわかったら、すぐに変更することが重要です。データ構造の欠陥を放置すると、その後長きにわたって、思考を混乱させ、コードを複雑化する原因となる。
あるレコードを関数に渡す際に、必ず別レコードのフィールドも渡す必要がある場合、フィールドを移動したくなります。まとめて関数に渡すデータは、通常なら同じレコードにまとめるべきで、それによりデータの関係が明確になる。あるレコードを更新するたびに別レコードのフィールドも更新していることは、フィールドの場所が間違っていることを示唆している。複数の場所にある同じフィールドを更新しなければならないことは、フィールドを別の場所に移動して一度だけで更新できるようにすべきことを示している。
フィールドの移動は、通常、より広範囲な変更の一部として行います。フィールドの移動が完了すると、そのフィールドの利用プログラムの多くにとっては、移動先のオブジェクトのほうが移動元よりも適切なデータのアクセス先となる。しかし、そのリファクタリングは後回しにする。別のケースとして、データの利用方法がネックになり、その時点では「フィールドの移動」を行えない場合がある。そうしたときには最初にデータの利用側をリファクタリングし、その後でフィールドを移動する必要がある。
手順
- 移動元のフィールドをカプセル化する。
- テスト
- 移動先にフィールド(およびアクセサ)を作成する。
- 静的解析を実行する。
- 移動元のオブジェクトから移動先のオブジェクトを参照できるようにする。 移動先への参照として、既存のフィールドやメソッドが使えるかもしれない。使えない場合は、参照用メソッドを簡単に作れるかどうかを調べる。うまくいかない場合は、移動元のオブジェクトに移動先のオブジェクトを格納する新しいフィールドを作成する必要があるかもしれない。これを恒久的な変更としてもよいが、より広範囲のリファクタリングがある程度進むまでの一時的な変更としてもよい。
- 移動先のフィールドを使うようにアクセサを調整する。 移動先のオブジェクトが移動元のオブジェクト間で共有される場合は、移動先と移動元の両方のフィールドを更新するように setter を変更した上で「アサーションの導入」を施し矛盾する更新を検出できるようにする。矛盾する更新がないと判断できたら、移動先のフィールドを使うようにアクセサを変更する。
- テスト
- 移動元のフィールドを削除する。
- テスト