[우테코 6기 프리코스] 4주차 회고(Feat. 크리스마스 프로모션)

Jii·2023년 11월 19일
0

우테코

목록 보기
5/5

주절주절 느낀 점

거짓말 살짝 보태서 1주 차 미션 시작한게 엊그제 같은데 벌써 4주 차가 끝나고 회고를 작성하고 있다는게 안 믿긴다...🥹 이제 좀 프리코스에 적응하면서 나만의 루틴도 갖추고 있었는데(사실 루틴이라기엔 학교 -> 집 -> 프리코스 공부 ->잠♾️)이긴 했지만,,,,(?)아쉽다.

3주 차 미션이 끝나고 4주 차 미션을 기다리면서 약간 작년 기출 나왔으면 하는 마음 반, 새로운 미션 나왔으면 하는 마음 반이였는데 완전히 새로운 문제가 나왔다. 그것도 다가오는 크리스마스를 맞이하여 음식 관련 할인 프로모션을 진행하는 것이다.

awwww🥹 이렇게 메일 형식으로 요구 사항 및 프로모션 계획에 대해 설명해주셔서그런지 진짜 회사에 입사해서 개발을 하는듯한 기분이 들었을 뿐만 아니라 4주차 미션 중 가장 재밌었던 것 같다.(이 아이디어 생각해내신 코치님께 진심으로 감사의 인사 전합니다!!)
미션하는 동안 개발자 직업 체험을 하면서 만약 실제로 내가 개발한 기능들을 실제 고객들이 사용하게되면 정말 뿌듯할 거 같다는 생각이 들었으며, 다시 한 번 개발자가 꼭 되어야겠다고 다짐한 것 같다.
이 직업,,,정말 짜릿하잖아?!✨

신경썼던 부분

일단 구현 후 리팩토링

지난 3주 차를 구현하면서 타임어택을 겪고, 처음부터 완성된 코드를 작성하려 하기보다는 일단 실력 내에서 돌아가게끔 구현한 후에 리팩토링 하는 것으로 다짐했고, 그걸 지켰다. 이렇게 하니 리팩토링 할 때 코드가 이미 작성되어 있으니 발전시켜야 할 부분이 명확하게 보여 훨씬 괜찮았던 것 같다. 이전에는 실력은 안 따라주는데 마음만 앞서서 처음 구현할 때부터 새로운 걸 적용하기가 매우 힘들었을 뿐만 아니라 오래 걸렸는데 말이다. 더하여 내 능력 내에서 1차 구현을 마치니 이번 주차가 요구 사항은 훨씬 까다롭고 난이도도 높았지만 정신적으로는 더 쉽게 느껴졌으며 더욱 즐겁게 임할 수 있었던 것 같다!!

클래스 책임 분리

클래스마다 책임을 명확히 분리해주기위해 전략패턴을 처음으로 사용해보았다.

이번 미션의 핵심 기능에 대해 정의해보자면 사용자의 주문 조건에 따라 할인 이벤트를 적용하는 것이라 생각한다.
이에 할인 이벤트 적용을 구현하기 위해 Enum(+함수형 인터페이스)전략패턴 둘 중 어떤 방식을 선택할지 많은 고민을 하였다..!

Enum(+함수형 인터페이스)을 도입하려 했던 이유:
자바 8부터 Enum내에서 함수형 인터페이스를 사용가능하게 되면서 단순히 데이터 뿐만 아니라 서비스 로직을 작성할 수 있게되었다. 이로 인해 데이터와 로직이 한 클래스 내에 존재하여 응집성이 높으며, Enum자신의 상태와 행동을 스스로 책임지게 되므로, Enum 내부 코드 변화가 다른 클래스들에게 크게 영향을 끼치지 않을 것 같다 판단하였다.

그럼에도 전략패턴을 도입한 이유:
단순히 할인 정책이 몇 개 존재하지 않는다면 Enum도입이 더 간결하고 명확할 것 같았지만, 확장성을 고려하였을 때 많은 이벤트가 도입된다면 전략패턴을 사용하였을 때 각각의 클래스가 담당하는 역할이 명확해져서 코드를 이해하고 확장하기 쉬워질 것이라 생각하였기 때문이다.

따라서

public interface DiscountStrategy {
    DiscountInfo applyDiscount(OrderItems orderItems);

    boolean isApplicable(Day day, OrderItems orderItems);
}

이렇게 할인 가능한지와, 할인 적용한 정보(할인 이벤트 및 금액)메서드를 각 이벤트마다 오버라이딩 해주었다.

테스트 코드

예외 사항이 무척 많았던 이번 미션이라 테스트 코드를 전보다 꼼꼼하게 작성했다..!

업로드중..
커버리지 확인도 해보았다! static으로 사용해준 클래스들을 생성자 사용하여 객체 생성하게 될 시 예외가 터지도록 만들어주는 부분 빼고는 높은 커버리지가 나왔다!
업로드중..
또한 이번 미션 요구사항 중 하나인 도메인 단위의 테스트를 구현하기 위해 domain패키지 내에있는 클래스마다 테스트를 다 만들어주었다.
근데 도메인 내 클래스마다 테스트를 작성하다보니 내용이 겹치는 느낌이 많이 들었다.
마치,,
이렇게 A를 가지고 있는 B 클래스 테스트 로직이 A 클래스 테스트 로직을 다 포함하며 오직 한 단계 앞선 느낌이랄까...?

아직 올바르게 테스트 코드를 작성하고 있는건지, 어떻게 작성해야 좋은 테스트 코드인지 잘 모르겠다 😵‍
프리코스 내에서 여러 사람들이 작성하신 코드를 많이 읽고 참고하며 발전 시켜야겠다.
그래도 테스트 코드가 뭔지도 몰랐던 3주 전의 과거의 나와 비교해보면 많이 늘은 것 아닌가!!! 칭찬하쟈 칭찬해!!

디미터의 법칙

디미터의 법칙을 지켜 한 클래스의 책임을 다른 클리스에게 전가 시키지 않도록 많이 노력하였다.
괜히 .(도트)가 2개 이상 사용되면서 정보를 가져오게되면 혹시나 책임을 전가한 것이 아닌지 확인하면서 메서드들이 올바른 클래스 내에 위치하도록 많은 신경을 써주었다.

public static Menu from(String menuName) {
        Predicate<Menu> isSameName = menu -> menu.name.equals(menuName);

        return menus.stream()
                .filter(isSameName)
                .findFirst()
                .orElseThrow(ExceptionMessage.INPUT_ORDER_FORMAT::getException);
    }

위와 같이 말이다
메뉴를 서비스 코드내에서 조건에 맞춰 값을 가져오는 것이 아니라 메뉴 클래스 내에서 값을 찾아 반환해주었다!

이를 통해 캡슐화뿐만 아니라 응집도를 높이는 것이다!

Generic

이번에 Generic 타입을 처음으로 사용해보았다. 예외 사항 발생 시 에러를 출력하고 다시 입력 받는 것이 은근히 반복돼 제네릭 타입을 사용하여 커스텀 클래스를 만들어준 것이다! 이로 인해 다시 입력 받느라 반복되었던 try -catch 부분을 재사용 시켜주고 반복을 줄여주었다.
커스텀 클래스를 만들면서 드디어 함수형 인터페이스인 supplier를 처음 사용해보았다!

커스텀 클래스가 코드 재사용성을 높여주고 반복을 줄여준다는 점에서는 높이 사지만, 코드를 읽는데 시간이 좀 걸린다는 점에서 좀 더 반복이 많은 곳에서 사용되면 더 좋을 것 같다!
아래는 이번 미션에서 Generic을 사용한 곳이다 ⬇️

package christmas.util;

import christmas.io.writer.Writer;
import christmas.validator.InputValidator;

import java.util.function.Supplier;

public class RetryHandler {
    private final Writer writer;
    private int retryCount = 0;

    public RetryHandler(Writer writer) {
        this.writer = writer;
    }

    public <T> T retryUntilSuccess(final Supplier<T> supplier) {
        try {
            T result = supplier.get();
            retryCount = 0;
            return result;
        } catch (IllegalArgumentException exception) {
            writer.writeln(exception.getMessage());
            InputValidator.validateRetryCount(++retryCount);
            return retryUntilSuccess(supplier);
        }
    }
}

아쉬웠던 점

이번 미션 구현은 영혼을 탈탍타 털어 아쉬움없이 제출하려고 3주차 코드리뷰도 몇 분 안하고 빨리 시작했는데도,,시간이 부족했다🥲
뒤 돌아보면 아쉬운 점이 보이는 코드,,,, 다 내가 성장했기에 그런 거였으면..!!! 지금 봤을 때도 리팩토링 해야할 부분이 산더미지만 제일 아쉬웠던 점 몇 개를 적어보고자 한다.

Dto

dto를 도메인 클래스 내에서 생성해주지 않고 dto 클래스내에서 자체적으로 dto를 생성해주려다보니 getter를 다 열어버린 것 같다,,,, 이 점이 제일제일제일 아쉽다.
그리고,
getter를 무작정 안쓰는 것이 아니라 지양하면 되는 것은 알겠는데,,,그럼 getter를 대체 어느 곳에서 쓰면 괜찮을 것일까..? 이 점도 아직 답을 찾아 헤메는 중이다,,,

1월 확장

업로드중..
이 부분을 읽고 엇!!! 1월에도 플래너를 적용시킬 수 있다는 확장성을 고려하고 미션을 구현해야겠다!! 라고 생각했었는데,,, 미션 구현하다보니 1월로 고치려면 엄청난 보수가 필요할 것 같다,,,흑흑
(이 부분은 나중에 1월로 바꿔보면서 어느 곳이 수정되었고, 유지보수하기에 좋은 코드를 작성하려면 어떻게 해야할지 공부해봐야겠따,..!)

테스트 코드를 1차 구현 이후에 작성

초반에 리팩토링을 많이 해야할 것 같다는 느낌에 테스트 코드를 어느정도 구도를 잡은 1차 구현 이후에 작성하였다.
그렇지 않으면 테스트 코드마저 여러번 작성하게 되면서 효율이 별로일 것 같았기 때문이다.
그치만 아쉽다!!...
대체 어떻게 기능 하나 구현할 때마다 테스트 코드를 작성할 수 있을까..
멀고도 먼 테스트 코드의 세계,,,
일단은 남은 시간동안은 바로바로 테스트 짜는 것을 다시 도전해봐야겠다..!
하다보면 익숙해지고 요령을 터득하겠지🤔

프리코스 마무리

끝이라니!!! 끝이라니!!! 이렇게 끝이 났다니
넘 아쉽다 우어엉어어엉
빨리 다른 분들이 작성하신 코드들 내 거와 비교하며 공부하고 다음 미션 구현하고 싶지만? 다음은 없다는 거...🥹

4주간 저어어엉말 많이 배우고 성장했다. 특히 클래스 책임 분리하는 것은 여전히 어렵지만 그래도 초반보다는 많이 분리해낼 수 있게된 것 같다.
또 마지막 크리스마스 미션 코드는 작성한 양이 2000줄을 넘겼다니. 내 개발인생 중 이렇게 많은 양의 코드를 작성한 적은 이번이 처음이다,,ㅋㅋㅋㅋ.

아아 프리코스 하면서 하나 뼈 시리게 깨달은 점이 있는데 바로 노력에는 끝이 없다는 것,,,이다.
내 나름 최선을 다해 프리코스에 열심히 참여했는데, 그럼에도 불구하고 대단하신 열정 짱짱맨분들이 많이 참여하셔서 보면서 많이 배우고 느낀 점도 많았다. 이 열정 대단하신 분들과 그대로 우테코까지 들어가고 싶다,,,,

이상 후기 마침니다 -!

profile
Empower Yourself

0개의 댓글