Combine Functions Transform

関数群の変換への集約 動機 ソフトウェアの多くは、プログラムにデータを投入して、そこからさまざまな派生情報を計算する処理を含んでいる。派生値はさまざまな箇所で必要になり、派生値が参照されるたびに繰り返される。 こうした派生値はまとめるのが望ましく、一貫した探しやすい場所で更新がおこなわれるようにして、重複したロジックは避けるべき。 その1つの方法はデータ変換関数を使うことです。これは元データを入力としてすべての派生値を計算し、それらを出力データのフィールドとして設定するものです。そうすることで、派生値について調べたいときは変換関数だけを見ればよくなる。 もう1つの方法が「関数群のクラスへの集約」。元データに基づいてクラスを構成し、ロジックをそのクラスのメソッドに移す。 重要な違いは、元データがコード内で更新される場合は、クラスを使うほうが良い。変換関数を使うと派生データが新たなレコードに保持されます。そのため元のデータが変更されると不整合が生じる。 関数群を集約したい理由として、派生値を求めるロジックの重複をさけたいということがある。それだけなら、単に「関数の抽出」をロジックに適用する手もあるが、関数が扱うデータ構造と近い位置に置かれていないと、関数を見つけ出すのが難しくなる。変換関数を使うと、探すのが容易になり利用もしやすくなる。 手順 変換されるレコードを入力とし、同じ値を返す変換関数を作る。 通常、この関数の中ではレコードのディープコピーが行われる。この変換によって元のレコードが変更されていないことを確認するテストを書くとよい。 ロジックを選んでその本体を変換関数側に移し、レコードに新たなフィールドを設ける。そのフィールドを使うようにクライアント側のコードを変更する。 ロジックが複雑ならば、まず「関数の抽出」を施す。 テスト その他の関連した関数群について上記の手順を繰り返す。

February 21, 2022

Combine Functions Into Class

関数群のクラスへの集約 動機 共通のデータに対して互いに関わりの深い処理を行う一群の関数があれば、クラスを定義するチャンスと考える。(共通データは通常は関数呼び出しの際に引数として渡さる。)クラスを使うことで、これらの関数が共有する環境がより明示的になり、関数の引数が大幅に減ることで、オブジェクト内の関数呼び出しを単純化できます。そうしたオブジェクトをシステムの他の部分に参照として渡すのも容易になる。 このリファクタリングは既存の関数群を体系化するだけではなく、他で断片的に計算を行っている箇所を特定し、新たなクラスのメソッドとしてリファクタリングする良い機会も与えてくれる。 手順 関数間で共有しているデータのレコードに「レコードのカプセル化」を施す。 関数間で共有しているデータが、レコード構造としてまとめられていない場合は、「パラメータオブジェクトの導入」を施し、それらをまとめるレコードを作る。 「関数の移動」を適用して、共通のレコードを扱う関数をそれぞれ、新たなクラスへと移す。 関数呼び出しの引数のうち、クラスのメンバになっているものは、引数のリストから取り除くことができる。 データを操作するロジックの断片があればそれぞれ、「関数の抽出」で抽出してクラスに移す。

February 20, 2022

Introduce Parameter Object

パラメータオブジェクトの導入 動機 データ構造体にまとめることには意味があり、データ項目間の関係を明示するとができる。 新たな構造体を使えば、関数のパラメータ数は少なくて済みます。その構造体を使うすべての関数が、構造体の要素を取得するのに同じ名前を使うことで、一貫性の向上にも役立ちます。 このリファクタリングの真価は、コードにより深い変化を引き起こすことにあります。新たな構造体を特定したら、その構造体を使うようにプログラムの振る舞いを改めます。一連の共通関数群になることも、データ構造とそれらの関数を組み合わせたクラスになることもあります。この過程でコードの概念的な構図が変化することもある。そうした構造体を新たな抽象に引き上げると、問題領域の理解がすっきりする。 手順 ふさわしい構造体がまだ存在しないなら、作成する。 後で振る舞いをまとめやすいのでクラスにすることが多い、構造体が「値オブジェクト」なのか確認するとよい。 テスト 関数宣言の変更を施し、新たな構造体用のパラメータを追加する テスト 新たな構造体の正しいインスタンスを渡すように各呼び出し側を修正する。1つの呼び出しを修正するごとにテストする 元のパラメータを使用している箇所を、新たな構造体の要素を使うように1つひとつ置き換える。元のパラメータを削除し、テストする。

February 20, 2022

Rename Variable

変数名の変更 動機 変数はうまく名前を付けさえすれば、目的説明する上で非常に役立ちます。しかし注意深く考えていない場合やユーザーのニーズが変わってプログラムの目的が変わったから、などがあり不適切な名前となることがある。 手順 変数が広く使われている場合、「変数のカプセル化」を検討する。 変数への参照をくまなく探し、それらをすべて変更数。 変数が別のコードベースから参照されている場合、その変数は公開されているので、このリファクタリングを行うことはできない。 変数が変更されない場合、変数を新たな名前の変数にコピーしてから、徐々に置き換えていき、その都度テストする テスト

February 20, 2022

Encapsulate Variable

変数のカプセル化 動機 スコープが大きくなるにつれて変更が困難になっていく。そのため広い範囲でデータを移動したいといは、カプセル化して、変数へのアクセスを関数経由にするのが非常に良いやり方。これでデータの再構成という困難な作業を、関数の再構成というより簡単な作業に変えることができる。 それ以外にデータの変更や参照を監視できるという明確な利点を得られる。データ更新の際の検証や後処理を追加するのも簡単。 スコープが1つの関数より大きいものは、関数を通じてのみアクセスできるようにし、データのスコープが大きくなるほどカプセル化はより重要になる。 手順 変数を参照・更新するためのカプセル化用関数を作る。 静的チェックを実行する。 変数への参照を、1つひとつ適切なカプセル化関数の呼び出しに置き換える。置き換えるごとにテストする。 変数の可視性を制限する。 変数への直接アクセスを防げないことがよくある。その場合、変数名を変更してテストすることで、置き換えが漏れた参照を見つけることができる。 テスト 変数の値がレコードの場合、「レコードのカプセル化」を検討する。

February 20, 2022