저번에 지나가다가 본건데 제 동심이 짓밟혔어요
문득 엔티티 클래스에 @Builder를 붙이다가 생각이 들었습니다.
왜 @AllArgsConstructor 쓰지 말라고 했더라.
그리고 여러 프로젝트에서 @Builder와 함께 @AllArgsConstructor를 쓰는 것에 대해서
@AllArgsConstructor는 클래스에 존재하는 모든 필드에 대한 생성자를 자동으로 생성하는데, 인스턴스 멤버의 선언 순서에 영향을 받기 때문에 변수의 순서를 바꾸면 생성자의 입력 값 순서도 바뀌게 되어 검출되지 않는 치명적인 오류를 발생시킬 수 있습니다.
본 주제를 검색했을 때 블로그들에 복붙으로 여럿 적혀있는 글이다. 검출되지 않는 치명적인 오류
라는 것은 조금 과장인 것 같아요.
정확히는 순서가 바뀐 필드가 타입이 같은 경우에는 런타임에 에러가 발생할 수 있기 때문에 주의가 필요합니다.
+ 당연히 순서가 바뀔 때 뿐 아닌, 필드가 추가되는 경우도 문제가 됩니다.
예시
기존에 작성해둔 코드
@AllArgsConstructor
class Person {
private String name;
private int age;
}
아래와 같이 인스턴스를 생성할 것이에요
Person person = new Person("김철수", 25);
그런데 다른 개발자가 필드의 순서를 바꾸었습니다.
@AllArgsConstructor
class Person {
private int age;
private String name;
}
어딘가에서 person을 만들고 있던 아래 코드는 오류가 발생할 것입니다.
Person person = new Person("김철수", 25);
이에 대한 대책으로 이미 빌더 패턴을 잘 적용하시고 있을 것 같습니다. 그리고 Lombok의 @Builder
를 많이 쓰시지 않을까 싶어요.
만약 JPA 엔티티 클래스라면 @NoArgsConstructor(access = AccessLevel.PROTECTED)
를 붙여서 사용하고 계실 것 같습니다.
@Builder
는 생성자가 없는 경우에 모든 필드를 파라미터로 받는 생성자를 만들지만, 위 경우에는 따로 생성자를 만들지 않아 문제가 됩니다.
제가 블로그랑 오픈소스 여럿 찾아보니까 보통 두 방향으로 하는 것 같은데요
@AllArgsConstructor
쓰기아무래도 빌더 패턴으로만 객체를 만들자고 약속하고 쓰겠죠 !
@AllArgsConstructor
@Builder
class Person {
private String name;
private int age;
}
// 사용 예
Person person = Person.builder()
.name("김철수")
.age(25)
.build();
class Person {
private String name;
private int age;
@Builder
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 사용 예
Person person = Person.builder()
.name("김철수")
.age(25)
.build();
더 깔끔한 코드를 원한다면 1번을.
@AllArgsConstructor
의 문제점을 코드에 담고 싶지 않다면 2번을 택하는 것 같습니당.
@AllArgsConstructor(access = AccessLevel.PRIVATE)
을 사용한다면 어떨까요?
접근 수준을 private로 설정하는 겁니다
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
class Person {
private String name;
private int age;
}
// 사용 예
Person person = Person.builder()
.name("김철수")
.age(25)
.build();
생성자를 사용해 객체를 생성하는 것을 막을 수 있고, 코드도 깔끔해서 좋은 것 같습니다!
@AllArgsConstructor를 지양하는 이유로 캡슐화 위반을 지적하는 시선도 있는 것 같습니다. 여기에 공감하고 방지하길 원한다면 2번(생성자 만들고 @Builder붙이기)를 택해야 할 것 같습니다