DAO Setter 제거, update 관련 method 추가 - leegwichan/StackOverFlow_Refactoring GitHub Wiki

◎ 기존 작성 방법

  • Entity에서 모든 field에 대해 getter, setter를 만듦
    • 생성자는 NoArgsConstructor 이용
  • Service Layer에서 setter를 이용해 DAO에 있는 정보를 업데이트 함

◎ 기존 작성 방법의 문제점

  • DAO의 Setter를 사용하기 때문에 변경이 안되어야 하는 정보도 손쉽게 변경할 수 있다.
  • DAO의 내부 field 값이 바뀌게 된다면, setter를 사용한 이외 파일에서도 많은 코드들을 바꿔야 한다.
    • 다른 파일들이 DAO 내부 구조에 영향을 크게 받는다.

◎ Refactoring 중점 사항

  • 기존 DAO의 Setter를 제거하고 다른 생성자, update관련 method 추가
    • Builder를 추가하여 생성시 값을 추가할 수 있도록 함
    • 이외 변경이 필요한 field 값은 따로 method를 구현함

◎ Refactoring 효과

  • DAO를 사용하는 Service Layer에서 DAO의 구조를 몰라도 메서드를 사용하여 작업을 실행함
    • Service Layer의 코드 양 약 25% 감소
  • DAO의 field 값을 외부에서 함부로 변경할 수 없게 됨
    • 특정한 형식에 맞추어야만 변경하도록 함 ex)DAO의 update()

◎ 코즈 작성시 정보 & Error Handling Log

◎ 코드 변경 전후 비교

@Transactional
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;
    ...

    @Override
    public Member updateMember(Member member) {
        Member findMember = findVerifiedMember(member.getMemberId());

        Optional.ofNullable(member.getImage())
                .ifPresent(image -> findMember.setImage(image));
        Optional.ofNullable(member.getDisplayName())
                .ifPresent(displayName -> findMember.setDisplayName(displayName));
        Optional.ofNullable(member.getLocation())
                .ifPresent(location -> findMember.setLocation(location));
        Optional.ofNullable(member.getMemberTitle())
                .ifPresent(title -> findMember.setMemberTitle(title));
        Optional.ofNullable(member.getAboutMe())
                .ifPresent(aboutMe -> findMember.setAboutMe(aboutMe));

        return memberRepository.save(findMember);
    }
 
    ...

    public Member findVerifiedMember(long memberId){
        Optional<Member> optionalMember = memberRepository.findById(memberId);
        Member findMember = optionalMember.orElseThrow(() ->
                new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND));

        return findMember;
    }
}

// 변경 전
@NoArgsConstructor
@Getter
@Setter
@Entity
public class Member extends Auditable {
    ...
}
// 변경 후
@Transactional
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository;
    ...

    @Override
    public Member updateMember(Member member) {
        Member findMember = findVerifiedMember(member.getMemberId());

        findMember.updateMember(member);
        return memberRepository.save(findMember);
    }

    ...

    private Member findVerifiedMember(long memberId){
        return memberRepository.findById(memberId).orElseThrow(() ->
                new BusinessLogicException(ExceptionCode.MEMBER_NOT_FOUND));
    }
}

@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Entity
public class Member extends Auditable {

    ...

    public void updatePassword(String encodedPassword) {
        this.password = encodedPassword;
    }

    public void updateMember(Member member) {
        this.image = Optional.ofNullable(member.image).orElse(this.image);
        this.displayName = Optional.ofNullable(member.displayName).orElse(this.displayName);
        this.location = Optional.ofNullable(member.location).orElse(this.location);
        this.memberTitle = Optional.ofNullable(member.memberTitle).orElse(this.memberTitle);
        this.aboutMe = Optional.ofNullable(member.aboutMe).orElse(this.aboutMe);
    }
}
⚠️ **GitHub.com Fallback** ⚠️