-
Setter의 사용 금지JAVA/Java 2021. 12. 13. 16:57
프로젝트 진행중 엔티티나 DTO에 setter를 사용하게 되는 일이 종종 발생하게 되는데,
이는 일관성 유지에 어려움 등의 여러가지 문제점으로 인해 사용이 금지된다.
① Setter 사용의 의도를 알기 어려움
public ActivityCreateDTO saveActivity(ActivityCreateDTO activityCreateDTO) { Activity activity = new Activity(); activity.setName(activityCreateDTO.getName()); activity.setDescription(activityCreateDTO.getDescription()); activity.setScore(activityCreateDTO.getScore()); activityRepository.save(activity); activityRepository.save(activity); return new ActivityCreateDTO(activity); }
보통 setter는 위와 같이 엔티티의 값을 변경하고자 할 때 많이 사용되는데 setter로 값을 변경하는 의도가 분명하지가 않다. 어떤 변화를 주기 위해서 값을 변경하는지 명확한 의도를 나타내지 않는다.
public class Activity { private Integer id; private String name; private Integer score; private String description; public Activity(String name, Integer score, String description) { this.name = name; this.score = score; this.description = description; } // 비지니스 로직 public Activity updateActivity( Activity requestActivity) { this.name = requestActivity.name; this.description = requestActivity.description; this.score = requestActivity.score; return this; } }
public ActivityCreateDTO updateActivity(ActivityCreateDTO activityCreateDTO, MultipartFile multipartFile) { Activity existingActivity = activityRepository.findById(activityCreateDTO.getId()) .get(); Activity requestActivity = activityCreateDTO.toActivity(); Activity updatedActivity = existingActivity.updateActivity(requestActivity); activityRepository.save(existingActivity); return new ActivityCreateDTO(existingActivity); }
위와 같이 엔티티에 값을 변경하고자 하는 비지니스로직을 생성 해주고 service계층에서는 updateActivity 로직을 사용하므로서 값을 변경하고자 하는 의도를 지닌 로직명을 명확히 하고 변경 이유를 알려주도록 한다.
② 값의 일관성 유지에 어려움
자바의 빈 규제에 따라서 setter 는 public 으로 모든 곳에서 접근이 가능하기 때문에 의도치 않게 값이 변경되는 경우가 발생할 수 있다.
@Builder의 사용
멤버 변수가 많고, 다양한 생성자를 가져야 하는 경우에는 객체 생성시점에 값을 넣어주어 객체 값의 일관성을 유지하도록 돕는 @Builder를 사용할 수 있다.
public class ActivityCreateDTO { private Integer id; private String name; private Integer score; private String description; private String imageUrl; public ActivityCreateDTO(String name, Integer score, String description) { this.name = name; this.score = score; this.description = description; } public ActivityCreateDTO(Integer id, String name, Integer score, String description) { this.id = id; this.name = name; this.score = score; this.description = description; } }
원래의 경우 setter값을 지양하고자 많은 생성자를 지니게 된다.
public class ActivityCreateDTO { private Integer id; private String name; private Integer score; private String description; private String imageUrl; @Builder public ActivityCreateDTO(Integer id, String name, Integer score, String description) { this.id = id; this.name = name; this.score = score; this.description = description; } }
Activity activity = Activity.Builder() .name("name") .score(12) .description("description") .build()
위와 같이 @Builder를 사용하게 되면 많은 생성자를 사용할 필요 없이 setter의 사용을 줄일 수 있다.
public class Activity { protected Activity() {}; }
기본 생성자를 기본적으로 필요로하는 JPA의 경우 protected까지 생성자를 제어하는 것을 지원하므로 new Activity() 의 사용을 막을 수 있어 객체를 더욱 일관성 있게 유지할 수 있다.
@NoArgsContructor(access = AccessLevel.PROTECTED) public class Activity { protected Activity() {}; }
롬복을 사용하면 더 편하게 나타낼 수 있다.
(참고한 사이트)
https://bloowhale.tistory.com/97
'JAVA > Java' 카테고리의 다른 글
Refactoring ① : 첫번째 예제 (0) 2021.12.17 DTO와 VO 그리고 Entity (0) 2021.12.13 계층별, 기능별 패키지 구성 (0) 2021.12.12 객체지향 생활 체조 (0) 2021.12.12 Java Code Convention ( + Google Java Style Guide) (0) 2021.12.11