클린코드를 위한 TDD, 리팩토링 with Java
edu.nextstep.camp
경험해야할 학습 목표
- TDD 기반으로 프로그래밍하는 경험
- 메소드 분리 + 클래스를 분리하는 리팩토링 경험
- 점진적으로 리팩토링하는 경험
경험할 객체지향 생활 체조 원칙
- 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기만 한다.
- 규칙 2: else 예약어를 쓰지 않는다.
- 규칙 3: 모든 원시값과 문자열을 포장한다.
- 규칙 5: 줄여쓰지 않는다(축약 금지).
- 규칙 8: 일급 콜렉션을 쓴다.
로또 미션을 끝내고 작성하는 후기다.
자동차 경주보다는 더 어려웠으며 많은 지적을 받았다.
step1, 문자열 덧셈 계산기
이전 자동차 경주 때 했던 문자열 계산기와 비슷하다.
, 콤마로 문자열을 나누는것과 동일하다. 다른 점은 사용자가 커스텀구분자를 추가하여 그 구분자로 분해하는 요구사항이 있다.
[step1] 문자열 계산기 리뷰 부탁드립니다 by loop-study · Pull Request #1250 · next-step/java-lotto
안녕하세요 박현철입니다. 문자열 계산기 리뷰 부탁드리겠습니다! 수정하거나 보완이 필요한 조금이라도 있으면 많은 피드백 부탁드리겠습니다!!!📖📖📖📖📖📖📖📖📖📖📖📖
github.com
이전에 비슷한 경험을 해서 그런지
이 단계에서는 매직넘버(하드코딩 값)을 상수로 바꿔달라는 요청 등을 받고 넘어갔다.
step2, 로또(자동)
본격적인 로또 과제에 돌입했다.
[step2] 로또 자동 리뷰 부탁드립니다. by loop-study · Pull Request #1256 · next-step/java-lotto
안녕하세요 박현철입니다. 이전 미션에서 배웠지만 아직도 미숙한 점이 많습니다. 진행하면서 생긴 의문사항 질문드립니다 로또 당첨 결과내역에 대한 수익률이 1 기준에 따라 손해, 이익 출력
github.com
새롭게 추가된 객체지향 생활체조 규칙들이 있는데도, 리뷰어님이 더 추가해주신 생활체조 규칙이 있었다.
덕분에 이전보다 생소한 환경으로 많은 자동차 경주보다 많은 시간을 생각하고 진행하게 되었고,
어찌어찌 결과를 낼 수 있었다. 하지만 아주 제대로 뚜드려 맞기 시작했다🙈
내가 생각했던 역할과 책임에서 미숙하여 하나로 합쳐야 되는것도 있었고, 새로운 역할을 만들어주는 게 어떠냐는 피드백도 있었다.
특히 로또 당첨 순위에 대해 enum Rank 로 관리하고, 당첨 결과에 대한 LottoRank 를 관리했다가 둘을 합치는게 어떠냐는 의견과
무의식적으로 줄임말을 사용했던 거와 매직넘버를 그대로 사용한 케이스가 여럿 있어서 지적 당했다.
단순 반복문이 아닌 스트림으로 변경해보는건 어떠냐는 지적도 존재.
테스트에 대해 여러가지 의견을 주셨다.
가장 중요한건 생활체조의 원칙 2가지를 지켜달라 하셨다
규칙 7 : 3개 이상의 인스턴스 변수를 가진 클래스를 쓰지 않는다.
규칙 9 : 게터/세터/프로퍼티를 사용하지 않는다.
많은 Request Changes 를 받았고 수정하게 되었다.
step3, 로또(2등)
이전 단계에서 추가사항으로 2등이 생긴 단계이다.
[로또 3단계] 리뷰 요청드립니다. by loop-study · Pull Request #1278 · next-step/java-lotto
안녕하세요 박현철입니다 지난번에 요청을 누락했다는 피드백보고 상수클래스 처리했습니다(죄송합니다😭😭😭) 확인해주시고 피드백 부탁드립니다!!
github.com
진행은 예상보다 단순했다. 지난번 피드백을 반영하고 리뷰요청을 드렸고
리뷰어님도 응집도 관련해서 책임을 옮기고 역할만 재설정하고 다시 요청부탁한다는 단순한 피드백에
이전단계에서 많은 수정을 했으니 잘 넘어가나 싶었다.
하지만 다시 요청을 드린 뒤 새로운 지적사항들이 나타나기 시작했다.
변수명이 겹치는거 같다, 게터를 사용하지 말고 다른 방식으로 해달라, 이 책임을 다른 곳에 옮기면 좋을 거 같다 등
수정 후 재요청 해달라 했다.
많은 고뇌의 시간을 가지게 되었다.
리뷰어님의 지적을 다시 한번 되짚어가면서
내가 설계한 역할과 책임에 대한 모든 의심이 시작되고(이게 정녕 맞긴한가?)
수정하다가 테스트를 하는 도중 심각한 오류를 발견하게 되었다.
바로 Rank 와 LottoRank 를 합친 곳에서 에러가 있었던것.
public enum LottoRank {
THREE(3, 5_000),
FOUR(4, 50_000),
FIVE(5, 1_500_000),
SIX(6, 2_000_000_000);
private int rankCount;
private int prize;
private int winnerCount;
LottoRank(int matchCount, int prize) {
this.matchCount = matchCount;
this.prize = prize;
}
...
}
보이는가, 나는 이때까지 enum 을 제대로 사용한거 같은데,
왜 테스트에서 누적되서 winnerCount 가 오르는지 이해가 안되었다.
static 도 아닌데 왜 오르지? 하고 생각했다.
저기서 3시간 동안 헤맸고, 결국엔 내가 enum 을 이해못하고 사용했다는걸 깨닫게 된다.
바이트코드로 enum 을 봤더니 디폴트로 static 선언이 되어있었다.
enum 에 대한 잘못을 깨닫고 간신히 피드백을 반영하고 다시 리뷰 요청을 드렸다.
또, 많은 지적을 받게 된다. 이번에는 테스트에 대한 지적이였다.
과도하게 중복되는 테스트가 있고, 이로인해 무의미해 보이는 테스트도 있다는 것.
또한 다른 방식으로 테스트를 해달라는 등의 피드백을 받았다.
그제서야 이미 가장 작은 단위에서 실행하는 테스트인데
상위에서 똑같이 테스트를 진행했던 무의미한 테스트가 보였고 수정했다.
step4, 로또(수동)
수동으로 구매가능 하다는 요구사항이 추가되었다.
[로또 4단계] 리뷰 부탁드립니다 by loop-study · Pull Request #1304 · next-step/java-lotto
안녕하세요. 박현철입니다. 피드백 반영하면서 책임 위치가 변경되었습니다 기존 로또기계에서 문자열을 split 하는 과정을 inputView 에서 처리 후 List 로 반환하게 변경되었습니다. 적절한지 확인
github.com
이전까지는 로또는 금액만 입력하면 자동으로 랜덤으로 번호가 생성되었는데
이번에는 수동으로 구매갯수를 입력해야하고, 번호도 직접 선택하는 로직이 추가되었다.
여기서 로또티켓을 만들어주는 LottoMachine 는
단순히 자동 갯수와 수동 갯수, 그리고 입력된 수동 번호들만 받아서 로또를 넘기면 되겠다고 생각했었다.
그러기 위해선 입력된 금액과 수동 갯수를 이용하여 자동 갯수와 수동 갯수를 관리하는 역할이 필요하다 생각하여 LottoQuantity를 추가했다.
로또 생성에 관한 테스트는 자동 갯수, 수동 갯수, 수동 번호들을 미리 만들어놓고 테스트를 해야하는 힘든 과정이 추가되었다.
리뷰어님은 LottoMachineTest 에 테스트를 위한 프로덕션 코드가 많다고 이런건 지양해야한다 수정을 요구하셨고,
로또도 한번에 생성하는데 자동과 수동 따로 나눠달라는 요청과, LottoMachine 에서 LottoQuantity 의 자동 개수를 가져오는 로직에
규칙 9 : 게터/세터/프로퍼티를 사용하지 않는다. 를 언급하시면서 get 을 안쓰고 만들 방법을 생각해보라 등의 피드백을 주셨다.
여기서 머리가 터지는 경험을 했다.
로또를 생성하는데 자동, 수동 갯수를 관리하는 LottoQuantity 의 게터를 사용안하면 어떻게 로또를 만들라는 거지?
생각을 거듭하다가, 게터가 아니라 질문을 던지면 되나? 하는 생각에 LottoMachine 에서 로또를 자동 발급할 때 반복되는 index 를 LottoQuantity에게 던지고 계속 만들어도 되냐고 물어보게 된다.
하지만 이것도 반환되는 boolean 도 게터가 아닌가? 라는 생각에 머릿속이 혼란으로 가득차게 된다. 결국 아무것도 손에 안잡히고 생각이 꼬이고 꼬여 터지게 된다.
결국 해당 리뷰어에게 DM 으로 무슨 뜻인지 질문했다.
결론은 단순했다. LottoQuantity 역할이 필요해보이냐고.
그제서야 입력부터 결과 출력까지의 로직을 보게되니, LottoQuantity 의 역할은 불필요하고 대체할 요소가 있었던것.
LottoQuantity 을 걷어내고 수정하자
로또는 마무리가 되었다.
후기
이번 로또에서는 역할과 책임 분배에 많은 시간이 걸렸다.
역할과 책임에 대해 많은 에러사항이 존재했었고,
결합도와 응집도에 대한 오류사항도 많았다.
리뷰어가 사소한건 바로 지적해주었지만,
잘못된 설계는 힌트로 주면서 내가 스스로 깨닫게 해주는 유도 방식에 시간이 꽤 걸렸다.
누구는 이걸 곧바로 알려주면 시간도 아끼고 더 빨리 배울 수 있는거 아니냐? 생각할 수도 있을거다.
하지만 스스로 깨닫고 수정하는 경험이 매우 값진 경험이기에 시간 낭비라 생각되지도 않는다.
이번 미션을 하면서 역할과 책임, 결합도와 응집도를 더 알게 되었다. (오브젝트도 읽었다)
이제 사다리타기와 볼링핀 미션이 남았고, 교육 종료까지 한달보다 조금 더 남았으니
최대한 배우는걸 목표로 집중해야겠다.
(현재 글 등록 시점에 미션3, 사다리타기 마지막을 진행중이다)
'교육 및 인강 > TDD, Clean Code with Java' 카테고리의 다른 글
TDD, Clean Code with Java - 미션4, 볼링(🎳) 후기 (0) | 2021.04.10 |
---|---|
TDD, Clean Code with Java - 미션3, 사다리 후기 (0) | 2021.04.06 |
TDD, Clean Code with Java - 미션1, 자동차 경주 후기 (0) | 2021.03.18 |
TDD, Clean Code with Java 시작하며.. (2) | 2021.03.18 |