인프런 커뮤니티 질문&답변

PrivilegeEscalate님의 프로필 이미지

작성한 질문수

Readable Code: 읽기 좋은 코드를 작성하는 사고법

연습 프로젝트 소개

질문 제목을 뭐라 적어야할지 모르겠습니다. 죄송합니다

24.10.21 16:47 작성

·

71

·

수정됨

0

우선 강의 너무 재밌게 잘 보고있단 말씀 드리고 싶습니다.

 

일단 새로운 도메인에서 혼자 리팩토링을 하고있었는데요, List<StudyCafeLockerPass> 를 일급 컬렉션으로 감싸 StudyCafeLockerPasses 를 만들었습니다.

 

여기서 StudyCafeLockerPass 에게 type 과 duration 이 같은지 비교하는 질문을던질 때 StudyCafePass 자체를 인자로 넘길지, 아니면 StudyCafePass 로부터 type 과 duration 을 꺼내서 넘길지 고민입니다.

 

public class StudyCafeLockerPasses {

    private final List<StudyCafeLockerPass> lockerPasses;

    public StudyCafeLockerPasses(List<StudyCafeLockerPass> lockerPasses) {
        this.lockerPasses = lockerPasses;
    }

    public static StudyCafeLockerPasses of(List<StudyCafeLockerPass> lockerPasses) {
        return new StudyCafeLockerPasses(lockerPasses);
    }

    // TODO V1. 여기 (StudyCafeLockerPass 에게 질문을 던질때 StudyCafePass 자체를 넘길지)
    public StudyCafeLockerPass findOneBy(StudyCafePass selectedPass) {
        return lockerPasses.stream()
                .filter(option -> option.isEqualWith(selectedPass))
                .findFirst()
                .orElse(null);
    }

    // TODO V2. 여기 (StudyCafeLockerPass 에게 질문을 던질때 StudyCafePass 에서 type 와 duration 을 getter 로 꺼내서 넘길지)
    public StudyCafeLockerPass findOneBy2(StudyCafePass selectedPass) {
        return lockerPasses.stream()
                .filter(option -> option.isEqualWithV2(selectedPass.getPassType(), selectedPass.getDuration()))
                .findFirst()
                .orElse(null);
    }

}


V1 같은 경우의 StudyCafeLockerPass 메서드는 아래와 같습니다.

public class StudyCafeLockerPass {

    private final StudyCafePassType passType;
    private final int duration;
    private final int price;
    
    public boolean isEqualWith(StudyCafePass studyCafePass) {
        return isSamePassType(studyCafePass.getPassType()) && isSameDuration(studyCafePass.getDuration());
    }

    public boolean isSamePassType(StudyCafePassType passType) {
        return this.passType == passType;
    }

    public boolean isSameDuration(int duration) {
        return this.duration == duration;
    }
    
}

 

V2 경우의 StudyCafeLockerPass 메서드는 아래와 같습니다.

public class StudyCafeLockerPass {

    private final StudyCafePassType passType;
    private final int duration;
    private final int price;

    public boolean isEqualWithV2(StudyCafePassType passType, int duration) {
        return isSamePassType(passType) && isSameDuration(duration);
    }

    public boolean isSamePassType(StudyCafePassType passType) {
        return this.passType == passType;
    }

    public boolean isSameDuration(int duration) {
        return this.duration == duration;
    }

}



제가 느끼기에는 Getter 를 사용하지 않으려면 V1 이 맞는거같고.., 의존성을 생각한다면 V2 가 맞는거같은데 강사님의 기준이 있으실까요

(질문이 제가 봐도 이상한것같은데.. 죄송합니다)

답변 2

0

박우빈님의 프로필 이미지
박우빈
지식공유자

2024. 10. 22. 21:25

안녕하세요, PrivilegeEscalate 님!

좋은 질문이네요 ㅎㅎ 아래 추가 내용 남겨주신 부분에서 시작하자면,

 

아 리팩토링 (1) - 추상화 레벨 25분 10초쯤부터 해당과 비슷한 내용이나오네요!! 그렇다면 왜 StudyCafeLockerPass 가 아닌, StudyCafePass 에 질문을 던진 이유를 알 수 있을까요?

메서드의 설계는 곧 도메인에 대한 이해에서부터 시작되는데요.
(제가 만들었지만..) 제가 이 도메인을 이해한 내용 중 하나는, "StudyCafeLockerPassStudyCafePass 에 종속적이다" 입니다.

실제로 사물함 이용권은 스터디카페 이용권을 구입하지 않으면 사용할 수 없기 때문이죠.

두 객체 A와 B가 동등하고, 크게 관련이 없는 상태에서 내부 타입만 공통으로 가지고 있다면, 말씀주신 V2 처럼 type, duration 만 넘겨서 해당하는 pass를 찾았을 것 같은데요.
객체 A와 B가 종속적인 관계라고 저는 해석했기 때문에, 좀 더 주체가 되는 Pass가 LockerPass를 받아서 해당 데이터를 꺼내어 처리하는 방식을 선택하였습니다.

정답이 없고, 도메인을 이해하는 방식에 따라 달라질 수 있는 점이긴 한데요 ㅎㅎ 다만 메서드 설계 시 제가 설명드린 것처럼 명확한 이유에 근거하여 설계해보는 습관을 들이는 게 중요한 것 같습니다.

도움이 되셨기를 바랍니다.
감사합니다. 🙂

PrivilegeEscalate님의 프로필 이미지

2024. 10. 22. 23:33

아 종속적인 관계.. 이해했습니다. 그런 시야가 필요하군요. 감사합니다! 그리고 완강했습니다!! 진짜 너무 너무 많은 도움이 되었어요. 궁금한게 생기면 다시 찾아오겠습니다.

0

PrivilegeEscalate님의 프로필 이미지

2024. 10. 22. 01:56

아 리팩토링 (1) - 추상화 레벨 25분 10초쯤부터 해당과 비슷한 내용이나오네요!! 그렇다면 왜 `StudyCafeLockerPass` 가 아닌, `StudyCafePass` 에 질문을 던진 이유를 알 수 있을까요?