종우의 삶 (전체 공개)
Code refactoring - 1 본문
대상 repository : https://github.com/Jonggae/group-invitation ( Readme 참고 )
목표 : 가독성 향상, 부족한 기능 완성, 테스트코드 작성, 완성도 있는 코드
1. @Setter anotation에 대한 내용
@Setter의 사용은 자제하는 것이 좋다.
-> 자주 들은 내용이었는데 기능 구현을 더 신경쓰다보니 생각없이 @Setter를 박아넣고 시작.
리팩토링하여 좀더 안정성 있는 코드를 만들어보자. ->객체지향적인 내용
of, from toEntity등으로 변경하였음.
Entity 도메인에 setter를 사용하는 대신 생성자와 of를 이용하여 객체를 생성할 수 있도록 함.
@Entity
@Getter
@Setter
public class Member {
@Id
@GeneratedValue
private long id;
private String name; //초대받을 사용자 이름
private String phoneNumber; //초대받을 사용자의 전화번호
private String email; //초대받을 사용자의 이메일 주소
{~생략~}
}
이러한 코드의 형태에서
package com.exam.invitation.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Getter
@NoArgsConstructor
public class Member {
@Id
@GeneratedValue
private long id;
private String name; //초대받을 사용자 이름
private String phoneNumber; //초대받을 사용자의 전화번호
private String email; //초대받을 사용자의 이메일 주소
// private final boolean activated = Boolean.FALSE; //임시 회원이므로 활성화 태그를 만들어놓고 활성화 시키지 않음.
private Member(String name, String phoneNumber, String email) {
this.name = name;
this.phoneNumber = phoneNumber;
this.email = email;
}
public static Member of(String name, String phoneNumber, String email) {
return new Member(name, phoneNumber, email);
}
}
private로 선언된 생성자와 of를 사용한 객체 생성방법을 이용한 것으로 바꾸었다.
-> 이러한 방법의 의도는? (GPT쌤이 설명해줌)
private Member(String name ~~~) { ~ }
는 생성자이다. 생성자는 객체가 생성될 때 호출되는 특별한 메서드로 객체의 초기화를 담당한다.
외부에서 직접 호출되지 않도록 private로 선언하고 외부에서는 'new Member(~) 로 객체를 생성할 수 있다.
여기서 of 메서드를 함께 사용하여 객체 생성시에 필요한 로직을 설정한다.
of 메서드는 Member 클래스의 객체를 생성하고 반환한다. 여러 생성 로직을 캡슐화 할 수 있는 장점이 있다.
(팩토리 메서드라고 하는데...!? 이것은 또 뭘까)
이렇게 객체를 생성할 때 필요한 부분들은 전부 변경해주었다.
사실 확실한 이해를 아직 못하겠으므로 다른 코드들을 많이 바꾸거나 해보자.
2. 메서드 분리
package com.exam.invitation.service;
import com.exam.invitation.domain.Member;
import com.exam.invitation.dto.MemberDto;
import com.exam.invitation.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository tempMemberRepository;
// 초대 링크 생성과 함께 임시 멤버 생성해야함
public Member createTempMember(MemberDto tempMemberDto) {
Member tempMember = tempMemberDto.toTempMember();
if (tempMemberRepository.findByName(tempMember.getName()).isPresent()
|| tempMemberRepository.findByEmail(tempMember.getEmail()).isPresent()) {
throw new IllegalArgumentException("같은 이름, 이메일이 존재합니다");
}
tempMemberRepository.save(tempMember);
// 임시 멤버 생성 완료
return tempMember;
}
}
위 코드의 의도는
1. 초대 링크를 생성한다 (uuid를 포함한 무작위 도메인)
2. 초대 링크를 보낼 임시 멤버를 추가한다.
2- 1. #2에서 멤버의 이름, 이메일을 체크한 뒤에
2- 2. 임시 멤버를 db에 추가 한다.
이러한 코드였는데 createTempMember 메서드에 모든 것을 넣어놨었다.
명확한 이름을 만들기 위해 우선 TempMember라는 명칭을 전부 Member로 변경하였다.
-> 말이 임시멤버지 그냥 멤버를 추가하는 것과 다름 없었다. (과제 설명이 약간 모호함)
이후 한눈에 알아보기 힘든 메서드의 로직들을 분리하였다.
package com.exam.invitation.service;
import com.exam.invitation.dto.MemberDto;
import com.exam.invitation.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
private final InvitationLinkService invitationLinkService;
// 초대 링크 생성과 함께 임시 멤버 생성해야함
public void createMember(MemberDto memberDto) {
generateInvitationLink();
checkNameAndEmail(memberDto);
saveMember(memberDto);
}
private void generateInvitationLink() {
invitationLinkService.generateInvitationLink();
}
private void saveMember(MemberDto memberDto) {
memberRepository.save(memberDto.toEntity());
}
private void checkNameAndEmail(MemberDto memberDto) {
if (memberRepository.findByName(memberDto.toEntity().getName()).isPresent()) {
throw new IllegalArgumentException("같은 이름이 이미 존재합니다");
}
if (memberRepository.findByEmail(memberDto.toEntity().getEmail()).isPresent()) {
throw new IllegalArgumentException("같은 이메일이 이미 존재합니다");
}
}
}
너무 많은 분리를 진행한것 같은데, 마지막의 중복된 데이터를 검색하는 메서드(checkNameAndEmail)만 분리하였어도 괜찮았을 하다. 우선은 이대로 마무리 하였다.
'개발 > Spring' 카테고리의 다른 글
Spring security - 4 (0) | 2024.01.17 |
---|---|
Spring security - 3 // Security Config (0) | 2024.01.15 |
Spring security - 2 (0) | 2024.01.14 |
Spring Security - 1 (0) | 2024.01.14 |
Code refactoring - 2 (1) | 2024.01.10 |