일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 구글 OAuth login
- Spring multimodule
- 파이썬
- 개발자부트캠프추천
- @FeignClient
- jwt
- 항해99
- 99클럽
- 디자인패턴
- 인프콘 2024
- 커스텀 헤더
- jwttoken
- 단기개발자코스
- 빈 충돌
- infcon 2024
- 프로그래머스
- JavaScript
- DesignPattern
- 전략패턴 #StrategyPattern #디자인패턴
- 빈 조회 2개 이상
- 디자인 패턴
- 코딩테스트 준비
- TiL
- 취업리부트코스
- Python
- 1주일회고
- spring batch 5.0
- 개발자 취업
- KPT회고
- 프로그래머스 이중우선순위큐
- Today
- Total
m1ndy5's coding blog
About Setter (feat. Builder) 본문
스프링을 공부하다 보면 Setter 사용하지 마세요라는 말은 귀에 딱지 앉게 들어봤을 것이다.
이제부터 그 이유를 알아보자!
1. 의도를 파악하기 힘듦
member.setName("minsung");
member.setAge(20);
setter로 값을 변경하게 됐을 때는 왜 이 값을 변경했는지 setter 코드만 봐서는 유추가 힘들다.
이게 새롭게 값을 넣어주는 것인지, 기존의 값을 바꿔주는 것인지 한눈에 알기 쉽지 않다.
예를 들어보자
public void updateAge(int age){
this.age = age;}
setAge보다 더 직관적인 메서드명을 가지고 있다.
이 메서드를 사용한다면 아 기존의 age를 바꿔주는구나라고 더 직관적으로 이해가 가능하다.
2. 객체의 일관성을 유지하기 힘듦
setter을 사용하게 되면 어디에서나 값을 변경할 수 있게 되고 그렇기 때문에 객체의 일관성을 유지하기 힘들다.
하지만 이 말이 잘 이해가 가지 않았다.
setter을 사용하지 않고 위처럼 updateAge메서드를 사용한다고 해도 결국 public 으로 선언이 되어있고 어디에서나 불러올 수 있는데 왜 setter만 객체의 일관성을 유지하기 힘들다는 건지 이해가 안됐다...
이해가 안가서 이곳 저곳에 문의를 해봤고 그 결과 제대로 설명한 블로그를 찾을 수 있었다.
예를 들어서 member의 grade를 변경하는 메서드가 있다고 생각해보자
public class 회원관리{
public void updateMemberGrade(Member member){
if (member.getGrade().equals("VVIP")){
// 대충 VVIP등급 고객은 따로 관리한다는 코드
return
}
if (member.getGrade().equals("VIP")){
회원.setGrade("VVIP");
}
else if (member.getGrade().equals("NORMAL")){
회원.setGrade("VIP");
}
.
.
.
}
}
이런식으로 회원관리 class의 updateMemberGrade에 Member의 grade를 올려주는 로직이 있다고 가정하자.
이 때, 코드에서 보면 Grade가 VVIP인 고객은 따로 등급을 관리한다.
근데 이 시스템을 몰랐던 개발자가 다른 코드에서 grade를 올리는데 VVIP는 따로 고려를 해주지 않았다고 했을 때
그 코드에서는 VVIP는 따로 체크하는 조건이 없었으므로 아무런 고려가 되지 않았을 것이고 만약 setter를 통해 VIP로 내려버린다고 해도 바로 내려졌을 것이다.
그럼 거기에도 VVIP만을 위한 코드를 또 넣어줘야하고 다른 곳도 변경가능한 곳이 있다면 계속해서 코드를 넣어줘야할 것이다.
그럼 만약에 VVIP만을 위한 코드가 바꼈다면?? 또 일일히 찾아서 넣어줘야할 것이다.
이는 OCP 원칙, 확장에는 개방적이고 수정에는 폐쇄적이어야한다는 원칙을 무시해버린다.
그렇다면 어떻게 바꿔야할까?
@Getter
public class Member{
private int 구매금액;
private String grade;
public void upgradeMemberGrade(){
if (checkVVIP()){
return
else {
//...
}
}
private Boolean checkVVIP(){
if(this.grade.equals("VVIP")){
// ...
return true
}
return false
}
이런식으로 만들게 되면 다른 코드에서도 memberGrade를 변경하기 위해 upgradeMemberGrade메서드를 호출할 때 VVIP인지를 먼저 체크하게되고 혹시 vvip를 위한 로직이 변경된다 하더라도 checkVVIP코드만 변경하면 되기 때문에 간편하다.
또한 @Setter은 모든 필드에 변경 권한을 주지만 메서드를 정의해 사용하게 되면 변경을 원하는 필드만 변경할 수 있다.
그렇다면 객체를 생성할 때는 어떻게 생성할까?
바로 Builder 패턴을 사용해주면된다.
Builder의 장점으로는
1. 필요한 데이터만 설정해서 객체를 만들 수 있음
예를 들어 id값이나, createDate, updateDate과 같은 내가 직접설정해주지 않아도 되는 필드들은 굳이 값을 넣지않고 빌더를 통해 객체를 생성할 수 있다.
2. 가독성을 높일 수 있음
어? 그럼 필요한 데이터만을 설정해서 객체를 만들 수 있는건 생성자를 만들어서 하면되는데? 할 수 있다.
아래 예시를 보자
Member member = new Member("테스트", 19, 181, 121);
각 숫자가 무엇을 의미하는지 한번에 알 수 없다.
하지만 빌더를 사용하면
Member member = Member.builder()
.name("테스트")
.age(19)
.height(181)
.iq(121).build();
이렇게 명확하게 각 값들이 어떤 필드에 들어가게 될지 정확하게 알 수 있다.
'백엔드 with java > spring' 카테고리의 다른 글
ALL ABOUT REFRESH TOKEN (0) | 2024.05.20 |
---|---|
JWT Login과 Cookie (feat. Redirect) (0) | 2024.05.19 |
Entity 대신 DTO를 반환해야하는 이유 (0) | 2024.01.17 |
UnsatisfiedDependencyException (feat.영한님 강의) (2) | 2023.12.05 |
Spring Security UserDetails, UserDetailsService (1) | 2023.10.11 |