## 서론 okky 커뮤니티의 구인광고에서 관련 과제를 본 적이 있다. 객체 지향 설계로 하스스톤 게임의 인터페이스를 설계해보는 것이었는데, 객체 지향의 사실과 오해 책을 보면서 생각이 나 공부 겸 프로젝트를 생성하게 되었다. 참조 목록은 아래와 같다. * 객체지향의 사실과 오해 * [Okky - 초보 개발자에게 권장하는 객체지향 모델링 공부 방법](https://okky.kr/article/358197) * [Gibhub](https://github.com/jojoldu/oop-java) * [객체지향의 사실과 오해 관련 블로그글](https://jupiny.com/2019/01/12/object-orientation-fact-and-misunderstanding/) 책에 따르면 객체에 필요한 상태가 무엇인지를 결정하고 상태에 필요한 행동을 결정하는 것이 설계에 나쁜 영향을 끼친다. 훌륭한 객체를 만들기 위해서는 행동에 초점을 맞추어야 하고, 행동은 객체가 협력에 참여하는 유일한 방법이다. 모든 객체는 섬이 아니라는 점과 일맥상통한다. 때문에 필요한 메시지가 무엇인지를 정하고 그에 따라 행동을 결정한 뒤 필요한 상태를 선택하자는 게 초기 목표였지만, 초기에 구상했던 것과는 다르게 구현 과정에서 설계가 많이 변경되었다. ## 객체지향 설계 방법 1. 도메인에 필요한 객체 정리 2. 필요한 메시지 추가 3. 메시지를 수신할 객체 선택 4. 더 이상 필요한 메시지가 없을 때까지 2~3 과정 반복 5. 객체들이 수신하는 메시지를 바탕으로 객체들의 인터페이스 구성 6. 객체들의 메소드 구현 ## 하스스톤 게임 Spec |변경 전|변경 후| |------|------| |1. 플레이어 2명이 생명력 30의 영웅을 가지고 시작한다.
2. 초기 카드덱의 카드 개수는 30개로 시작된다.
3. 첫 턴에서 각 플레이어는 카드덱에서 선공 시 3장, 후공 시 4장의 카드를 받는다.
4. 첫 턴 이후 각 플레이어는 카드를 1장씩 받는다.
5. 플레이어가 받은 카드 중 하나를 게임보드에 등록하면 카드는 보드에 놓여진다.
6. 플레이어가 받은 카드 중 하나로 영웅을 공격하면 영웅은 피해를 입는다.
7. 영웅의 생명력이 0이 되면 영웅은 파괴되고 게임은 끝난다.|1. `플레이어` 2명이 생명력 15의 `영웅`을 가지고 시작한다.
2. 초기 `카드덱`의 `카드` 개수는 10개로 시작한다.
3. 첫 턴에서 각 `플레이어`는 `카드덱`에서 선공 시 3장, 후공 시 4장의 `카드`를 받는다.
4. 각 `플레이어`는 자신의 턴에 `카드`를 1장씩 받는다.
5. `플레이어`가 받은 `카드` 중 하나를 `게임보드`에 등록하면 `카드`는 `보드`에 놓여진다.
6. `플레이어`가 받은 `카드` 중 하나로 `영웅`을 공격하면 `영웅`은 피해를 입는다.
7. `플레이어`의 `영웅`으로 상대 `영웅`을 공격하면 `영웅`은 피해를 입고, 공격한 `플레이어`의 `영웅`도 상대의 공격력 만큼 피해를 입는다.
8. `영웅`의 생명력이 0이 되면 `영웅`은 파괴되고 게임은 끝난다.| 생각해보면 `카드를 등록하라`는 메시지는 등록된 카드가 추후 어떤 행동을 취할 수 있을 때 의미 있는 행동을 한 것이 된다. 그러나 등록된 카드로 공격하고, 등록된 카드가 공격을 받는 과정이 추가되면 복잡도가 다소 증가해 추가할 Spec에서 제외시키고, 추후 구현하고 싶은 기능에 추가하였다. 현재로선 카드를 등록하기만 할 수 있어 아쉽지만, 추후에 등록한 카드의 어떠한 행위들을 추가하게 된다면 Card 객체와 Board 객체의 책임도 늘 것이라 생각한다. ## 하스스톤에 필요한 객체 정리 1. `CardDeck` 2. `Card` 3. `Player` 4. `Board` 5. `Hero` ## 필요한 메시지 - 카드 나눔 시 - 카드를 나눠줘라 - 카드를 받아라 - 카드 등록 시 - 카드를 등록해라 - 카드를 꺼내라 - 공격 시 - 공격해라 - 카드를 꺼내라 - 피해를 입어라 ## 필요한 메시지를 수신할 객체 선택 ### 카드 나눔 시 |변경 전|변경 후| |------|------| |![image](https://user-images.githubusercontent.com/62458327/116365834-9e2c2a80-a840-11eb-843d-cbed7526dc18.png)|![image](https://user-images.githubusercontent.com/62458327/116200486-5ab7ba80-a773-11eb-88c6-f9376adbd1b0.png)| ### 카드 등록 시 |변경 전|변경 후| |------|------| |![image](https://user-images.githubusercontent.com/62458327/116365884-abe1b000-a840-11eb-845b-b9fa09358ba0.png)|![image](https://user-images.githubusercontent.com/62458327/116184398-a316ae80-a75a-11eb-8970-fd77f4144412.png)| ### 공격 시 #### 카드의 공격 |변경 전|변경 후| |------|------| |![image](https://user-images.githubusercontent.com/62458327/116365930-b734db80-a840-11eb-9ee7-466abcb69b68.png)|![image](https://user-images.githubusercontent.com/62458327/116194621-0bba5700-a76c-11eb-9615-9819147e107a.png)| #### 영웅의 공격 |변경 전|변경 후| |------|------| |![image](https://user-images.githubusercontent.com/62458327/116365967-c156da00-a840-11eb-9079-e3e7299c2389.png)|![image](https://user-images.githubusercontent.com/62458327/116194641-1248ce80-a76c-11eb-9009-7c72f48975a3.png)| ## 구현 코드 * [Gihub](https://github.com/sloth-bear/hearthstone) ## 결론 글을 쓰면서도 수정할 사항들이 보이지만, 점진적으로 보완해나갈 수 있는 점이 많다고 생각하고 싶다. 구현하면서 생성자에서 CardDeck을 초기화시키는 방향이 괜찮은 것인지, 외부에서 받는 것이 옳을지부터 생성자로 List를 추가하는 부분이 있는데, 이 경우 immutable List를 Parameter로 받게 된다면 내부적으로 의도치 않은 동작이 발생할 수 있기 때문에 어떤 방식으로 처리하면 좋을지 등 구현 방법에 대한 고민도 없진 않았다. 그러나 객체 지향과 관련된 과제이니 만큼, 더 아쉬웠던 부분은 카드에 hp 속성을 먼저 추가해둔 것이 결국 카드 간 공격행위가 고려되지 않았다는 점 등 게임 Spec 상 놓쳤던 부분, 속성을 먼저 설계함으로서 설계와 맞지 않는 부분이 생겼던 부분들이 조금 더 아쉽게 느껴진다.