読者です 読者をやめる 読者になる 読者になる

プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

データの再編成

リファクタリング 8章

本読みの再開。作業と交互に読みすすめるので、今までよりペースは落ちると思う。

自己カプセル化フィールド

フィールドを直接アクセスしているが、結合関係が煩わしくなってきた → フィールドに対するget,setを作ってそれだけでアクセス

  • フィールドのアクセス方法は2種類。1つはクラス内部であれば直接アクセスできる、もう1つはクラス内部であってもアクセサを使う
  • 間接アクセスの利点はサブクラスがオーバーライドできることと遅延初期化のようにデータ管理面での柔軟性を持てること
  • 直接アクセスの利点はコードが読みやすくなること
  • このリファクタリングは、最初は直接アクセスで作り、必要になった時点で間接アクセスにするという考え方
  • 適切なタイミングは、変数をサブクラス内の計算値を置き換えたくなった時に適用する

オブジェクトによるデータ値の置き換え

追加のデータや振る舞いが必要なデータ項目がある → そのデータ項目をオブジェクトに変える

  • 最初は単純なデータ項目だったが、後に振る舞いを追加する必要が出てきた場合にオブジェクト化する

値から参照への変更

同じインスタンスが多数存在するクラスがある。それらを1つのオブジェクトに置き換えたい → そのオブジェクトを参照オブジェクトに変える

  • 参照に置き換えることによってメモリの消費量を減らしたり、値の比較をしやすくしたりする

参照から値への変更

小さくて、普遍で、コントロールが煩わしい参照オブジェクト → 値オブジェクトに変更

  • 値から参照への変更の逆
  • 参照によるアクセスが煩わしくなってきたら値へと変更する
  • 値オブジェクトは特に分散並列処理システムで有効
  • 値オブジェクトは不変

オブジェクトによる配列の置き換え

配列の各要素が、それぞれ異なる意味を持つ → その配列を、要素ごとに対応したフィールドを持つオブジェクトに置き換える

  • 配列は同種のオブジェクトのコレクションを保持するために使用するべき
  • たとえば配列の先頭のデータに特別な意味を持たせて管理している場合はオブジェクト化する

観察されるデータの複製

あるGUIコントロールでのみ有効なドメインデータが有り、ドメインメソッドからもアクセスする必要がある → そのデータをドメインオブジェクトにコピーして、それらを同期させるためのオブザーバを設ける

  • 振る舞いを階層ごとに分離するのは容易だが、データはそうは行かない。そこで、複製して同期をとるメカニズムを用意する
  • Observer/Observableの代わりにイベントリスナー使うときにもこのリファクタリングが適用出来る

単方向関連の双方向への変更

2つのクラスが互いにその特性を使う必要があるが、単方向のリンクしかない → 逆ポインタを加えて、両方の集合を更新するように更新操作を変更する

  • 逆ポインタを用いて双方向性をもたせる

双方向関連の単方向への変更

双方向関連があるが、一方のクラスはもはや他方の特性を必要としていない → 不要になった関連の一方を削除する

  • 双方向はコストが掛かり、ゾンビも生まれやすくなる。また、相互依存性を強制するのでどちらかの変更がも一方にも影響を与える
  • 双方向関連が不要になったらやめる

シンボリック定数によるマジックナンバーの置き換え

特別な意味を持った数字のリテラルがある → 定数を作り、それにふさわしい名前をつけて、そのリテラルを置き換える

フィールドのカプセル化

公開フィールドがある → 非公開にしてアクセサを用意

  • データを公開するとオブジェクトにとって未定義の動作が引き起こされる可能性が出る
  • これはリファクタリングの手順の中の1つであり、その後、このメソッドを利用しているメソッドを探し、「メソッドの移動」により適切なオブジェクトへの配置が可能かどうかなどを検討する

コレクションのカプセル化

メソッドがコレクションを返す → 読み取り専用のビューを返して、追加と削除のメソッドを提供する

  • クライアントに直接コレクションを操作させるのではなく、追加・削除をクラスによって管理する
  • コレクションに対するクライアント側での未定義の動作を回避できる
  • 結合度を低下できる

データクラスによるレコードの置き換え

古いプログラミング環境のレコード構造とインターフェースを取る必要がある → そのレコード用に、振る舞いを持たないデータオブジェクトを作る

  • 従来のAPIやデータベースとのやり取りを行うための専用クラス

クラスによるタイプコードの置き換え

振る舞いに影響しない数字のタイプコードを持つクラスがある → その数字を新しいクラスで置き換える

  • シンボリック名は可読性を高められるが別名でしかない
  • 数字をクラスに置き換えると静的な型チェックができる
  • これを行う前に他のタイプコードの置き換えについて検討する
  • タイプコードが純粋なデータである時だけタイプコードをクラスで置き換える
  • すべてのswitchはいずれ「ポリモーフィズムによる条件記述の置き換え」により取り除かれる。そのために「サブクラスによるタイプコードの置き換え」、または「State/Strategyによるタイプコードの置き換え」で対処されている必要がある

サブクラスによるタイプコードの置き換え

クラスの振る舞いに影響を与える不変のタイプコードが有る → そのタイプコードをサブクラスに置き換える

  • タイプコードが振る舞いに関係しないなら「クラスによるタイプコードの置き換え」が適用出来る
  • タイプコードが振る舞いに影響を与える時、ポリモーフィズムを利用する(switchやif)「ポリモーフィズムによる条件記述の置き換え」
  • 出来ないケースはオブジェクトが生成された後にタイプコードが変わる場合、またはタイプコードを持つクラスがすでに別の処理でサブクラス化されている場合。その場合には「State/Strategyによるタイプコードの置き換え」
  • ポリモーフィズムによる条件記述の置き換え」の土台。きっかけは条件文により処理が分岐する場合。条件文がなければ「クラスによるタイプコードの置き換え」が有効
  • このリファクタリングを使うもう一つの理由は、あるタイプコードを持つオブジェクトにだけ関連する特性が存在する場合。このリファクタリングが終われば「メソッドの引き下げ」や「フィールドの引き下げ」を行なって、サブクラスをより特化できる
  • サブタイプによる振る舞いの差異をクラス自身で持つことが可能になる。新たなバリエーションにサブクラスの追加だけで対応できる
  • バリエーションが発生し続ける場合に特に有効

State/Strategyによるタイプコードの置き換え

クラスの振る舞いに影響するタイプコードがあるが、サブクラス化は出来ない → 状態オブジェクトでタイプコードを置き換える

  • タイプコードがオブジェクトの生存期間中に変化するか、サブクラス化が不都合な理由が別にあるときに適用出来る
  • ポリモーフィズムによる条件記述の置き換え」を使うならStrategy、状態に特有なデータを移動しようとしており、オブジェクトの状態が変わる場合はState

フィールドによるサブクラスの置き換え

定数データを返すメソッドだけが異なるサブクラスがある → そのメソッドをサブクラスのフィールドに変更して、サブクラスを削除する

  • 特性や振る舞いを変えるためにサブクラスが作られる
  • 定数データだけが異なるサブクラスはスーパークラスにフィールドを追加するだけで削除できる

この記事で読み進めている本

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 94人 クリック: 3,091回
  • この商品を含むブログ (295件) を見る