오늘 팀 프로젝트하다가 갑자기 이게 떠올랐다.
왜 Setter와 Builder가 나뉘어져있을까?
아라보자.
@Setter
public class Person {
private String name;
private int age;
}
public class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
Person person = new Person();
person.setName("John");
person.setAge(30);
클래스의 필드를 변경할 수 있는 메서드를 자동으로 생성하여 코드의 간결성을 높여주는 세터
@Builder
public class Person {
private String name;
private int age;
}
public class Person {
private String name;
private int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String name;
private int age;
PersonBuilder() {
}
public PersonBuilder name(String name) {
this.name = name;
return this;
}
public PersonBuilder age(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(name, age);
}
public String toString() {
return "Person.PersonBuilder(name=" + this.name + ", age=" + this.age + ")";
}
}
}
Person person = Person.builder()
.name("John")
.age(30)
.build();
자 이제 제가 하면서 느낀점을 말해볼게요.
따로 쓰는 이유는 Setter만 사용했을 때 Spring-data-jpa에서의 save가 update인지 insert인지 구분이 안 가서 insert에는 builder를 써주고 update에는 setter를 써줬고,
두 번째로는 Setter를 사용하고 보니 객체의 내부 상태를 쉽게 변경할 수 있어서 OCP에 위반되는 것 같아서 써줬습니당.
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class Person {
private final String name;
private final int age;
}
public class Main {
public static void main(String[] args) {
Person person = Person.builder()
.name("John")
.age(30)
.build();
// person.setName("Doe"); // This line will cause a compilation error
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
}
}
요로코롬하면 객체가 생성된 후에 상태도 변경되지 않으므로 OCP를 준수할 수 있죠.
하나 더 Entity에 builder를 쓰면
entity는 파라미터가 없는 디폴트 생성자를 만들어주고 builder는 파라미터가 있는 생성자를 써야하는데,
그래서 NoArgsConstructor와 AllArgsConstructor를 직접 명시해줘야 에러가 안 뜨더라구요.
결론은 Builder를 애용하고 Setter를 지양하자입니당.