리팩터링/리팩터링 기법

리팩터링 기법. 필드 옮기기(Move Field)

developer-tj 2023. 3. 22. 12:00
반응형

필드 옮기기(Move Field)는 클래스의 필드를 다른 클래스로 옮기는 리팩터링 기법 중 하나입니다.

클래스의 필드는 그 클래스가 속한 책임 영역에 해당하는 데이터여야 하지만, 때로는 다른 클래스와 관련된 데이터가 되기도 합니다.
이럴 때는 그 필드를 다른 클래스로 이동시켜야 합니다.
이 기법은 두 클래스 사이의 결합도를 줄여주고, 데이터와 책임이 더 잘 어울리도록 만들어줍니다.

필드를 옮길 때는 먼저 이 필드가 다른 클래스에서 사용될지, 아니면 새로운 클래스가 필요한지를 결정해야 합니다.
새로운 클래스가 필요하다면, 먼저 그 클래스를 작성하고, 이전 클래스의 필드를 새 클래스의 필드로 옮기고, 이전 클래스에서는 그 필드에 대한 getter, setter 메서드를 작성합니다.
그리고 이전 클래스의 메서드에서는 새 클래스의 인스턴스를 사용하도록 수정합니다.


다음은 Customer 클래스에는 이름(name), 이메일(email), 주소(address)라는 필드들이 있습니다.


class Customer {
public:
    Customer(std::string name, std::string email, Address address) 
        : _name(name), _email(email), _address(address) {}

    std::string getName() const { return _name; }
    void setName(std::string name) { _name = name; }

    std::string getEmail() const { return _email; }
    void setEmail(std::string email) { _email = email; }

    Address getAddress() const { return _address; }
    void setAddress(Address address) { _address = address; }

private:
    std::string _name;
    std::string _email;
    Address _address;
};

이메일 필드를 다른 클래스에서도 사용될수 있습니다.
필드 옮기기를 적용하여 이메일 필드를 별도의 Email 클래스로 추출합니다.


class Email {
public:
    Email(std::string address) : _address(address) {}

    std::string getAddress() const { return _address; }
    void setAddress(std::string address) { _address = address; }

private:
    std::string _address;
};

class Customer {
public:
    Customer(std::string name, Email email, Address address) 
        : _name(name), _email(email), _address(address) {}

    std::string getName() const { return _name; }
    void setName(std::string name) { _name = name; }

    Email getEmail() const { return _email; }
    void setEmail(Email email) { _email = email; }

    Address getAddress() const { return _address; }
    void setAddress(Address address) { _address = address; }

private:
    std::string _name;
    Email _email;
    Address _address;
};

이제 Email 클래스를 만들어서 Customer 클래스에서 이메일 필드를 Email 타입으로 바꿔주었습니다.
이제 Customer 클래스에서는 이름(name), 주소(address) 필드와 Email 클래스에서 정의한 getEmail(), setEmail() 메소드만 사용하게 되었습니다.

필드 옮기기를 사용하기 전에는 이메일 정보가 변경될때 Customer 클래스을 포함한 이메일을 사용한 모든 클래스를 각각 수정이 필요하여 산탄총 수술(Shotgun Surgery)이 발생합니다.
필드 옮기기를 사용한 뒤에는 Email 클래스만 수정하는 것으로 해결할 수 있습니다.