Setter 왜 쓰는지 알고 사용하자!
그동안 나는 너무 자연스럽게 private인 필드에 접근하기 위해 public으로 만들어진 getter & setter를 너무 자연스럽게 generate해서 사용했다. 실제로 사용이 되지 않는 경우에도 습관처럼 초기에 만들어 놓곤 했다.
특히 Lombok을 알게 된 이후로는 @Getter, @Setter를 왜 필요한지 고민의 과정을 거치지 않고 사용했다.
그렇다면 Setter를 왜 조심해서 써야 하는지 그 이유에 대해 살펴보고자 한다.
1. 값을 변경한 의도를 파악하기 어렵다.
package com.example.summer.accommodation;
public class Accommodation {
private String name;
private int minPrice;
private int id;
public void setMinPrice(int minPrice) {
this.minPrice = minPrice;
}
}
Accommodation accommodation = new Accommodation();
accommodation.setMinPrice(220000);
숙소의 최저가가 220000인 건 알겠는데 값이 처음으로 설정된 건지 아니면 변동되었는지 그 이유를 코드 작성자인 나를 제외하고 알 수 없다.
2. 객체의 일관성을 지키기 힘들다.
흠.. 다시 생각해보면 필드 자체를 잘 숨겨놓고 그 값은 Setter로 수정하고 Getter로 조회할 수 있으면 정보가 정말로 잘 숨겨졌다고 할 수 있을까?
public Room updateRoom(int id) {
Room room = findByRoomId(id);
room.setType("single");
room.setCapacity(2);
room.setPrice(80000);
return room;
}
위의 코드는 방의 정보를 업데이트하는 메소드인데 setter를 사용해 어디서든지 접근할 수 있기 때문에 외부에서 자유롭게 방의 정보를 변경할 수 있다. 즉, 객체가 일관성이 없는 상태가 될 가능성이 존재한다.
+ 해결 방법
public class RegisterRoomRequest {
private String type;
private int price;
private int capacity;
public String getType() {
return type;
}
public int getPrice() {
return price;
}
public int getCapacity() {
return capacity;
}
public RegisterRoomRequest(String type, int price, int capacity) {
this.type = type;
this.price = price;
this.capacity = capacity;
}
// toEntity
public Room toEntity(int id) {
return new Room(type, price, capacity);
}
}
toEntity 메소드를 사용하면 Setter를 사용하지 않고, 필요한 경우에만 RegisterRoomRequest를 통해서만 값을 설정할 수 있도록 제한할 수 있다. 또한 Setter 메소드를 여러 번 호출하지 않고 한 번의 호출로 필요한 데이터가 설정되기에 코드의 가독성이 향상된다. 무엇보다 데이터 변경이 RegisterRoomRequest를 통해서만 가능하기에 명확한 책임 분리(SRP)를 지킬 수 있다.