コードの不吉な匂い

コードの不吉な匂い

コードの不吉な匂い」とは

リファクタリングが必要になりそうなコードから発する匂い(w

不吉な匂いの例

以下の例に当てはまるような匂いを感じ取ったとき、リファクタリングが必要となる可能性が高いです。

重複したコード

同じようなコードが2ヵ所以上存在する。コピペコード。

⇒「メソッドの抽出」/「メソッドの引き上げ」で解決できる。

長すぎるメソッド

長すぎる関数

⇒「メソッドの抽出」でメソッドを短くする。

巨大なクラス

インスタンス変数の持ちすぎ。

「重複したコード」になりやすい。

⇒クラスを機能ごとに分割する。

多すぎる引数

引数の数が多すぎると、1つ1つの引数が何を意味しているのか分かりづらくなる。

⇒1つのオブジェクトにまとめる。

変更の発散

1つの修正に対して、クラス内での影響範囲が大きい場合。

例えば、1つの仕様変更に対して、3つのメソッドを修正しなければならない、ようなケース。

⇒「クラスの抽出」でクラスを分割する。

変更の分散

1つの修正に対して、クラス外への影響範囲が大きい場合。

例えば、1つの仕様変更に対して、複数のクラスのコードを修正しなければならない、ようなケース。

⇒「メソッドの移動」や「フィールドの移動」を行い、クラスをまとめる。

属性、操作の横恋慕

クラス内のあるメソッドが、別のクラスの属性や操作を頻繁に呼び出す場合。

⇒「メソッドの移動」で横恋慕メソッドを別クラスへ移す、または別クラスのメソッドをクラス内に統合する。

データの群れ

複数のデータが、あちこちのクラスやメソッドを飛び回る場合。

⇒「クラスの抽出」でデータを1つのクラスに統合する。

基本データ型への執着

基本データ(int/floatなど)のみの冗長なコード。

⇒「オブジェクトによるデータ値の置き換え」により、冗長なコードを削減する。

スイッチ文

長すぎるswitch文。

⇒「ポリモーフィズムによる条件記述の置き換え」を検討する。

パラレル継承

「変更の分散」の特殊ケース。

サブクラスを定義するたびに、別の継承ツリーにもサブクラスを定義しなければならないケース。

⇒「メソッドの移動」「フィールドの移動」により、継承構造を廃止していく。

怠け者クラス

あまり使われないクラス。

⇒「階層の平坦化」「クラスのインライン化」により、クラスを廃止していく。

疑わしき一般化

あまりにも汎用的な機能を詰め込み、その機能がほとんど使われないようなクラス。

ヘルパークラスなんかにありがち。

⇒「階層の平坦化」「クラスのインライン化」により、クラスをシェイプアップする。

一時的属性

特定の状況(メソッド)でしか使用されない属性。

⇒「クラスの抽出」で、属性を取り除く。

メッセージ連鎖

クラス間のメッセージの過剰な連鎖

複数のクラスのgetXxxxxが長々とつながっているようなケース。

⇒「委譲の隠蔽」で仲介人にメッセージ連鎖を任せる。

仲介人

仲介人が多すぎる場合。

⇒「仲介人の除去」「メソッドのインライン化」で直接処理するようにしてみる。

不適切な関係

クラス同士の親密なやり取りが多い場合。

⇒「メソッドの移動」「フィールドの移動」で、クラス間の距離を適度に置くようにする。

クラスのインターフェース不一致

処理は同じなのにシグニチャのみが異なるメソッド。

⇒「メソッド名の変更」でメソッドのネーミングを正しいものにする。

未熟なクラスライブラリ

始めから万能なライブラリは存在しない。

ライブラリの修正が不可能、または混沌とした形での修正しかできない。

⇒「外部メソッドの導入」「局所的拡張の導入」

データクラス

属性とget/set以外に何も持たないクラス。

⇒単なるデータ保持用であるため、「フィールドのカプセル化」を行う。

相続拒否

親の属性をあまり使わないサブクラス

⇒「メソッドの引き下げ」「フィールドの引き下げ」で、使われない属性/操作を兄弟クラスに移す。

コメント

過剰なコメント

⇒「メソッドの抽出」「メソッド名の変更」でコメントを減らす。