はじめに
巨大クラスを爆散したいときがあります。
その場合は、クラス抽出が便利です。
書籍
- 新装版 リファクタリング 既存のコードを安全に改善する
- Martin Fowler [著]
手順
(1) クラスの責務を切り出す方法を決める
(2) 切り出された責務を記述する新たなクラスを作る
(3) 元の暮らすから新たなクラスにリンクを貼る
(4) 移動しようとする各フィールドに「フィールドの移動(p146)」を適用する
(5) 移動が終わるごとにコンパイルしてテストする
(6) メソッドの移動(p142)を適用して元の暮らすから新たなクラスにメソッドを移動する
(7) 移動が終わるごとにコンパイルしてテストする
(8) 各クラスのインタフェースを見直して、減らす
(9) 新たなクラスを公開するか、公開するならそれを参照オブジェクトとして公開するのか、不変な値オブジェクトとして公開するのか決める
例
Personクラスの中に、電話番号のインスタンスがあります。
クラス分割を行い、Personクラスが持つ電話番号関連の責務を別クラスに持たせましょう。
分割前
import java.util.*; public class Main { public static void main(String[] args) throws Exception { Person person = new Person("Tom", "123-", "123-4567"); System.out.println(person.getName()); System.out.println(person.getTelepthonNumber()); System.out.println(person.getOfficeNumber()); } }
public class Person { private String _name; private String _officeAreaCode; private String _officeNumber; public Person(String name, String AreaCode, String number) { _name = name; _officeAreaCode = AreaCode; _officeNumber = number; } public String getName() { return _name; } public String getTelepthonNumber() { return _officeAreaCode + _officeNumber; } void setOfficeAreaCode(String arg) { _officeAreaCode = arg; } String getOfficeNumber() { return _officeNumber; } void setOfficeNumber(String arg) { _officeNumber = arg; } }
分割後
import java.util.*; public class Main { public static void main(String[] args) throws Exception { Person person = new Person("Tom", "123-", "123-4567"); System.out.println(person.getName()); System.out.println(person.getTelepthonNumber()); System.out.println(person.getOfficeNumber()); } }
public class Person { private String _name; private final Telephone telephone; public Person(String name, String areaCode, String number) { _name = name; telephone = new Telephone(areaCode, number); } public String getName() { return _name; } public String getTelepthonNumber() { return telephone.getTelepthonNumber(); } public String getOfficeNumber() { return telephone.getOfficeNumber(); } public String getAreaCode() { return telephone.getAreaCode(); } }
public class Person { private String _name; private final Telephone telephone; public Person(String name, String areaCode, String number) { _name = name; telephone = new Telephone(areaCode, number); } public String getName() { return _name; } public String getTelepthonNumber() { return telephone.getTelepthonNumber(); } public String getOfficeNumber() { return telephone.getOfficeNumber(); } public String getAreaCode() { return telephone.getAreaCode(); } }
リンク
以下のサイトは、巨大クラスを爆散するのにとても役立ちます。
- 役割駆動設計で巨大クラスを爆殺する
- https://qiita.com/MinoDriven/items/2a378a09638e234d8614