본문 바로가기

우아한테크코스/코드 리뷰

로또 게임 1

3주차 역시 새로운 짝과 새로운 미션을 시작하였다.

저번 주에 했던 TDD는 그대로 유지를 하면서 진행하였다.

이번 미션은 로또 게임이였다.


요구사항

요구사항에 보면 모든 원시값과 문자열을 포장한다. 라는 규칙이 있다.

3주차에는 확실히 2주차에 했던 자동차 게임보다 객체의 수도 훨씬 많고 어려워져서 객체지향적인 코드를 짜기 힘들었다.

그래도 페어와 최대한 객체지향적인 코드를 작성하려고 노력했다.

3주차에는 미션을 진행하면서

  • Exception
  • 컴포지션 패턴
  • 팩토리 패턴
  • ENUM
  • Stream API

등등 여러가지 새로 배우는 것들이 많았다.

굵직굵직한 주제들은 따로 블로그에 정리해서 올릴 예정이다.

Stream API는 지난 미션을 통해 알고있었던 부분들이지만 겉핥기식으로 알고있었다는 걸 이번 미션을 통해 깨달았다. 확실히 학습하고 정리해서 내것으로 만들고자 다짐했다.


짝이였던 학성의 코드 또한 내 코드와 매우 비슷했기 때문에 학성의 리뷰와 내 리뷰를 통해 깨달은 사실을 정리하고자 한다!

방어 로직이 필요한 코드인지, 어떤 파라미터가 넘어올 확률이 있는지 더 고민해보고 방어가 잘 된 코드를 짜려고 노력해야겠다는 생각이 들었다.


new Line을 만들 때 무조건 \n이면 되는 줄 알고 있었는데 그게 아니었다.

운영체제별로 다르기 때문에 앞으로는 newLine을 만드는 코드도 다르기 때문에 리뷰 내용처럼 앞으로는 System.lineSeparator() 메소드를 사용해서 처리한다면 더 이식성이 좋은 프로그램이 될 수 있겠다.생각했다.


Collection 인터페이스에서는 Iterable 인터페이스를 상속받고 있기 때문에 Stream의 중간연산 없이 forEach만 사용한다면 Iterable의 forEach를 사용해서 Stream을 생성하는 비용을 절약할 수 있다.

분명 Iterator & Iterable을 정리한 글에서 공부하고 정리해서 알고있었던 내용인데 습관처럼 Stream으로 forEach를 사용하고 말았다.

학습과 정리도 중요하지만 실습하고 응용해서 내 것으로 만드는 것도 참 중요한 것 같다. 그런 의미에서 코드리뷰는 내가 못봤던 부분들을 봐주시니까 너무 좋은 것 같다.


Stream을 잘 쓰는 사람이 되는 길은 멀고도 험하다. 저 부분을 꽤 오래 고민했는데 메서드 레퍼런스를 사용해서 가독성을 향상시킬 생각을 미처 하지 못했다. 메서드 레퍼런스를 쓴 코드가 가독성이 더 좋다면 안 쓸 이유가 없다. IDE의 기능을 활용해서 메서드 레퍼런스와 아닌 코드를 비교해보는 것도 좋을 것 같다고 생각했다.


중복된 코드는 피해야 한다. 당연히 알고있던 사실이지만 검증에도 중복이 있을 수도 있다는 걸 깨달았던 리뷰였다. 검증에 중복이 있는지 눈길조차 안줬던 것 같다. 테스트 코드를 포함해서 모든 코드는 중복될 수 있다는 사실을 깨달았다.

두 곳에서 하던 검증을 한 곳에서 검증하니 훨씬 더 명확한 코드가 된 것을 느낄 수 있었다.


Rank에 맞은 개수를 넘겨주면 몇 등인지를 리턴하고 3등이라면 LottoManager에서 보너스볼과 일치하는지 확인해서 2등인지를 확인하는 구조였는데 굳이 그럴 필요가 없었다.
오히려 서로 의존적인 관계가 되어서 결합도가 높아질 뿐이였다.

비슷한 기능으로 서로 의존적인 관계를 만들지 말고 하나의 기능을 확실히 한 곳에서 처리해서 응집도를 높이고 결합도는 낮춰야 된다는 걸 깨달았다.


테스트 코드를 수정하던 중 의문이 생겨서 이런 질문을 하기도 했다. 질문을 요약하면 한 클래스의 단위 테스트를 할 때 다른 클래스의 기능을 써도 되겠냐는 질문이었다.

답변으로 클래스 테스트는 가능한 독립적으로 영향을 안받게 구현하는 것이 맞지만
사용하려는 기능이 어차피 프로그램 다른 곳에서도 그 기능을 하기 때문에 수용할 수 있는 부분이라고 하셨다.

답변해주신 리뷰어님께 너무 감사했다. 뭔가 이론적인 원칙도 중요하지만 상황에 따라 적절히 판단하는 것과 그 능력도 중요한 요소인 것 같다.



처음에는 로또 등수를 나타낼 Rank라는 enum에서 변수를 하나 두고 그 등수에 몇번 당첨됐는지를 기록하려고 했었다.

하지만 이 부분은 굉장히 문제가 많은 코드였다. Enum은 프로그램이 실행될 때 각각의 인스턴스가 딱 하나만 생기는 것을 보장하는데 내부에서 변경되는 상태값을 가지면 문제가 되는 것이다. 상태값을 가지는 변수를 다른 클래스로 분리함으로써 문제를 해결했다.


로또 클래스가 있고 당첨 로또 클래스가 있을 때 중복되는 부분이 많기 때문에 당첨 로또에서 로또를 상속하는 구조로 만들었었는데 위와 같은 피드백을 받았다.

상속대신 컴포지션 패턴을 사용해야 한다. 위의 내용은 공부하다보니 내용이 많고 정리해두고 싶어서 블로그에 따로 정리할 예정이다!


Optional 일때는 항상 값이 없을 경우를 생각해야겠다. Optional을 잘 모르고 사용했기 때문에 생긴 문제인 것 같다. Optional은 생성 비용이 비싸기 때문에 신중히 사용해야 하는데 관련 내용을 한 번 깊게 공부하고 정리해볼 생각이다.


미션을 마쳐야 하는 시간이 정해져있고 짝프로그래밍으로 진행을 하다보니 시간이 너무 촉박했고 원하던대로 전부 구현하지는 못했다.

하지만 실무에서도 시간을 넉넉히 주지 않기에 주어진 시간내에서 최선의 결과물을 뽑아내는 연습을 하고있다고 생각한다.

언젠가는 꼭 한 번 리뷰할 게 없는 그런 멋진 코드를 짜보고싶다.

'우아한테크코스 > 코드 리뷰' 카테고리의 다른 글

블랙잭 2  (0) 2020.03.30
블랙잭 1  (0) 2020.03.18
로또 게임 2  (0) 2020.03.02
자동차 경주 게임  (0) 2020.02.18
문자열 계산기  (0) 2020.02.10