レガシーコード改善ガイド 20章 このクラスは大きすぎてもうこれ以上大きくしたくありません


前提

レガシーコード改善ガイドのoutputを章ごとにやってます。
自分のoutputとある程度の人に伝わったらラッキー程度の考えを前提にしているので、分かりやすい記事ではないです。
イラストもないので、完全に理解したい人は書籍を読みましょう。

概要

肥大化したクラスは単一責務の原則に基づいてクラスの分割を行う必要がある。その時は機能スケッチを用いて、見える化することで分割が容易になる。依存関係が強く分割することが困難なクラスの場合はまず、インターフェースの分離を行い、クラス間の依存関係を軽減してリファクタを行いましょう。

説明

実装しているとついつい、既存のクラスに関数を追加してしまいたくなる。もしくは自分以外の誰かがこういうことをして、肥大化し複数責務を請負ったクラスをみたことがあるのではないか?そのときに振り返るべきのが原則。
オブジェクト思考のクラス設計の原則はやはりSOLID原則

  • Single Responsibility Principle:単一責務の原則
  • Open/closed principle:オープン/クロースドの原則
  • Liskov substitution principle:リスコフの置換原則
  • Interface segregation principle:インターフェース分離の原則
  • Dependency inversion principle:依存性逆転の原則

リファクタをする指針としては、この単一責務の原則にそっているのか?を判別軸にして、単一責務でなければリファクタをする。
その際の単一責務かどうかを判別するにはテストがしやすいか?一文で名言化できるか?で単一責務であるかどうかがわかる。
両方の判別方法にクリアすれば問題ない。クリアしなかった場合、リファクタを進める。
リファクタをするにあたり、どのようなクラスに分割すれば良いのか?を考える。その時の手法が

  • 関数名を参照して、同様の名前がついている関数だけをまとめ上げて別クラスに移動する。
  • 変数と関数の関係性をイラストで表現する機能スケッチを行い、同じ処理をしているものたちだけまとめあげてクラスを移動する。

である。機能スケッチとは、どの関数が何を利用していて、どのような関係性なのかをぱっと見で把握しやすくし、別クラスに移動できそうな関数・変数群を識別するための手法である。作成するには、まず変数一式を一列に書き出す。それにたいして関数を一つずつ追記し、追記した関数が利用している変数もしくは別の関数に対して矢印を記載する。これにより変数・関数同士の依存関係がぱっと見でわかるようになる。
この依存関係にのっとって、別クラスに分割できそうなものは分割する。分割した結果、相互に利用がしづらくなった場合は依存の関係性を変えたりすることで改善が可能になるケースもある。
また、依存関係が多く、改善が容易でない場合インターフェース分離の原則に則り、クラス間の依存度を軽減する。

リファクタを実施するにあたり

前提として、現在の構成でもアプリケーションは安定稼働していることを認識し、またリファクタでテストを以下に追加したとしてもリファクタ直後は不安定になることを認識しましょう。それでもリファクタをした方が、今後のコストが回収できるのであればリファクタを実施しましょう。