본문 바로가기
우아한테크코스

우아한테크코스(프리코스) 3주차 회고

by 임동무 2022. 11. 15.

이번 주차 미션은 로또 미션이다.

https://github.com/woowacourse-precourse/java-lotto

 

GitHub - woowacourse-precourse/java-lotto: 로또 미션을 진행하는 저장소

로또 미션을 진행하는 저장소. Contribute to woowacourse-precourse/java-lotto development by creating an account on GitHub.

github.com

 

 

이번 주차를 진행하면서 우아한 테크 코스에서는 추가 요구사항을 부여했다.

추가된 요구 사항

  • 함수(또는 메서드)의 길이가 15라인을 넘어가지 않도록 구현한다.
    • 함수(또는 메서드)가 한 가지 일만 잘 하도록 구현한다.
  • else 예약어를 쓰지 않는다.
    • 힌트: if 조건절에서 값을 return하는 방식으로 구현하면 else를 사용하지 않아도 된다.
    • else를 쓰지 말라고 하니 switch/case로 구현하는 경우가 있는데 switch/case도 허용하지 않는다.
  • Java Enum을 적용한다.
  • 도메인 로직에 단위 테스트를 구현해야 한다. 단, UI(System.out, System.in, Scanner) 로직은 제외한다.
    • 핵심 로직을 구현하는 코드와 UI를 담당하는 로직을 분리해 구현한다.
    • 단위 테스트 작성이 익숙하지 않다면 test/java/lotto/LottoTest를 참고하여 학습한 후 테스트를 구현한다.

 

 

요약하자면 

1. 메서드를 잘 분리해서 15라인을 넘어가지 않도록 구현하라

2. 조건절을 조기 return 하거나, enum 클래스를 활용하여 else 문 사용을 회피하라.

3. 도메인 로직에 단위 테스트를 구현하며 핵심 로직을 구현하는 코드와 UI 를 담당하는 로직을 분리해 구현한다.

 


1. 기능 요구사항 작성

지금까지 기능 요구사항을 작성할 때에 그저 간단하게 기능을 나누어놓고 그거에 맞추어 커밋만 하면 된다고 생각했다.

하지만 코드 리뷰를 통해 여러 사람 코드를 보면서 사람들이 기능 요구사항을 굉장히 세세하게 짠다는 것을 알았고 이번 주차에는 나도 세밀한 기능 요구사항을 작성 해야겠다고 생각했다.

왼쪽 : 저번주 기능 요구사항  오른쪽 : 이번주 기능 요구사항

 

개발을 시작하기 전에 기능 요구사항을 세세한 기능까지 분류하여 작성하니

물론 기능 요구사항을 작성하는 시간은 훨씬 더 오래 걸렸지만 마치 간이 코딩을 하는 듯한 느낌이 들었으며 1. 클래스 분기가 비교적 쉬워졌고, 2. 메서드 리펙토링이 줄어들었다. 

 

기능 요구사항을 작성하면서 자연스럽게 클래스를 분리하며 각 클래스의 설명에 대해 작성한다.

또한 각 클래스에 포함되는 메서드를 하나하나 정의해가며 메서드가 과연 1개의 기능만을 가지고 있으며

그 메서드 들이 모인 클래스가 한가지 임무만 담당하는지에 대해서 계속해서 생각하며 작성했기 때문에

 

코딩을 하면서 클래스 분기나 메서드 리펙토링에 대해 고민할 필요가 많이 줄었다.

(물론 내가 작성한 기능 요구사항 자체에 오류가 있어 이 부분에 대해서 수정해야 할 때도 많았으며 그 때는 클래스 분기나 메서드 리펙토링에 대해 한 번 더 고민을 해야했다.)


2. MVC 패턴?

저번 주 다른 사람의 코드를 보고 MVC 패턴에 대해서 공부해서 이번 주차에는 적용 해봐야겠다고 생각했다. 하지만 기능 목록을 작성하고 나니 구현에 너무 많은 시간이 걸릴 것으로 예상되어 일단 요구사항 부터 확실하게 지키자고 판단했다.

그래서 메인 로직 담당 클래스들과 UI 담당 클래스로 나누어서 두 임무를 분리하였다.

 

또한 입,출력과 관련된 기능들과 같은 경우에는

"굳이 인스턴스를 생성할 필요가 있을까?" 라는 생각이 들었다.

 

그래서 입/출력 관련 기능들은

입력과 출력을 담당하는 클래스의 메서드들을 static 으로 선언하여 인스턴스 생성 없이 메서드를 사용할 수 있도록 작성했다.

 

 


3. 예외처리

이번주 주차를 진행하면서 가장 헤맸고, 가장 수정 많이한 부분이다. 

처음에는 예외를 모두 한 군데에 묶어서 마찬가지로 static 정의하려고 했고 그렇게 작성했다.

 

하지만 웬걸... 핵심 클래스인 Lotto 클래스 (일급 컬렉션) 이 생성자 내부에서 예외를 확인하고 있가. 

 

그래서 결국 예외 담당 클래스를 전부 삭제하고 예외가 발생하는 각각의 지점에서 예외를 처리해주기로 했다.

 

 

기능을 구현하던 어느날 갑자기 메일 한 통이 날라왔다.

'IllegalArgumentException' 을 발생시키고 -> 로그를 찍고 -> 프로그램을 종료하는 방향으로 생각하세요.

이 문장을 보고 프로그램 종료 전 로그를 찍으라는 의미라고 해석했다.

 

하지만 테스트를 돌려보니 자꾸만 테스트가 실패했고 결국 나는 이것이 문제 오류라고 생각하여 우아한 테크 코스에 메일을 보냈다.

답장이 없었다.... 결국 내 잘못 이라는 뜻이다....

 

계속해서 생각해보았고 저 문장을 곱씹어보았다. 그랬더니 결국 해결책에 도달했다.

예외를 발생시킨 시점에서는 IllegalArgumentException 을 발생시키고 이를 상위 메서드에서 받아서 로그를 찍고, 프로그램을 종료하라는 방식이었던 것이다.

 

그래서 어플리케이션의 main 메서드 전체를 try~catch문으로 묶어서 예외가 발생할 경우,

예외발생 -> 로그 찍기 -> 프로그램 종료 의 순서가 지켜지도록 코드를 구현했더니 테스트를 통과할 수 있었다.

 

 

 


3주차 총평 :

이번 3주차는 지금까지의 주차보다 훨씬 더 시간 사용을 많이 한 것 같다.

언급한 여러 이유가 있겠지만 이번 주차에서 가장 아쉬웠던 점은 요구사항을 꼼꼼하게 읽어보지 않았다는 점이다.

 

꼼꼼하게 읽지않아서 실수한 첫 번째 부분은 Randoms 의 pickNumberInRange() 를 활용했다는 것이다.

처음에는 난수 생성시 전주차와 동일한 메서드를 사용하여 전부 구현하고 테스트를 돌리는데 시간초과가 떴다...

 

어떤 부분인지 확인하기 위해서 여러 코드를 수정해보면서 해결해보다가 결국 난수를 생성하는 부분에서 시간초과가 발생한다는 사실을 알았다. 그래서 이를 어떻게 해결할 까 고민한 끝에 저번주에 정의된 이유가 궁금했던 pickUniqueNumbersInRange() 를 사용해보기로 했다. 이를 사용하니 해결할 수 있었고 그럼 이걸 사용해도 되나? 라는 생각에 요구사항을 다시 한번 읽어 보았더니 애초에 이 메서드를 사용하는 것이었다...

 

두 번째 부분은 예외처리 부분이다.

나는 예외처리를 계속해서 하나의 클래스에서 정의해야겠다고 고집을 부렸다. 

 

그래서 예외처리를 전부 다 구현해놓고 막상 사용하려고 하니, 테스트에 Lotto를 생성하는 생성자에서 예외처리를 하는 테스트가 정의되어 있었다.. 

그렇다면 Lotto 의 생성자에서 List<Integer> 를 파라미터로 받아서 얘외처리를 하려고 하였으나

전부 String 입력값을 파라미터로 예외처리를 하였고 다른 예외처리는 전부 예외를 모아놓은 클래스에서 관리하지만 

Lotto 관련 예외처리는 Lotto 에서 관해야하는 문제가 발생하였다.

 

그래서 결국 예외처리는 각 예외가 발생하는 부분에서 관리하는 것으로 수정하였고 예외 메시지만 Constant 상수 클래스에 저장하는 방향으로 수정하였다.

 

 

 

그 전까지는 이 모든 요구사항들을 내가 최종 코딩 테스트에서 5시간 만에 구현할 수 있을까? 라는 질문을 스스로에게 계속해서 하면서 조금이라도 더 빠르게 구현하기 위해서 신경을 많이 썼던 것 같다.

 

하지만 이번 주차를 진행하면서 그냥 그런 생각을 다 버리기로 했다.

최종 코딩 테스트에서 작성한 기능 목록중에 1개밖에 구현을 못하던, 10개를 구현하던, 전체를 다 구현하던지는 이제 중요하지 않다.

 

그저 내가 기능 요구사항을 꼼꼼하게 읽고 나서

최대한 수정이 적도록 기능 목록을 작성할 수 있는 역량을 키우고,

들여쓰기 수준, else 예약어 사용 금지 등 주어지는 추가 요구사항에 최대한 적합하게

하나의 기능이라도 구현할 수 있다면 그걸로 충분히 성장했다고 생각한다.

 

 

 

댓글