-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
가위바위보 게임 [STEP 1] Wan #8
base: rft_2_wannn
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요. @hsw1920 !
3번째 프로젝트까지 진행해보셨네요!👍
가위바위보와 게임 진행에 대해 많은 고민을 해보신 것 같습니다.
처음이지만 XCTest
를 잘 활용해보셨네요!
확정성에 대한 고민에 대한 제 생각도 완과 비슷한 생각입니다.🙂
SOLID 원칙의 ISP 원칙과 비슷한 내용인 것 같습니다!
이후 고민과 궁금한 부분에 대해서 코멘트를 남겨보았습니다!
확인해보고 의견 나눠보면 좋을 것 같습니다~
mutating func win() { | ||
self._winCount += 1 | ||
} | ||
mutating func lose() { | ||
self._loseCount += 1 | ||
} | ||
mutating func draw() { | ||
self._drawCount += 1 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
승/무/패 를 Int
타입으로 표현해보셨네요! Int
으로 표현하신 이유가 있을까요?
win()
, lose()
, draw()
승무패에 대한 메서드를 구현한 것도 좋지만
게임의 결과를 인자를 받는 메서드로 표현해보는 것은 어떨까요? 의견이 궁금합니다!
// Created by 홍승완 on 2024/03/20. | ||
// | ||
|
||
enum Hand: CaseIterable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CustomStringConvertible
프로토콜을 활용해봐도 좋을 것 같습니다!
var randomHand: Hand { | ||
return random() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
손패를 잘 구현해보셨네요!👍
var sut: RockPaperScissorsGame? | ||
|
||
// MARK: 보로 비겼을 때 | ||
func test_paper_draw() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사용자와 컴퓨터의 가위바위보 테스트 코드를 잘 작성해보셨네요!
여기서 더 일반화하여 가위바위보 규칙에 대한 테스트로 작성해보면 어떨까요?
가위바위보 승/무/패 에 대한 규칙을 테스트하는 코드를 작성하면,
사용자의 승패, 컴퓨터의 승패를 더 적은 테스트 코드로 가위바위보 게임 규칙(승무패)을 커버할 수 있을 것 같습니다!
print(">>>>>>>>>>>RANDOM TEST>>>>>>>>>>>>>>>>>>") | ||
print("| userHand: \(userHand)", "computerHand: \(computerHand) |") | ||
print("| user Win: \(win!) \t|\n", | ||
"| user Lose: \(lose!)\t |\n", | ||
"| user Draw:\(draw!)\t |") | ||
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어떤 용도로 사용하는 print
문 일까요? 불필요한 구문이면 제거하는 것이 어떨까요?
repeat { | ||
test_nextGame(sut: sut) | ||
} while user.score.winCount < 3 | ||
&& computer.score.winCount < 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
삼세판 규칙을 테스트 코드 안에서 구현하셨네요. 특별한 이유가 있을까요?
테스트 코드 안에서 로직을 구현하기 보다는 구현 코드에서 삼세판을 판가름할 수 있는 로직을 테스트하는 것은 어떨까요?
if userWinCount > computerWinCount { | ||
XCTAssertEqual(sut?.user.score.winCount, 3) | ||
} else { | ||
XCTAssertEqual(sut?.computer.score.winCount, 3) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reset 테스트 구문에서 승패에 대한 테스트를 추가로 작성하신 이유가 있을까요?
@zdodev
안녕하세요 소대 완 입니다!
벌써 3주차라니 아쉽습니다..
갑작스런 개인 일정때문에 지난주부터 코스에 더 많은 시간을 투자하지 못하고 있다는게 너무 아쉽습니다.. ㅠㅠ..
week2의 코멘트도 아직 적용하여 Step2를 진행하지 못하고 있지만.. 먼저 week3 PR 올리겠습니다..! (이후 꼭 혼자서 진행해보겠습니다!)
미션 요구사항에 따라
최대한 RED-GREEN-REFACTOR에 맞추어 개발을 진행하였습니다 !
하지만 TDD, Unit Test가 이번이 처음이어서 잘 작성한건지 사실 의문스럽네요 ;)
내용
개발 과정은 먼저 요구사항에 대한 테스트 코드를 작성하며 해당 비즈니스 로직을 구현하였고,
요구된 모든 기능이 구현된 뒤
기획의 변경
을 염두에 두어 리팩터링을 진행하였습니다.비즈니스 로직은 UI와 분리하였기에 UI는 Step1에서 구현하지 않았습니다.
TestCode는
의 순서로 진행하였고, 로직또한 위 순서에 따라 구현되었습니다.
이후
기획의 변경
을 저는 Game 종류가 변경될 수 있다. 라고 생각하고 진행하며 리팩터링을 진행하였습니다.고민했던 점
사실 User에 집중해야할 지, Game에 집중해야할 지 판단이 명확하게 서질 않았습니다.
일단 저는 Game은 User가 반드시 참여한다고 생각하였기에 Game이 User에 의존하도록 구현하였습니다.
설계에 대한 고민
1-1. Game은 가위,바위,보를 사용하는 게임으로 생각하여 HandGameable 프로토콜을 구현하여 이를 채택시켰습니다.
1-2. 이후 Game이 추가된다면 유저가 참여한 상태에서 HandGameable 프로토콜을 따르는 다른 Game의 구현체를 교체하는것으로 생각하였습니다!
1-3 User와 Score또한 Game관련의 최소한의 프로토콜이 존재하며 다른 Game으로 교체된다면 각 User와 Score의 다른 구현체로 교체하는 것을 생각했습니다.
2-1. User는 Game을 Play하는 사람이며 각자 자신의 Score와 Hand를 가지도록 구현하였고 이를 모두 프로토콜로 구현하였습니다.
2-2. User가 각자 자신의 Score와 Hand를 관리할 대한 책임이 있다고 생각했습니다.
확장성에 대한 고민
위 1-3에 작성한대로 각 구현체들은 Game관련 protocol을 따르게 됩니다.
지금 당장은 전혀 문제가 없어보입니다.
하지만 이후 Game이 추가된다면 결국 새로운 구현체가 생성이 될 것입니다.
최초 작성한 protocol의 요구사항이,
추후 구현될 다른 Game에서 필요치 않은 경우를 생각하게 되었습니다.
이런 경우에는 결국
둘 중 하나일 것이라고 생각하는데요.
저라면 1번을 택하고 기존 구현체에 extension으로 다른 구현체에 필요 없는 메서드, 프로퍼티를 기본구현할 것 같은데
이런 부분은 최소한의 고려만 하고 상황에 따라 그때 그때 판단하는 것이 나은지 궁금합니다.
테스트 코드에 대한 고민
테스트코드에서만 필요한 Game 인스턴스의 메서드의 경우에는 어떻게 처리해야할 지 잘 모르겠습니다
일단 HandGameable protocol에
play()
로 구현하긴 하였는데, 추후 실제 게임에서는nextGame()
으로 모두 대체가 가능해보이는 것이 고민입니다.