Skip to content

TDD, 클린코드를 적용하여 로또 게임 구현

Notifications You must be signed in to change notification settings

Perhona/java-lotto

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

로또


미션을 완수하고 배운 내용 by Perhona

  • 요구사항 분석을 철저히 진행하여 작은 단위로 기능을 나누고, 그에 따라 객체를 설계
  • 사이드 이펙트를 발생시킬 수 있는 클래스 내 멤버변수 선언을 지양하고, 메서드로 질의할 수 있도록 설계
  • 주석 없이도 팀원이 알 수 있는 명확한 메서드명을 짓기
  • get()으로 값을 꺼내서 변경하는 방식의 설계 지양
  • Enum 클래스를 사용하여 많은 상수 값을 관리
  • 넘겨받은 파라미터 값을 바꾸는 것은 안티패턴으로, 사용을 지양
  • 스트랭글러 패턴을 통한 기존 로직과 신규 로직이 공존하며 진행되는 점진적인 리팩토링

진행 방법

  • 로또 요구사항을 파악한다.
  • 요구사항에 대한 구현을 완료한 후 자신의 github 아이디에 해당하는 브랜치에 Pull Request(이하 PR)를 통해 코드 리뷰 요청을 한다.
  • 코드 리뷰 피드백에 대한 개선 작업을 하고 다시 PUSH한다.
  • 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.

온라인 코드 리뷰 과정


🚀 1단계 - 문자열 계산기

기능 요구사항

  • 사용자가 입력한 값에 따라 사칙연산을 수행할 수 있는 계산기를 구현한다.
    • 덧셈
    • 뺄셈
    • 곱셈
    • 나눗셈
  • 입력 문자열의 숫자와 사칙 연산 사이에는 반드시 빈 공백 문자열이 있다고 가정한다.
  • 나눗셈의 경우 결과 값을 정수로 떨어지는 값으로 한정한다.
  • 사칙연산의 계산 우선순위가 아닌 입력 값에 따라 계산 순서가 결정된다.
  • 입력값이 null 이거나 빈 공백 문자일 경우 IllegalArgumentException throw
  • 사칙연산 기호가 아닌 경우 IllegalArgumentException throw
    • Sign 클래스 생성 후 검증

프로그래밍 요구사항

  • indent depth는 최대 1단계까지
  • 메소드 크기가 최대 10라인 이하(한가지 일만 하도록 한다.)
  • else 를 사용하지 않는다.

Feedback 23.11.19

  • Stack -> Queue 변경
  • while -> for 변경
  • Sign Enum 구현
  • 연산작업에 대한 위치 고민
    • Sign Enum 에게 위임
  • Main 클래스 생성

Feedback 23.11.21

  • 멤버 변수로 정의하면 객체는 상태를 갖게 됨, 멤버변수 선언 지양
  • Calculator 내부 메서드 divide 의 이름 고민
  • 멤버변수가 아닌 매개 변수로 넘기면서 자연스러운 표현 고민
    • Calculator 클래스 전체 구조 수정
  • 사용자 입력 기능 추가
  • Sign의 validate 방식 변경
  • Sign의 of()와 calculate() 테스트 분리

Feedback 23.11.22

  • Sign 구조 개선

🚀 2단계 - 로또(자동)

기능 요구사항

  • 로또 구입 금액을 입력하면 구입 금액에 해당하는 로또를 발급해야 한다.
  • 로또 한 장의 가격은 1000원이다.
  • 금액을 입력받아 로또를 구매한다.
  • 로또 번호는 1부터 45까지이며, 로또 한 세트의 번호는 중복되지 않는다.
  • 지난 주 당첨 번호를 입력받아 당첨 통계

Todo

  • 6개로 이루어진 로또 set를 로또 갯수만큼 생성한다.
    • 로또 1개를 생성한다.
    • Colletions.sort() 메소드로 정렬
  • 당첨 통계
    • 지난 당첨 로또 생성
    • 당첨 로또 중 3, 5, 6개 일치 시 당첨으로 간주
    • 등수별 당첨 갯수 반환
    • 총 수익률
      • Lotto 순위 enum 추가
        • 몇 개일 때 당첨인지
        • 당첨금은 얼마인지
      • LottosResult 가 관리하는 것
        • 전체 수익률
        • 등수당 당첨 갯수

프로그래밍 요구사항

  • 모든 기능을 TDD로 구현해 단위 테스트가 존재해야 한다. (UI 로직 제외)
  • UI 로직을 InputView, ResultView와 같은 클래스를 추가해 분리한다.
  • indent depth는 1까지 허용
  • 함수(메소드) 길이가 15라인을 넘어가지 않도록 구현한다.
  • else 예약어를 사용하지 않는다.

Feedback 23.11.24

  • LottoGenerator 테스트를 위한 동작 분리
  • Lotto 내 변수의 재사용성 고민
    • 외부에서 주입받은 변수 외 멤버변수 삭제
  • Lotto의 생성자 2개 중 테스트를 위한 생성자를 없애기
    • 생성자 방식 변경
  • Lotto의 멤버변수 ranking의 위치 고민
    • 삭제
  • Lotto의 멤버변수 matchingCount를 쓰지 않기
    • 삭제, 메서드 이용하여 return
  • Stream의 generate와 limit 활용
  • 수익률 계산 역할의 위치 고민
  • Map.of() 활용
    • Ranking 내 Map 삭제

Feedback 23.11.27

  • increaseMatchingCount() 구조 변경
  • LottoGenerator 의 lottos() 구조 변경
  • Stream 표현식을 가독성있게 변경

🚀 3단계 - 로또(2등)

기능 요구사항

  • 로또 2등 당첨을 구현한다.
    • 당첨 확인을 위해 보너스 번호를 별도로 입력받는다.
    • 2등 당첨은 5개 번호 일치 + 보너스 번호 일치이다.
    • 당첨 통계에 2등을 추가한다.

프로그래밍 요구사항

  • java enum을 적용한다.
  • 일급 콜렉션을 사용한다.

Feedback 23.11.29

  • 2등을 찾는 로직 개선

🚀 4단계 - 로또(수동)

기능 요구사항

  • 사용자는 수동으로 구매할 로또 수를 입력한다.
  • 사용자는 수동으로 구매할 번호 6개를 구매할 수량만큼 입력할 수 있다.
  • 사용자가 입력한 갯수 외 나머지는 자동으로 생성한다.
  • LottoNo를 이용해서 로또 각 번호의 유효성을 검사한다.
    • Lotto의 각 번호
    • WinningLotto의 보너스 번호

프로그래밍 요구사항

  • 사용자가 잘못된 값을 입력했을 때 java exception으로 예외 처리를 한다.
  • java8에 추가된 Optional 을 적용해 NullPointerException이 발생하지 않도록 한다.

Feedback 23.12.03

  • 파라미터의 의미를 명시적으로 드러내주기 위해 변수로 추출
  • 클래스명이나 변수명에 줄임말을 쓰지 않고, 컬렉션은 복수로 표현
  • number -> new LottoNo(number) 에서 생성자 레퍼런스 활용
  • Lotto ranking 메서드 내 당첨 로또와 비교하는 부분에서 WinningLotto에게 contains를 직접 질의하기

About

TDD, 클린코드를 적용하여 로또 게임 구현

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%