앞서 작성한 Controller에 대한 글에서 처럼, SpringBoot로 개발을 하다보면 @AllArgsConstructor @NoArgsConstructor, @RequredArgsConstructor 등 의 어노테이션을 자주 사용하곤 한다.
역할과, 의미를 대강 알고 사용하는 것과 알고 사용하는 것은 다르기 때문에 좀 더 깊은 이해를 위해 기록을 남긴다
public Referee(int strike, int ball, String nothing) {
this.strike = strike;
this.ball = ball;
this.nothing = nothing;
}
gamePlay.playGame(new Referee(0,0,"낫싱"));
클래스에 선언된 멤버 변수들은 타 클래스에서 마음대로 접근할 수 없게끔 접근 제어자를 private로 선언한다.
그렇기에 다른 객체를 인스턴스로 생성할 때 변수의 값을 주며 생성하기 위해 사용하는 것이다.
이 외에도 다른 객체에서 값을 주기 위한 방법이 몇가지 있다.
public void setBall(String nothing){
this.nothing = nothing;
}
하지만!
나는 Setter의 사용을 지양하려고 한다. 아예 안 쓰진 않지만 최대한 안쓰려고 노력중이다.
왜?
소프트웨어 공학에서 유지보수 용이성은 프로그램의 생명을 좌우한다. 따라서, 의도가 확실하지 않은 setter의 사용을 지양하려 한다.
setBall 대신에 의도를 분명히 드러낼 수 있는 방안으로 별도의 메서드를 만들면 해결될 수 있다.
public void setPassword(String password){
this.password = password;
}
public void changePassword(String newPassword){
this.password = newPassword;
}
비밀번호를 변경하기 위해 setPassword()를 사용하는거보다 changePassword()를 사용하는 것이 가독성이 더 좋다.
public User(Long id, String userName, String userNickname, String userEmail, String password){
this.id = id;
this.userName = userName;
this.userNickname = userNickname;
this.userEmail = userEmail;
this.password = password;
}
Builder 패턴이란?
앞서 쓴 생성자와 다르게 빌더를 사용하면
- 필요한 데이터만 쓸 수 있다.
- 유연성을 확보할 수 있다.
- 가독성을 높일 수 있다.
- 불변성을 확보할 수 있다.
이런 장점이 있다.
User seokki = new User(1L,"준석","닉네임","naver","213");
이런 상황에서 특정한 (ex)키나 몸무게)와 같은 변수를 추가하려면 기존의 모든 코드를 수정해야 하는 번거로움이 있다.
User seokki = new User(1L,"준석","닉네임","naver","213");
1L, 213, naver 등이 무엇을 의미하는지 알기 어렵다.
그럼 결국 이 생성자를 선언한 클래스로 가서 확인을 해야한다.
public Member toEntity() {
return Member.builder()
.id(id)
.email(email)
.nickname(nickname)
.password(password)
.build();
}
반면 Builder 패턴을 사용하여 직관적으로 데이터를 파악할 수 있다.
앞에 Setter 처럼 개방폐쇄원칙에 위배되기 때문이다.
음.. 정리하다보니 원래 정리하려던 Constructor에서 멀리까지 와버렸네..
이제 내가 자주 남발?하는 @~~Constructor 들에 대해 정리하겠다.
하지만..
Lombok에서는 AllArgsConstructor와 @RequiredArgsConstructor의 사용을 주의하거나, 권하지 않는다.
왜?
Jpa에서는 프록시 생성을 위해 기본 생성자를 반드시 하나 생성해야 한다. 이때 접근 권한을 protected가 아닌 public으로 할 경우에 문제가 발생할 수 있다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor(access = AccessLevel.PUBLIC)
생성된 객체의 인자값이 null이 된다면 큰 문제를 발생시킬 수 있다.
그렇기 때문에 기본 생성자의 접근을 protected로 하길 권장한다고 한다.
아무 생각 없이, 기계적으로 어노테이션을 남발해왔던 것 같다. 그게 습관이 됐겠지. 지난 나의 모습에 반성하고... 앞으로는 코드 한 줄 한줄에 의미를 담아 작성하는 습관을 꼭 들여야 겠다.
아직 졸업 작품 개발에 여유가 있으니, 차근차근 고민하며 좀 더 좋은 코드를 만들 수 있는 습관을 길러야겠다.