[우아한테크코스 7기] 3주차 프리코스 회고

dev_yuni·2024년 11월 6일
9

우아한테크코스

목록 보기
3/4
post-thumbnail

들어가기 전에!

이번 미션은 로또를 자주 구매하는 편이 아니라서 문제를 잘못 이해한 점과 목표했던 것을 잘 이행했는지에 대한 의문과 마지막에 급한 수정으로 인한 깔끔하지 못한 코드 등.. 참.. 다사다난했던 것 같습니다.. 🥲

“오히려 회고 때 적을 게 많아졌네?! 완전 럭키Vㅣ키잖아! 🍀 ” 하고 마인드 컨트롤을 하고 회고를 작성해보겠습니다.

이전 리뷰에서요!

이전 미션에서 불변 객체와 함수(메서드) 작명에 대한 피드백을 받았고, 각각의 개념을 구체적으로 이해하고 적용하기 위해 학습을 진행했습니다.

불변 객체

위의 개념이 적용된 불변 객체는 생성된 후에는 내부 상태가 절대 변경되지 않는 객체를 의미합니다. 즉, 외부에서 수정할 수 없도록 제한하는 방식입니다.

Java에서 불변 객체의 특징은,
1. 필드를 final로 선언하여 객체의 상태를 변경할 수 없도록 합니다.
2. Setter 메서드를 제공하지 않아서 외부에서 값을 변경하지 못하도록 제한합니다.
3. 내부에 가변 객체가 포함된 경우에는 참조를 직접 반환하지 않고 복사본을 반환하여 상태 변화가 일어나지 않도록 합니다.

함수(메서드) 작명

메서드 작명은 항상 주의하려고 노력하지만, 가끔 메서드의 역할을 명확히 표현하지 못하거나 중복된 이름을 사용하는 경우가 생깁니다.
이번 학습을 통해 메서드 작명에 대해 구체적인 기준을 세워봤습니다.

  • 직관적이고 명확한 메서드명을 사용하여 메서드의 역할을 쉽게 파악할 수 있도록 합니다.
  • 변수명에 자료형을 포함하지 않습니다. 예를 들어, inputList 대신 inputs처럼 변수의 역할에 집중한 이름을 사용합니다.
  • 중복되는 이름을 포함하지 않습니다. 예를 들어, InputView.inputCount()처럼 클래스명과 메서드명이 중복되는 경우, 메서드명을 간결하게 변경하여 중복을 피합니다.

로또

기능 요구 사항

간단한 로또 발매기를 구현한다.

  • 로또 번호의 숫자 범위는 1~45까지이다.
  • 1개의 로또를 발행할 때 중복되지 않는 6개의 숫자를 뽑는다.
  • 당첨 번호 추첨 시 중복되지 않는 숫자 6개와 보너스 번호 1개를 뽑는다.
  • 당첨은 1등부터 5등까지 있다. 당첨 기준과 금액은 아래와 같다.
    • 1등: 6개 번호 일치 / 2,000,000,000원
    • 2등: 5개 번호 + 보너스 번호 일치 / 30,000,000원
    • 3등: 5개 번호 일치 / 1,500,000원
    • 4등: 4개 번호 일치 / 50,000원
    • 5등: 3개 번호 일치 / 5,000원
  • 로또 구입 금액을 입력하면 구입 금액에 해당하는 만큼 로또를 발행해야 한다.
  • 로또 1장의 가격은 1,000원이다.
  • 당첨 번호와 보너스 번호를 입력받는다.
  • 사용자가 구매한 로또 번호와 당첨 번호를 비교하여 당첨 내역 및 수익률을 출력하고 로또 게임을 종료한다.
  • 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시키고, [ERROR]로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
    • Exception이 아닌 IllegalArgumentExceptionIllegalStateException 등과 같은 명확한 유형을 처리한다.

실행 결과

구입금액을 입력해 주세요.
8000

8개를 구매했습니다.
[8, 21, 23, 41, 42, 43]
[3, 5, 11, 16, 32, 38]
[7, 11, 16, 35, 36, 44]
[1, 8, 11, 31, 41, 42]
[13, 14, 16, 38, 42, 45]
[7, 11, 30, 40, 42, 43]
[2, 13, 22, 32, 38, 45]
[1, 3, 5, 14, 22, 45]

당첨 번호를 입력해 주세요.
1,2,3,4,5,6

보너스 번호를 입력해 주세요.
7

당첨 통계
---
3개 일치 (5,000원) - 1개
4개 일치 (50,000원) - 0개
5개 일치 (1,500,000원) - 0개
5개 일치, 보너스 볼 일치 (30,000,000원) - 0개
6개 일치 (2,000,000,000원) - 0개
총 수익률은 62.5%입니다.

요구 사항 요약

  • indent depth(들여쓰기)가 3이상이 되면 안된다.
  • 3항 연산자는 쓰면 안된다.
  • 함수(메서드)가 한 가지 일만 하고 15 라인이 넘어가지 않아야 한다.
  • else 예약어는 쓰지 않는다.
  • Java Enum을 적용한다.
  • 단위 테스트*를 작성한다.

제 목표는요!

  • 요구 사항을 잘 지키자. (특히, 15 라인 넘기지 않는 것과 depth 3이상)
  • Enum을 써보자!
  • 불변 객체를 적극적으로 사용해보자.
  • 완성해보자!

이런 걸 고민했어요!

로또가..어떻게 되더라..?

미션을 받으면 가장 먼저 설계를 위해 문제를 분석합니다.
평소 로또를 잘 구매하지 않았던 저는.. 로또의 발급 과정에 대해서 잘 몰랐습니다..
지금 생각해보면 '왜 그렇게 생각했지?' 하지만 다음에는 이런 실수를 하지 않기 위해 작성해봅니다. 이번엔 그림을 그려가면서 어떤 흐름을 가지고 있는지 어떤 협력이 필요할 지 고민했습니다.
(부끄럽네요//)

저는 사용자에게 당첨 번호를 받는 것이 아닌 로또 번호를 받는 거라고 생각했습니다. 그래서 로또 번호 생성기가 당첨 번호까지 랜덤으로 생성되는 걸로 이해를..했습니다.
(이미 로또가 개수만큼 발행되는데 ,, 왜그랬는지 참..)
아무튼! 저 설계는 틀렸지만 흐름을 이해하는 데에는 도움이 됐습니다!

검증은 누가 책임질래!?

지금까지 Validator를 만들어서 한 클래스에서 관리하게 했습니다.
그런데 주어진 Lotto 객체 안에 검증 메서드가 들어있는 것을 보고 이번에는 객체가 스스로 검증하는 방식으로 해야하나 하고 고민했습니다.
하지만 저는 이번에도 Validator를 만들었습니다. 이유는 공통적인 검증 과정이 객체마다 중복되면 오히려 관리하기 어려울 것이라고 판단했기 때문입니다.
미션이 끝난 후 많은 분들의 코드를 보니 객체가 스스로 검증하게 하는 코드를 많이 봤습니다. 이후에 생각해보니 공통 검증 과정을 클래스로 분리하고 각 객체별로 필요한 검증을 따로 두는 것이 더 좋았을 것 같다고 생각이 듭니다.
검증에 대한 고민을 저뿐만이 아니라 많은 분들이 하신 것 같습니다. 커뮤니티에 토론하는 글을 읽으면서 다른 분들의 여러가지 생각들을 들어볼 수 있어서 정말 좋았습니다.

다시 입력하세요.

요구사항 중 이전 미션들과 다르게 예외가 발생하면 그 부분부터 재입력을 받는 사항이 추가되었습니다. 저는 재입력을 어디에서 담당하는 것이 좋을 지 고민했습니다.
View vs. Controller vs. Service 제가 고민한 담당 후보였습니다.
각각의 장단점을 아래에 적어보겠습니다.

  • View 계층 : 입력 관련 예외처리가 하나에 집중되니 쉽게 이해할 수 있습니다. 하지만, 입력만 받는 InputView에서 예외까지 처리하게 되면 비지니스 로직을 하게 되어 책임이 모호해질 것이라고 판단했습니다.
  • Controller 계층 : 전체 흐름을 관리하기 때문에 특정 시점에서의 입력을 제어할 수 있습니다. 하지만, Controller의 코드가 복잡해지니 가독성이 떨어질 것이라고 생각했습니다.
  • Service 계층 : 재입력을 담당하면서 비지니스 로직을 처리하기 떄문에 controller의 코드가 간결해집니다. 하지만, 비지니스 로직에 UI 관련 책임이 추가되기 때문에 단일 책임 원칙을 위반할 수 있습니다.

처음에 저는 Controller에서 while문을 사용하여 재입력을 처리했습니다.
근데 코드가 길어지니 가독성이 저하된다고 생각하여 분리하는 것이 좋겠다고 판단했습니다. 그래서 Service 계층에 재입력 책임을 주는 것으로 결정했습니다.

미션 제출 이후 다른 분들의 코드를 보면서 다양한 재입력 방법이 있다는 것을 알게되었습니다. 함수형 인터페이스를 사용하신게 정말 인상깊었습니다 👍

이런 점은 아쉬웠어요..

미안해.. 테스트 코드야..

이번에 로직을 구현하느라 목표인 단위 테스트를 신경쓰지 못했습니다.
문득 단순히 객체를 테스트 하는데 의문이 들었습니다. '객체가 잘 생성되는 지까지 불변한지까지 테스트를 과연 해야할까' 그래서 어떤 객체는 테스트를 한 것이 있고 하지 않은 것이 있는 신뢰성 없는 코드가 되어버린 것 같습니다..
4주차 미션에서는 테스트 코드를 신경써서 문서화로서의 기능을 할 수 있게 하겠습니다.

DTO 사용, 이번엔 놓치지 않을 거예요!

많은 분들이 이번 미션에서 DTO를 사용하신 것을 봤습니다.
저도 이전 리뷰에서 DTO를 적용해보는 것에 대한 제안을 받았었습니다.
그래서 '이번에는 DTO를 꼭 적용시켜야지!' 하고 다짐했지만 어떻게 활용할 지가 명확하지 않아 적용하지 못했습니다. 제목과 다르게 놓쳐버렸습니다.
(이해하고 사용하고 싶은 욕심이 좀 있었습니다!!)

급할 수록 차분하게

마지막에 재입력 받는 부분을 급하게 리팩토링 하다가 controller에 있던 주석을...지우지 못하였습니다. 불필요한 import도 제거하지 못한 것 같습니다.
급하게 PR을 올려야한다는 생각에 너무 지저분한 코드를 제출하게 되었습니다.

(이렇게 걸려버렸습니다. 사실 안걸리는게 이상합니다.. 😂 )
이번 일을 계기로 반성하며 다음에는 무리하게 리팩토링하거나 급하게 휙휙하는 일이 없어야겠다고 생각했습니다.

마지막으로!

참 마지막까지 많은 일들이 있었습니다. 하지만 리뷰를 주고 받는 과정에서 정말 많은 걸 배울 수 있었던 것 같아요. 서로의 리뷰 뿐만이 아니라 다른 분들의 다양한 리뷰를 보면 '어떻게 저렇게 생각하시지'하는 분들이 저어엉말 많았어요!

이번 4주차 미션을 보고 눈물을 살짝 머금긴했는데 그래도 이번 미션을 하면서 아쉬웠던 부분들, 실수 했던 부분들을 만회한다고 생각하고 열심히 해보려고 합니다!
그리고 이번에도 재입력을 받는 부분이 있더라구요! 그래서 함수형 인터페이스를 공부해서 재입력을 받는 방식을 도전해보려고 합니다. 아자아자!

지금까지 다들 너무너무 고생 많으셨고, 마지막까지 화이팅입니다 🍀

링크

구경 오셔서 꿀밤 때려주시면 달게 받겠습니다 🙇🏻‍♀️

PR 구경하러 가기!


참고

profile
꾸준히 성장하는 백엔드 개발자

2개의 댓글

comment-user-thumbnail
2024년 11월 7일

미안해.. 테스트 코드야.. 😆

회고 잘 읽었습니다!
일주일동안 많은 내용을 학습하신 것 같아요.
4주차에는 목표한 바를 꼭 다 이룰 수 있었으면 좋겠네요 😄
마지막까지 화이팅해봐요!! 🙌

함수형 인터페이스 공부하신다길래.. 제 정리글 홍보하고 갑니다.. 총총..
함수형 인터페이스와 표준 API

1개의 답글