[우테코 7기] 모바일 프리코스 2주차 회고록

[2주차] 자동차 경주

🚀 자동차 이름 목록과 경주 횟수를 입력받아 랜덤으로 이동하여 승자를 출력한다.

  • 주어진 횟수 동안 n대의 자동차는 전진 또는 멈출 수 있다.
  • 각 자동차에 이름을 부여할 수 있다. 전진하는 자동차를 출력할 때 자동차 이름을 같이 출력한다.
  • 자동차 이름은 쉼표(,)를 기준으로 구분하며 이름은 5자 이하만 가능하다.
  • 사용자는 몇 번의 이동을 할 것인지를 입력할 수 있어야 한다.
  • 전진하는 조건은 0에서 9 사이에서 무작위 값을 구한 후 무작위 값이 4 이상일 경우이다.
  • 자동차 경주 게임을 완료한 후 누가 우승했는지를 알려준다. 우승자는 한 명 이상일 수 있다.
  • 우승자가 여러 명일 경우 쉼표(,)를 이용하여 구분한다.
  • 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

 입력

  • 경주할 자동차 이름(이름은 쉼표(,) 기준으로 구분)
    pobi,woni,jun
  • 시도할 횟수
    5

 출력

  • 실행 결과 예시
경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)
pobi,woni,jun
시도할 횟수는 몇 회인가요?
5

실행 결과
pobi : -
woni : 
jun : -

pobi : --
woni : -
jun : --

pobi : ---
woni : --
jun : ---

pobi : ----
woni : ---
jun : ----

pobi : -----
woni : ----
jun : -----

최종 우승자 : pobi, jun

 


2주차 과제 구현 리포지토리

 

GitHub - medAndro/kotlin-racingcar-7: 자동차 경주 미션 저장소

자동차 경주 미션 저장소. Contribute to medAndro/kotlin-racingcar-7 development by creating an account on GitHub.

github.com

 

 

1주차 공통 피드백

사실 1주차 코드를 구현하면서 이전 기수의 공통 피드백을 미리 참고하였던 터라 이미 지키고 있었다 (1주차 과제 진행 중에 "의미 없는 주석을 달지 않는다"를 보고서 뒤엎기도 하였고...)
검색하면 나오는 이전 기수의 피드백과의 차이점은 없었다고 생각한다. 약간의 단어 수정 정도?
2주차 과제는 공통 피드백을 더욱 반영해 코드로 의도를 나타내는데 주력하고 주석을 최소한으로 수정하기로 했다.

 

1주차 코드 리뷰 지적받은것

  •  println문 하드코딩 
    • main()에서 하드코딩한 이유에 대해서 지적받았는데 이건 고쳐야겠다고 생각했고 2주차에서 Messages 객체에서 출력문을 관리하는것으로 고쳤다.
  • 연관된 함수들이 서로 떨어져있는 응집성 문제
    • 2주차 과제에서 MVC패턴을 적용하여 어느정도 해결하였다고 생각한다.

2주차 과제의 첫인상

저번주보다 모호한 요구사항이 적게 느껴저 구현 자체는 더 쉬웠다고 느꼈다. (사실 1주차도 처음엔 쉬워보였지만 요구사항을 여러번 읽었을때 모호한 내용이 꽤 많아서 리팩터링 하는데 시간을 많이 보냈지만..)
학습 목표에서 테스트 도구를 사용하는 방법을 익히라고 해서 JUnit 5와 AssertJ를 사용법을 익히고 난 뒤 TDD로 개발하는 것을 목표로 했다. 

개발 순서

회고하며 다시 생각해봐도 1주차처럼 모호한 내용은 없었다고 생각한다. 구현 초반의 개발 순서는 다음과 같다

  1. API로 자동차 이름 문자열과 경주 횟수를 입력받는다
  2. 쉼표로 분리하여 LinkedHashMap 자료형에 Key로 자동차 이름, Value로 거리를 0으로 초기화하며 저장한다.
  3. 경기를 한번 진행하는 코드를 작성한다.
  4. 경주 횟수만큼 반복한다.
  5. LinkedHashMap의 Value의 최대값을 찾아 Key를 찾고 우승자로 출력한다.

TDD를 사용하기 위해 중간중간 테스트도 진행하면서. 이 순서대로 구현을 완료하였다.

TDD 그리고 Private 메서드

TDD는 실패하는 작은 단위 테스트를 작성하고 테스트가 성공하도록 코드를 작성하는걸 반복하여 개발하는것을 말하는데. 테스트 코드 작성을 잘 할줄 모르는 상황이라 테스트 코드에 대한 테스트 코드가 필요하다고 생각될 지경이였다... 

실제로 테스트코드가 제대로 돌아가는지 의심스러워서 메소드를 거의 완성한 시켜가며 테스트를 작성하곤 했으며 따라서 완전한 테스트 주도 개발이라고 보긴 어려울듯 싶다... TDD를 적용하려면 테스트 코드 작성에 더 익숙해지고 난 뒤에 적용하는게 좋을것 같다...
테스트를 작성하면서 Private 메서드가 잘 작동하는지 테스트하고 싶다는 욕구가 들었는데 나 말고도 그런 사람이 넘쳐나는지 Junit의 창시자 Kent Beck이 하도 물어보니까 만든 사이트 shoulditestprivatemethods.com에 답이 나와있다.

"하지마"


private 메서드는 public 메서드의 구현에 포함되는 영역으로서 테스트 대상이 아닌것이다. 따라서 공개된 메서만 테스트 하기로 하였다.

 

MVC 디자인 패턴

[10분 테코톡] 도기의 MVC 패턴


MVC패턴을 공부하고 적용면서 느낀것은 여러 블로거의 포스팅을 뒤져봐도 프로그래밍 문법처럼 딱 떨어지지 않고 사람마다 약간씩 달라서 혼란스러웠다 MVC패턴을 이미지 검색하면 나오는 모식도 역시 저마다 약간씩 다르게 그려져 있다.
이렇게 혼란스러울떄 10분 테코톡 발표 영상을 보고 "MVC 패턴은 효율적인 유지보수를 위해 뷰와 도메인의 관심사를 분리하는것이며 정해진 규칙이나 구현 방법이 없다."라는 것을 알게 되었다.

내가 생각하는 MVC의 구체적인 구현방식.

 

과제를 진행하면서 내가 생각하는 MVC패턴은 컨트롤러라는 중재자가 있고 과제의 프로젝트 규모를 고려해 오버엔지니어링이 되지 않도록 DTO는 사용하지 않고 모델과 뷰는 서로를 모르게끔 구현하는것으로 진행했다.
 1차로 구현을 완료한 코드를 MVC 구조로 리팩터링을 진행하면서 구성요소가 명확하게 분리되니 기존 코드보다 유지보수가 쉽다고 느껴졌다. (예를 들어 입력 예외 처리가 잘못될 경우 컨트롤러에 연결된 Validator를 수정하면 되니까.)

 

이번 과제를 하는데 [10분 테코톡] 도기의 MVC 패턴 영상제리의 MVC패턴 영상 이 많은 도움이 되었다. (제리의 MVC 영상에서 설명하는 예제가 무려 이번 2차 과제랑 동일하다), 단 제리의 MVC패턴 영상에서 View에서 모델 객체를 파라미터로 받아 모델의 구조를 알아야 출력이 가능한 방식으로 구현하고 있는데 이것은 지양했다. (규모가 커질 경우 모댈 객체를 포장하는 DTO를 사용하여 비슷하게 구현하는건 괜찮을 것 같다.)

 

이번 과제를 통해 알게 된 코틀린

  • 데이터 클래스를 사용해보었다.
    • getter setter를 따로 구현할 필요 없이 객체.프로퍼티로 값을 넣거나 뺄 수 있어 편하다.
  • 예외처리를 위해 일일히 throw를 던지고 있었는데... require()를 사용하여 괄호 안의 false일 때 IllegalArgumentException 를 발생시켜 입력값을 검증할 수 있다는걸 알게 되었다. 
  • try catch대신 runCatching{}을 사용할 수 있다는걸 알았다
    • 중괄호 안의 함수가 성공하면 Result객체를 반환한다.
    • getOrElse{}는 Result객체의 메서드로서 Result가 실패하였다면 getOrElse{}의 람다식{중괄호안}을 실행한다.
  • 의존성 주입과 팩토리 메서드 사용법에 대해 알아보았다.
    • 컨트롤러의 생성자를 통해 뷰와 예외처리기, 서비스 등을 주입하여 결합도를 낮췄다.
    • 팩토리 메서드를 사용함으로써 객체 생성 로직을 캡슐화하고, 코드를 단순화 사켰다.

 

Pull Request와 과제 제출

이번엔 우테코 6기에서 만든 서비스인 CoReA의 코드 리뷰 가이드를 참고해서 PR을 작성했다.

예제는 문제없이 통과할거라 생각했고 역시나 한번에 통과했다.

 

3주차에 공부할거리

  • 공통 피드백, 코드리뷰 개선사항 꼼꼼히 보고 적용할것
  • 테스트 코드 작성을 더 공부할것
    • 아무 값이나 반환시키도록 빈 메소드를 일단 만들고 구현해나가는 방식의 TDD접근법을 시도
    • private 함수를 테스트하고 싶다면  클래스 분리를 해볼것 <- 과거 공통 피드백 내용
    • 테스트하기 좋은 메서드로 개발할것 (참고)
  • 코틀린 문법을 더 공부할것. 아직도 모르는게 너무 많다....