nprogram’s blog

気ままに、プログラミングのトピックについて書いていきます

巨大クラスをクラス抽出で爆散

はじめに

巨大クラスを爆散したいときがあります。

その場合は、クラス抽出が便利です。

書籍

  • 新装版 リファクタリング 既存のコードを安全に改善する
    • 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();
    }
}

リンク

以下のサイトは、巨大クラスを爆散するのにとても役立ちます。