ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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] Setter 사용을 지양하자!!

    들어가며 안녕하십니까 백엔드 개발자 지망생 BLoo 입니다. 이번 시간에는 제가 Entity와 DTO등에 Setter를 지양하고 있는데 그 이유를 한 번 정리하고자 포스팅하게 되었습니다. 보통 자바 클래스는

    bloowhale.tistory.com

    https://velog.io/@aidenshin/%EB%82%B4%EA%B0%80-%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94-JPA-%EC%97%94%ED%8B%B0%ED%8B%B0-%EC%9E%91%EC%84%B1-%EC%9B%90%EC%B9%99

     

    JPA 엔티티 작성 - Setter 금지

    엔티티를 작성함에 제가 생각하는 몇가지 원칙(?)이 있습니다.그중 엔티티(객체)의 Setter 사용 금지 원칙(?) 에 대해 알아보겠습니다.엔티티를 작성할 때 습관적으로 모든 필드에 Setter를 생성하는

    velog.io

     

    '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
Designed by Tistory.