🏨 수업 피드백
1. cache vs pool
두 개념의 차이점은 미묘하게 다르다. 구분하자.
- cache
- 미리 만들어두기
- pool
- 만든 게 있으면 꺼내쓰기/없으면 만들어 넣어두기
고로 블랙잭에서 내가 활용한 개념은 cache이다(게임에 사용될 카드들을 미리 생성해 놓았기 때문)
2. 클래스 파일의 수
클래스 파일이 많아지면 경계하는 의견이 있다. 보통 클래스 파일이 많아지면 내부 코드를 다 확인하는 등 유지보수가 힘들어질 것이라고 생각하기 때문이다.
하지만 객체를 잘 분리하면 이런 일이 없다. 내부 코드를 확인한다는 것 자체가 그 코드가 내가 예상하는 것처럼 행동할 거라는 확신이 없어서라고도 볼 수 있기 때문이다.
따라서 메서드 명으로 역할을 정확히 드러내서 시그니처만 보고도 이해할 수 있도록 하는 것이 중요하다.
👩💻 코드 리뷰
1. 추상 클래스와 인터페이스
블랙잭 미션은 Dealer와 Player가 각각 카드를 뽑는 로직이 있다.
뽑는 기준도 다르고 딜러는 플레이어 겸 상대 선수(?) 로의 역할도 추가로 있다고 생각했다.
때문에 플레이어가 딜러를 상속받게 하여 공통의 책임은 수행하되, 추가 역할도 수행하도록 하고자 했다.
그런데, 이 관계에 대해 상속이 적절한가라는 피드백이 달렸다. 기대하는 역할이 다르기 때문이다.
따라서 플레이어와 딜러의 관계 뿐만 아니라, 어떤 경우에 상속이 더 적절하며, 어떤 경우에는 인터페이스 또는 추상 클래스를 사용하는 것이 올바른지 고민해보았다.
우선, 딜러와 플레이어의 관계를 4가지로 고민해보았다.
- 딜러가 플레이어를 상속
- 게임 안에서 딜러와 플레이어가 각각 다른 "역할"을 기대하고 있기 때문에 적절하지 않다.
- 딜러에 플레이어를 합성
- 마찬가지로 역할이 다르기 때문에 딜러가 플레이어를 가지고 있다는 게 어색한 것 같다.
- 딜러와 플레이어가 Playable 인터페이스를 구현
- 제가 생각하기에 인터페이스는 타입보다는 어떤 특징을 나타내게 할 때 좋을 것 같은데, 다른 역할이기 때문에 타입으로 정의를 하는 것이 조금 더 자연스러울 것 같다.
- 딜러와 플레이어가 Gamer 추상 클래스를 상속
- 딜러와 플레이어가 Gamer의 한 종류라고 볼 수 있고 그에 맞는 공통된 책임이 존재한다. 세부 구현은 달라도 되기 때문에 가장 적절한 것 같다.
결론으로, Gamer 추상 클래스를 통해 게임에 참여하는 모든 게이머가 가져야할 공통적인 역할을 묶고, 딜러와 플레이어가 게이머를 상속받게 하여 다른 역할에 대한 부분은 구현을 하는 식으로 진행했다.
상속과 인터페이스, 추상 클래스까지 크게 고민하지 않고 사용했던 것 같은데, 이번 기회를 통해 이러한 구현방식에 따라 기대하는 역할이나 책임이 많이 달라질 수 있다는 것을 느꼈다.
2. VO와 view
이번 미션에서 VO를 몇개 사용했었다. VO는 비즈니스 로직을 담고 있기 때문에 도메인이라고 생각하기 때문이다.
때문에 view에 값을 전달 시 원시값을 빼내어 전달했는데, 리뷰어에게 이런 피드백을 받았다.
기껏 만들어둔 값객체들을 view에서는 전혀 활용하지 못하고 있다.
처음에는 VO도 로직을 가질 수 있기 때문에 domain이다 -> domain이니 view에서 모르게 dto를 만들어줘야 한다 라고 생각해서 원시값을 제거했었다.
그런데 리뷰를 받고 곰곰히 생각해보니, 애초에 domain을 view에서 모르게 하려고 했던 이유가 domain의 내부를 감추고 싶어서였는데 VO면 값을 래핑만 했기 때문에 사실 공개된 객체이지 않은가 하는 생각이 들었다.
결과적으로 VO는 dto에서 사용해도 된다라는 기준을 세웠다.
3. 테스트코드에서만 쓰이는 메서드
TDD를 하면서, 한번씩 테스트에서만 사용되는 메서드들이 생겼다.
정말 반드시 테스트가 필요한 부분이라고 생각되면 프로덕션 코드에서 사용되지 않더라도 남겨두고, 크게 중요하지 않는 테스트라고 생각되면 테스트를 제거했다.
Deck이라는 일급 컬렉션에서 테스트에서만 사용되는 getDeck() 남겨두었는데, 그 이유가 getDeck()이 2가지를 테스트 하고 있기 때문이다.
- 배분 시에 가장 위에 카드부터 배분하는지
- 52개의 카드로 이루어져있는지
1번 같은 경우는 꼭 위의 카드가 배분되지 않더라도 프로그램 동작 자체에는 문제가 없기 때문에 반드시 테스트가 필요하지는 않지만,
2번은 하나의 덱은 사이즈가 52로 고정적이고 (요구사항이 변경돼 다른 카드집을 사용한다면 52는 아니여도 고정적일 것이라고 생각)
추가로 사이즈가 52개라는 것은 모든 shape과 score에 대해 1:1로 잘 매칭되었다 까지 예상할 수 있기 때문에 테스트가 반드시 필요한 부분이라고 생각했다.
그래서 조금의 찝찝함을 감수하더라도 getDeck()을 남겨두고 이 부분에 대해 리뷰어님에게 여쭤보았다.
결론적으로 리뷰어님은 남겨두어도 괜찮을 것 같다고 하셨다.
이런 경우에 실무에서는 어떻게 처리할지 궁금하다.
당장 나는 불필요한 프로덕트 코드를 남겨둘 것 같다. 나마저도 안전성이 더 중요하다고 생각하는데 현업은 더 그러지 않을까? 하고 넘겨짚어본다.
'우아한테크코스 6기 > 1단계' 카테고리의 다른 글
난 레벨 1 동안 어떤 경험들을 했을까? (3) | 2024.04.25 |
---|---|
[블랙잭 미션] 감정 회고 (2) | 2024.04.13 |
[블랙잭 미션] 페어프로그래밍 단계 학습 내용 정리 (0) | 2024.04.13 |
[사다리 타기 미션] 학습 내용 정리 (0) | 2024.03.26 |
[자동차 경주 미션] 학습 내용 정리 (1) | 2024.03.25 |