📘 Effective Java

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

loose 2022. 9. 2. 16:07
반응형

빌더 패턴

 

@Builder
public Member(String name, String email, String picture, Role role) {
        this.name = name;
        this.email = email;
        this.picture = picture;
        this.role = role;
}
Member.builder()
                .name(name)
                .email(email)
                .picture(picture)
                .role(role)
                .build();

생성자에 @Builder를 걸면 아래와 같이 사용가능하다.

빌더 패턴은 점층적 생성자 패턴와 자바빈즈 패턴의 장점만을 따다 만든 패턴이다.

정적 팩토리 메소드나 생성자를 사용할 때 매개변수가 많다면 빌더 패턴을 이용하는 것이 좋다.

 

점층적 생성자 패턴과 자바빈즈 패턴

 

점층적 생성자 패턴은 메소드 오버로딩 방식으로 생성자를 결정하는 방식이다.

매개변수의 개수에 따라 생성자가 여러개 사용된다는 단점이 있다.

 

자바빈즈 패턴은 생성자에 던지는 변수들을 빼고 메소드로 대체하는 방식이다.

메소드를 이용해 변수 값을 대신 결정하는 방식을 말한다. 보통 Setter 방식을 떠올리면 된다. 

장점으로는 생성자 매개변수 순서에 제약이 없다. 그러므로 매개변수가 많을 때 장점을 가진다. 단점으로는 변수 하나를 설정하기 위해 메소드를 한번 호출해야한다. 

 

빌더 패턴의 또 다른 장점

 

빌더 패턴은 계층 클래스 구조일 때 형변환 없이 연쇄적으로 작용이 가능하다. 무슨 말이냐면 계층적으로 구분된 클래스에 전부 빌더 패턴을 적용하면 빌더 패턴의 특징인 자기 자신을 return한다라는 특징 때문에 형변환 없이 연쇄작용으로 객체를 손쉽게 만들 수 있다.

 

장단점

 

개인적으로 생각하는 빌더 패턴의 장점

 

빌더 패턴을 사용할 때 가장 큰 장점은 자바빈즈 패턴의 장점인 매개변수의 순서에 집중하지 않아도 된다는 점이다. 

선택적인 속성을 설정하거나 여러 단계의 초기화 과정을 갖는 객체를 생성하는 데 적합

 

개인적으로 생각하는 빌더 패턴의 단점

 

캡슐화가 안된다. Item 1에서 정적 팩토리 메서드를 사용할 때 매개변수를 DTO로 감싸는 형식으로 캡슐화를 경험할 수 있었다. 근데 빌더 패턴을 쓰는 순간 캡슐화가 사라져버린다. 빌더 패턴의 매개변수들이 그대로 드러나기 때문이다. 그리고 빌더 패턴 자체로 다음에 올 개발자가 필수적으로 배워야하는 패턴될 수 있다는 단점과 연쇄 메소드로 이루어진 객체 생성 때문에 가독성이 떨어진다. 

또한 추가적인 코드 및 클래스가 필요하므로, 작은 크기의 객체나 단순한 객체 생성에는 오버헤드가 될 수 있습니다.

 

결론

 

빌더 패턴은 매개변수가 많을 때만 쓰고 나머지는 정적 팩토리 메서드를 사용하는 것을 고려하는게 좋지 않을까 생각해본다.(정적 팩토리 메서드 패턴이 가지고 있는 이점이 빌더 패턴을 쓸 때 사라지는 경향이 있기 때문에)

변수가 많을 때는 정적 팩토리 메서드 패턴이 헷갈릴 수 있을 것 같다.

개발 환경에서 가로 스크롤이 쭉쭉 뻗어나가는 걸 보고 싶지 않으면 빌더 패턴을 쓰는게 나을 것 같다.(물론 빌더 패턴도 세로로 쭉쭉 뻗어 나간다...)

사실 두 개를 선택적으로 사용하는 것은 오히려 유지보수 관점에서 일관성이 떨어져 개발자들로 하여금 더 헷갈릴 수도 있다.

기술의 장점과 효율적인 코드도 중요하지만 유지보수 측면에서는 생산성도 중요하기 때문에 어떤 패턴을 쓸지에 대한 협상은 고민이 많이 필요한 영역일 듯 하다.

개인적으로는 정적 팩토리 메소드가 무분별한 객체 생성을 막아주기 때문에 어플리케이션을 확장 가능성에 초점을 맞추고 있을 때 사용하는 것이 좋은 것 같다.

하지만 피상적인 프로젝트가 중요하고 유연하고 빠르게 개발해야 된다면 빌더 패턴을 사용하는 것이 올바르게 보인다.

 

매개변수가 너무 많을 때 대처법

 

주석을 사용하라
Builder를 수동으로 만들면 메소드를 수동으로 만들 수 있으니 필요한 요소들은 그룹화해서 만들 수 있다. 
혹은 객체들 값을 default 값 부여
필요하지 않은 요소는 생략한다.

728x90