# リファクタリング 第3章、第4章 ## 第3章 コードの不吉な臭い ### リファクタリングをいつ行うか リファクタリングをいつ行うかは、直感で決定するため、明確な基準は無い。 判断基準となる具体的な感覚は、自ら経験し養っていかねばならない。 以下は判断基準となる「臭い」の種類について取り上げる。 ### 不吉な名前 コードの名前は、単純明快でなければならない。 そのために重要であるのが適切な名前付けである。 シンプルではあるが、最も難しいことでもある。 ### 重複したコード 同一構造のコードが複数ある場合、関数の抽出やステートメントのスライド等で1つのコードとしておくのが良い。 ### 長い関数 長い関数は短い関数に分割する。 最近のコードは関数呼び出しのタイムロスがほぼ無いため、必然的に短い関数に整えるほうがメリットが大きくなる。 関数の抽出、パラメーターや一時変数の削減、条件分岐の書き換え等を行う。 ### 長いパラメーターリスト パラメーターリストは、長すぎるとしばしば混乱を招くもとになる。 問い合わせによるパラメータの置き換えや、オブジェクトの受け渡し等で削減できる。 ### グローバルなデータ どこからでも変更可能なグローバル変数は、バグの温床となりかねない。非常に強い「臭い」のひとつである。 関数などによるカプセル化や、直接参照可能な個所の限定により、徐々にスコープを狭めていく。 ### 変更可能なデータ 変数の再定義(let, var)等、変更可能なデータは、いつ予期せぬ変更によりプログラムが動かなくなるか分からない。 変更のカプセル化(getter、setter等)や、問い合わせと更新の分離、関数群への変換の集約等で、変更可能な部分を狭めていくと良い。 ### 変更の偏り 変更箇所が1か所で済まない場合、変更の偏りが起きていると言える。 1つの目的でモジュールが使用されていない場合は、変更の偏りが生じている証拠。 フェーズの分離や関数の移動などで、データ構造を明確にすると良い。 ### 変更の分散 1つの変更をするためにあちこちのモジュールを少しずつ変えなければならない場合、変更する箇所が分散している可能性がある。 関数の移動やフィールドの移動を用いて、一つのモジュールに変更箇所をまとめ上げる。 ### 特性の横恋慕 モジュールの内部処理よりも、外部へのデータ連携の割合が大きい場合、適切な位置への関数の移動を行う事で最小限のデータ連携で済むようになる。 ### データの群れ データの集合は、同じ部分に住処をつくるべきである。 パラメータオブジェクトの導入(Javaのクラスオブジェクト)及びオブジェクトの受け渡しによって、まとまったデータを扱える。 ### 基本データ型への執着 日付や時刻、貨幣、座標等の便利な型に対し、基本データ型(主に文字列)で処理している場合は、オブジェクトによるプリミティブの置き換えが有効である。 ### 重複したスイッチ文 スイッチ文やif文は、ポリモーフィズムによる条件記述の置き換えによって解決できる。 特に必要なのは重複処理があるスイッチ文の場合である。 ### ループ for文等のループもパイプラインによる置き換えが可能である。 ### 怠け者の要素 不要な変数定義等、構造的に無意味な要素は、関数のインライン化等を行い排除すべきである。 ### 疑わしき一般化 一般化を狙った機構がそうならなかった場合や、テストケースのみに利用されている場合も、怠け者の要素と同様に排除すべきである。 ### 一時的な属性 インスタンス変数の値が特定の状況でしか設定されていない場合、変数の意味をなしていないため排除すべきである。 ### メッセージの連鎖 メッセージが延々とオブジェクトを移りわたっている状態では、ナビゲートする過程の構造にクライアントが依存してしまう。 委譲の隠蔽により連鎖を隠したり、関数の移動で連鎖を短くまとめる等の対策が必要である。 ### 仲介人 メソッドの大半が別のオブジェクトに委譲している場合は、仲介人の除去を行い、直接オブジェクトに処理させると良い。 ### インサイダー取引 モジュール間で頻繁にやり取りするような場合、モジュールの独立性が低く問題である。 関数の移動等で一つにまとめて、モジュール同士のやり取りをできるだけ行わないようにする。 逆に必要以上にまとまりすぎている場合は、適宜仲介人に委譲すると良い。 ### 巨大なクラス インスタンス変数だらけのクラスは重複したコードが出る可能性が高く、考えものである。 クラスの抽出で役割ごとにクラスを分割すると良い。 ### クラスのインターフェース不一致 他のクラスへの置き換えは、インターフェースが同様の場合に限られる。 関数宣言の変更を用いて、インターフェースを合わせる。 ### データクラス データクラスは過剰にアクセスされやすい。 不要なsetterはfinal等を設定して削除したり、必要な処理をデータクラスに移動させる等の対策がある。 ### 相続拒否 継承関係にあるにもかかわらず、スーパークラスの継承を全然使っていないような場合は、スーパークラスに独自機能がありすぎる可能性がある。独自機能はメソッドやフィールドの押し下げにより、兄弟クラスへと移すと良い。 ### コメント コメントは、「不吉な臭い」に気づく大きなヒントになる可能性がある。 コメントが必要でなくなるようなリファクタリングを実施するべきである。 ## 第4章 テストの構築 ### 自己テストコードの意義 テストコードを書くことは、適切なリファクタリングを行う上で欠かせない。 テストは新たなプログラミングを行う前に書くのが良い。何をすべきかを自問自答することになり、インターフェースが確立される。コーディングが完了する時点も明確になる。 ### テストのフレームワーク テストは、テストフレームワークの形式に則りテストコードを記述する。 以下JavaScript用 * Mocha * Chai * jest * react-testing-library 等 ### フィクスチャの変更 フィクスチャ(テスト入力するパラメータのこと)は定常的に変更される。 一般的には1つのテストには1つの検証を行う事が望ましい。 ### 境界値の検査 正常値を入力した正常処理だけでなく、異常値を入力した際の振る舞いも確認できる。 異常値を表す場合はテストが失敗するので、どこまでが正常値なのかの境界がはっきりするメリットがある。 ###### tags: `読書`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up