본문 바로가기
개발/Effective Java

[Effective Java] 생성자에 매개변수가 많다면 빌더를 고려하라

by 손너잘 2022. 1. 3.

실제로, 프로젝트를 진행하면서 클래스의 매개변수가 많은 경우 빌더를 즐겨 사용했다.

그리고 책에서 나온것 같이 setter를 사용하여 불변식을 지키지 못하는 상황을 방지할 수 있는 점, 그리고 생성자에 값을 잘못 넣을 가능성을 없앨 수 있다는 점에서 정말 좋다고 생각한다.

 

하지만 그 전에 생각해야 할 부분이 있다. 애초에 필드가 왜 많아야 하는가? SRP를 제대로 준수했다면 필드가 많을 필요가 없다.

만일 파사드 패턴과 같은 상황으로 인해 필드가 많아지는 경우는 어떡하는가?

생각해보면 이런 경우는 필드가 또 다른 객체로 이루어져 있다. 객체 필드의 의미와 타입의 중복이 없고 이는 생성자를 통해 객체를 생성하더라도 잘못된 데이터를 넣을 가능성 낮출 수 있으며 정합성 또한 보장 가능해진다.

 

내가 빌더를 주로 사용하는 경우는 Test Fixture를 만들때이다. 만일 어느 객체의 테스트용 Fixture를 만드는데 특정 필드는 고정된 값이어도 되며 필요에 따라 변경 가능하게 할 때, 그리고 그와 동시에 다른 필드는 값 정의가 필요할 떄 builder를 사용해서 Fixture를 간편히 만들 수 있게 한다.

예시는 아래와 같다.

 

public class User {

    private final String name;
    private final int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class TUser {

    public static Builder builder() {
        return new Builder();
    }

    private static class Builder {
        private String name = "손너잘";
        private int age;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder age(int age) {
            this.age = age;
            return this;
        }

        public User build() {
            return new User(
                name,
                age
            );
        }
    }
}

User는 도메인이며 TUser는 Fixture를 생성하기 위한 Builder를 정의한 객체이더. 이런식으로 빌더를 이용해 Fixture용 객체를 생성하면 테스트를 위해 도메인 객체를 건들지 않으면서, 동시에 간편하게 Fixture를 만들 수 있다.

Builder에서 name이 기본적으로 초기화 되어있기 때문에 사용자는 name을 정의하지 않고도 간편히 age만 정의하여 User를 만들어낼 수 있으며 이를 통해 fixture를 생성하는 코드라인을 줄이는 이점 또한 갖는다.

 

하지만 이 방식도 단점은 있다. 바로 TUser가 User에 강하게 의존하기 때문에 User의 필드가 변경되던가 하면 TUser도 변경되어야 한다. 하지만 그럼에도 불구하도 나는 이 방식을 선호하며 실제로 매우 편하기도 하다.

댓글