마지막 미션은 새로운 주제의 미션이었다.
이번에도 그전과 동일하게 회고의 느낌으로 작성할 예정이다.
내가 고민한 점과 적용한 점 수정했던 부분 및 이유를 작성할 것이다.
고민거리
이번에 enum을 적용해야 하는 상황이 거의 필수적으로 일어났다고 생각했다. 그래서 이를 적용했는데, 문제는 얼마나 나눌 것인가에 대한 고민이었다. 처음에는 카테고리마다 전부 나누고 메뉴판에서 통일하는 방식을 생각했다. 하지만 이러한 방법은 복잡도가 올라간다는 생각도 했고, 입력으로 들어온 값을 찾기가(이름으로 매칭되는 값) 번거롭다는 느낌을 받았다. 물론 분리가 잘되어있다는 생각이 들긴 함.
그래서 한눈에 보기에도 편하고 매칭되는 값을 찾기도 편하게 전부 모아서 관리하였다.
물론 정말 확장 가능성도 생각한다면 다른 방법이 더 좋을 수도 있을 것 같다. 지금은 이런 방법도 무리는 없어 보인다.
개인적인 생각으로는 지금이 방식이 가독성이 더욱 좋아 보인다는 생각이 든다.
이번에 enum을 쓰면서 필드가 너무 많이 증가한다는 느낌을 받았다. 예를 들어 이벤트 이름, 증정품 이름, 증정품 가격, 증정품 개수 등등.. 너무 많은 정보를 한 번에 관리해야 한다는 부담이 있었다. 이를 해결하고자 연관된 정보를 묶고 이를 원시값을 포장하여 관리하도록 수정했다. 증정품은 이름과 가격을 묶어서 Goods라는 이름을 주고 내부 이름과 가격은 다시 원시값을 포장하였다. 덕분에 관리하는 측면에서도 편해지고 이후 확장이 일어난다고 하더라도 유연하게 대처할 수 있겠다는 생각을 했다.
고민거리
이번 미션의 InputView 예시에서는 입력을 int로 변환해서 주었다. 기존에는 나는 무조건 String을 반환하고 전부 도메인에서 처리하도록 만들었다. 그러다 보니 만약 int값이 필요하면 그 값이 숫자인지도 확인하는 로직이 도메인에 들어가야 했고, 검증의 범위가 늘어났다.
어쩌면 나는 예외는 도메인에서 터져야 한다는 강박을 가지고 있었던 것 같다. 이를 나도 적용하여 InputVeiw에서 int로 변환하는 로직을 작성해 보았다. 이 방법을 사용하니 책임에 대한 분리가 이루어져 도메인에 부담이 줄어든다는 장점이 있었다.
고민거리
위의 로직에 이어져서 고민이 된 부분은 바로 readorder이었다. 실제 받는 값은 "시저샐러드-1, 제로콜라-3"과 같은 문자열이었고, 이를 직접 잘라서 도메인까지 넣어줘야 했다. readDate의 경우 단순히 int만 넘기면 해결되지만 readOrder은 어디까지 만들어서 줘야 하는지에 대한 고민을 했다. 우선 실제 도메인이 필요로 하는 List <Order>까지 만들어서 주는 것은 뷰가 도메인을 알기에 당연히 안된다고 생각했다.
그렇다면 단순하게 String을 받고 밖에서 알맞게 잘라서 도메인에 들어가야 하는데 만약 dto로 넣어주면 도메인이 dto를 알게 된다는 단점이 다시 한번 발생한다. 따라서 이를 해결하고자 mapper를 적용해 봤다. 즉 view -> dto -> mapper -> domain의 흐름으로 진행되게 바꾸었다.
즉 dto를 활용하여 (시저샐러드, 1), (제로콜라, 3)으로 잘라서 묶어주고 mapper를 통해서 이를 우리가 원하는 List <Order>로 만들어서 도메인에 넣어주었다.
적용한 점
앞서 InputView를 보면 알다시피 이번에 중복 코드를 줄이기 위해 함수형 인터페이스를 적용해 보았다.
이전에는 while, try-catch와 같은 중간의 코드가 바뀌는 경우에 코드 중복을 줄이기 어려웠다.
이를 해결하고자 여러 자료를 찾아보다가 문득 Spring의 트랜잭션의 원리를 생각해 보았다.
단순하게 트랜잭션 어노테이션 하나만으로 트랜잭션이 시작되고 비즈니스 로직이 실행되고 이후 트랜잭션이 종료되는 것이 내가 고민하는 것과 동일하다는 생각을 했다.
그래서 이를 찾아보고 적용해 보았다.
지금은 중복코드가 사용되는 메서드가 많지 않아서 오히려 불필요해 보일 수도 있지만, 이것은 더 증가할수록 더 높은 활용도를 보인다.
또한 지금도 충분히 활용 가치가 있다고 생각된다. 이전에는 너무 지저분해 보이는..
적용한 점
배지를 증정하는 과정도 enum을 사용하였다. 로직은 혜택 금액을 보고 가장 값이 비싼 배지를 증정하는 것인데, 이때 저는 배지의 순서를 가격이 큰 순으로 정해두고 혜택 금액이 가격보다 큰 배지를 찾는 순간 바로 반환하도록 만들었다. 다만 이러한 설계는 순서에 매우 의존적이라는 생각이 들었다. 그래서 이를 수정하고자, 혜택 금액이 더 큰 배지들을 찾은 이후 그중에 가장 비싼 배지를 반환하도록 수정하였다. 이러한 설계가 추후 버그나 여러 측면에서 유리하다는 생각에 진행하게 되었다.
만약 순서가 바뀐다면 당연하게도 예상치 못한 결과가 나온다.
이 과정에서 Goods에서 CompareTo를 재정의하였다.
이렇게 되니 순서에 상관없이 정상작동한다. 또한 의미상 좀 더 자연스럽다.
재미있던 점
이번 미션을 하면서 재미있던 경험은 해당 날짜에 할인이 적용 가능한지 여부를 체크하는 과정이었다. 직접 계산 로직을 만들어서 해당 날짜가 무슨 요일인지 계산하는 메서드를 만들었다. 예를 들면 들어온 날짜를 7로 나누어 나머지가 1이면 월요일, 2이면 화요일 이런 식으로 만들고 이름을 DayOfTheWeek라고 두었다. 그리고 밥을 먹다가 문득 날짜 관련 라이브러리를 사용하면 요일도 알 수 있지 않을까?라는 생각이 들었다. 그리고 이를 찾아보니 실제 날짜에 대해 요일을 계산하는 라이브러리가 있었고, 이름이 dayOfWeek라는 이넘 타입으로 존재했다. 이를 라이브러리를 사용하도록 수정하였다. 내가 만든 이름과 실제 존재하는 네이밍이 매우 유사하다는 점이 인상 깊었고 재미있었다.
실제 내 커밋 내역이다.
이후 실제 라이브러리를 적용한 모습이다.
역시 라이브러리를 사용하니까 더 편하고 알아보기 쉽다는 생각을 했다.
적용한 점
위의 코드와 이어져서 이번에 enum을 유연하게 사용할 방법이 궁금했다.
예를 들면 위의 코드를 보면 DiscountType이 정확히 어떤 것인지 모르는 경우에 할인이 적용가능한지 알 수 있는 방법과 같은..
그래서 이를 활용하기 위해 canApply를 구현하도록 만들었다.
이를 활용하니 외부에서 사용할 때 유연하게 사용가능했다.
디테일한 부분은 전체 코드를 봐야 하지만, 내가 적용한 부분을 보면 매개변수가 DiscountType임을 알 수 있다.
즉 구체 타입은 모르지만, 들어온 값에 따라 동적으로 할인이 가능한지 여부를 구체타입에 따라 다르게 적용해 준다.
배운 점
이번에도 테스트를 진행할 때 Fixture를 적용했다.
객체를 생성하는 과정을 테스트에서 따로 사용하는 것인데, 이번에도 Fixture의 중요성을 느꼈다.
앞선 InputView에서의 고민 때문에 orders를 생성할 때 필요한 값이 계속해서 바뀌게 되었다.
그럴 때마다 테스트가 전부 다 깨지는 일이 빈번하게 일어나기도 했다.
결국 테스트도 관리의 대상이기에 프로덕션코드의 변경이 일어나면 테스트도 크게 바뀐다. 특히 생성하는 부분..
그래서 Fixture를 적용하니 추후에 바뀌어도 Fixture 부분만 수정해도 해결되기에 테스트를 관리하기 편해졌다.
예를 들어 Order가 생성자였다가 정적 팩토리 메서드로 바뀌었다고 가정하자.
결국 테스트가 전부 깨지게 된다.
실제 이런 일이 안 생길 것 같지만 생각보다 자주 일어났다.
이를 Fixture를 활용하니 변화에 빠르게 대응할 수 있었고 관리도 쉬워졌다.
생성자가 정적팩토리로 바뀌면 Fixture만 에러가 발생한다.
매우 쉽게 해결할 수 있다.
마무리
이외에도 많은 고민을 하고 적용한 점이 있다.
마지막 미션이 생각보다 어려워서 더욱 몰입할 수 있었던 것 같다.
코드를 작성할 때 타당한 이유를 찾으려 했고 이러한 과정 속에서 많은 성장을 했다고 생각한다.
오늘을 마지막으로 프리코스가 종료되는데, 정말 재미있었고 성장도 한 것 같아서 기쁘다는 생각이 들었다.
프리코스 과정 중에 조금 더 노력할 걸이라는 후회가 남지 않도록 정말 최선을 다한 것 같다. 그 덕분에 끝난 것이 아쉽기도 하지만, 과정은 너무나 만족스럽다고 생각한다.
최종 코테를 갈 수 있을지는 모르겠지만, 남은 기간 동안 꾸준히 노력해서 코테를 본다면 꼭 붙을 것이다.
'JAVA' 카테고리의 다른 글
[이펙티브 자바] 모든 객체의 공통 메서드 (0) | 2024.06.16 |
---|---|
[이펙티브 자바] 객체 생성과 파괴 (2) | 2024.06.13 |
[JAVA] 로또를 구현하면서 배운점 (2) | 2023.11.10 |
[JAVA] 자동차 경주를 구현하면서 배운점 (3) | 2023.11.02 |
[JAVA] 숫자 야구 게임을 구현하면서 배운점 (4) | 2023.10.27 |