Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第31章 リファクタリング #37

Open
at-grandpa opened this issue Jan 12, 2018 · 11 comments
Open

第31章 リファクタリング #37

at-grandpa opened this issue Jan 12, 2018 · 11 comments

Comments

@at-grandpa
Copy link
Owner

  • システムの設定変更を大きな変更であっても、小さなステップの積み重ねで行っていくパターン
  • TDDのリファクタリングは、テストさえ通れば、べた書きでもそれをリファクタリングという
  • 考えつく限りのテストを書く
  • 網羅性が大事
  • 問題がありそうだったけど、他のテストが全部通ったのでコミットした、は許されない
@at-grandpa
Copy link
Owner Author

差異をなくす

  • よく似ているコードの共通化をしたい
    • コードの内容をだんだん近づけていって、完全に一致したら一つにする
  • 精神をすり減らすリファクタリングもある
  • 小さいステップと具体的なフィードバックに基づいた戦略を使う
  • 良く出会うリファクタリング
    • 二つのループが似ている。一致させればmergeできる
    • 条件分岐の中身が似ている。一致させれば分岐を取り除ける
    • メソッドが良く似ている。一致させれば1つ消せる
    • クラスが似ている。一致させれば1つ消せる
  • ゴールから考えながら差異をなくすパターンもある
  • サブクラスのメソッドを一つずつ親クラスのメソッドと一致させ、親クラスへ移動し、空っぽになったサブクラスを消す

@at-grandpa
Copy link
Owner Author

変更の分離

  • 複数の部分から構成されるメソッドやオブジェクトを変更したい
    • 変更すべき部分を分離独立させよう
  • メソッド抽出、オブジェクトの抽出、メソッドオブジェクト、などがある

@at-grandpa
Copy link
Owner Author

データ構造の変更

  • データの持ち方を変えるにはどうするか
    • データを一時的に複製する
  • 方法
    • 内側から外側へと向かう方法
      • 内部構造を書き換えた後に外部インターフェイスを変更する
          1. 新構造の為のインスタンス変数を定義
          1. 旧構造でデータが設定されている部分をその変数に置き換える
          1. 旧構造のデータを使っている部分をその変数に置き換える
          1. 旧構造のコードを消す
          1. 外部インターフェイスを新構造に反映する
    • APIの側から変更を行いたい場合
        1. 新構造のパラメータを追加する
        1. 新構造のパラメータを内部で旧構造に変換する
        1. 旧構造のパラメータを削除する
        1. 旧構造を使っている部分を新構造に置き換えていく
        1. 旧構造のコードを削除する
  • 理由
    • 「一から多へ」の変更のときに、データをどうするかが悩み
    • 手順
      • コレクションの入れ物を定義
      • 単一のデータをインスタンス変数に設定している箇所の近くに、コレクションに追加するコードを書く
      • 単一のデータの代わりにテストのコレクションを使うように変更する
        • この時点では、コレクションに一つのデータしか入っていないので、処理全体の意味合いは変わっていない
  • プロトコルは違うが、同等のフォーマットのものに移行するテクニック

@at-grandpa
Copy link
Owner Author

メソッドの抽出

  • 込み入った長いメソッドを読みやすくしたい
    • 一部をメソッドに分離しよう
  • 方法
      1. 新しく切り出す部分を探す。ループの中身やループ全体、条件分岐の各分岐など
      1. 抽出する範囲の外で一時変数への代入が行われていないことを確認する
      1. 旧メソッドから該当範囲をコピーし、コンパイルする
      1. 旧メソッドの一時変数やパラメータの中で新メソッドから使うものを、新メソッドのパラメータに追加する
      1. 旧メソッドの中から新メソッドを呼び出す
    • まー、あたりまえのことっぽい
  • 理由
    • 部分に名前を付けられる
    • 理解が進む

@at-grandpa
Copy link
Owner Author

メソッドのインライン化

  • メソッド抽出の逆
  • メソッドそのものの処理で置き換える
  • 方法
    • まーイメージどおり
  • 理由
    • 何が実際に行われているか確認できる
    • 分離されていた箇所を横断してリファクタリングできる
    • 結局は全体感を把握できていれば、修正する幅も広がるよね、ということ

@at-grandpa
Copy link
Owner Author

インターフェースの抽出

  • ある処理の実装をもう1種類作る時
    • インターフェースを作り、共通の処理を括りだす
  • インターフェースを実装していきましょうという話
  • 最初の実装を終えて、次の実装に進んでいるとこに発生しやすい
  • 名前付け大事

@at-grandpa
Copy link
Owner Author

at-grandpa commented Jan 12, 2018

メソッドの移動

  • メソッドを移動させたい
    • あるべきところにメソッドを加え、それを呼び出すようにする
  • あたり前っちゃ当たり前
  • メソッド内でフィールドへの代入が行われていた場合は諦める
  • ある箇所で、他のオブジェクトのメソッドが複数回呼ばれていたら、移動する時がきた証拠
  • 利点
    • 対象コードの意味が深くわかっていなくても、1つのオブジェクトに対して複数回のメソッドが呼ばれていたら、移動のサイン
    • 素早く安全に行う手順がある
    • 目を見張る結果になることが多い

@at-grandpa
Copy link
Owner Author

メソッドオブジェクト

  • 複数のパラメータやローカル変数を必要とする込み入ったメソッドを表現する
    • メソッドをオブジェクト化してしまう
  • ローカル変数はそのオブジェクトのインスタンス変数
  • 単一メソッドrunを定義し、元のメソッドと同一な処理にする
  • こうすると整理できる
  • 新しいロジックを導入する準備段階に有用
  • テストもしやすくなる
  • パラメータや一時変数だらけのメソッドはメソッドの抽出をやりにくい
    • 膨大な一時変数やパラメータの数になる
    • こういったメソッドを抽出するのに、メソッドオブジェクトは有用

@at-grandpa
Copy link
Owner Author

パラメータの追加

  • 新しくパラメータを追加したい
  • 追加したらコンパイルエラーを活用して、修正点を調べる

@at-grandpa
Copy link
Owner Author

メソッドからコンストラクタへのパラメータの移動

  • メソッドからコンストラクタにパラメータを移動するにはどうするか
    • 一箇所ずつ変更してはテストをまわし、全て変更したら不要箇所を消す
    • めっちゃ小刻みにいこう

@at-grandpa
Copy link
Owner Author

この章で得た知見

  • 安全にコードを変更していく手順
  • 一気にやってしまいがちだけど、そうすると手戻りが痛い
  • ポイントは「本当に小さなステップで行うこと」
  • すぐにおかしくなったら戻して考える
  • それが最速になるのだ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant