본문 바로가기

프로젝트 이야기/지니어스:모노레일

1편 : 설계하기

들어가며

0편에서는 간단하게 기존의 프로젝트를 소개했다면 1편부터는 본격적으로 설계-구현-평가를 해나갈것이다. 먼저 간단하게 프로젝트를 설계하고자 했다. 설계의 경우는 실제 프로그래밍을 통해 구현을 하면서 충분히 바뀔수 있는 것이므로 처음엔 간단하게 설계했고, 코딩을 진행하면서 설계를 점차 완성해나갔다. 책임 주도 설계의 원칙을 적용해 구현하였으며, 필요에 따라 디자인 패턴을 적용하였다.

책임 주도 설계 (Responsibility Driven Design)

책임 주도 설계란 책임을 어떤 객체에 배치하는가를 중심으로 설계를 하는 것이다. 어플리케이션에서 필요한 책임을 먼저 파악하고 책임을 수행하기에 적적한 객체를 찾아 배치하는 방식으로 설계를 한다.

책임

어떤 책임들이 있을까?

프로젝트의 주제는 지니어스의 나온 모노레일 게임이다. (규칙은 아래 링크 참고)

먼저 어떤 객체들이 존재할지에 대해 생각하였다.

  • 타일
  • 게임보드
  • 플레이어
  • 게임시스템

이어서 어떤 도메인이 존재하는지 생각하고 각 도메인 모델을 설계하였다.

 

도메인1 : 타일을 게임보드에 놓는다.

도메인 : 타일을 게임보드에 놓는다.

1. 타일의 타입, 위치를 설정한다. (Player)

2. 타일을 게임보드에 놓는다. (Board)

3. 타일이 규칙에 따라 올바르게 놓아졌는지 검사한다. (Checker)

 

하나의 객체가 너무 많은 책임을 가지면 좋지 않다. 그래서 OTT의 단일책임 원칙에 따라 규칙을 검사하는 객체를 추가하였다. 그에 따른 도메인 모델은 다음과 같다.

 

도메인2 : 턴을 종료한다.

도메인 : 턴을 종료한다.

1. 턴 종료한다.

2. 모든 철로가 모두 연결되엇는지 검사한다.

3. 모든철로가 연결되었을 경우, 해당 턴의 플레이어를 승자로 하고, 게임을 종료한다.

 

도메인 모델들의 공통점

각각의 도메인 모델들을 만들다 보니 다음과 같은 공통적인 모델로 추상화할 수 있었다.

  • System: 다음으로 진행할 과정을 선택및 Player에게 요청
  • Player : Play에게 게임을 요청 (타일놓기, 타일빼기, 불가능선언, 턴종료, 에러처리)
  • Checker: 현재 상태가 올바른지 검사 (선로 연결 가능여부, 모든 선로 연결 여부)
  • Board : 타일 삽입, 제거(push/pop) / 보드 화면에 전송

 

디자인패턴 적용

결국 각 기능이 같은 패턴 내에서 세부 구현만 바뀌는 방식으로 진행된다.

 

타일놓기(PutTile)이라는 메세지가 Player에게 전송되면 Play는 Board에 타일을 놓고, Checker는 모든 선로가 규칙에 맞

게 연결되어 있는지 검사한다. 그후 결과 메세지를 System에 전송하면 System은 결과를 받고 다음 행동을 결정한다.

 

에러처리(HandleError)라는 메세지가 Player에게 전송되면 Play는 Board에서 잘못 삽입된 타일을 제거하고, Checker는 모든 선로가 제대로 연결되었는지 검사한다. 그후 결과 메세지를 System에 전송하면 System은 결과를 받고 다음 행동을 결정한다.

 

턴종료(EndTurn)라는 메세지가 Player에게 전송되면 Play는 Board 프로세싱을 하지 않고 바로 Checker를 통해 모든 선로가 연결되었는지 검사한다. 그후 결과 메세지를 System에 전송하면 System은 다음 행동을 결정한다.

 

결국 Play와 Checker 두 인터페이스만이 존재하고 두 인터페이스의 구현객체가 바뀌면서 각 행동이 수행된다. 이를 근거로 Play에는 Strategy Pattern을 Checker에는 Factory Method Pattern을 적용하였다. 그리고 유일한 객체를 생성하는 Board는 Singleton을 적용하였다.

 

PlayStrategy 인터페이스의 경우 행동에 따라 구현이 천차만별이다. 예를 들어 새로운 행동이 필요할 경우, 그 행동에 따라 새로운 구현이 생기고 Player가 선택할 수 있게끔 구현해야 한다. 이 이유로 전략패턴을 적용하였다.

그에 반에 Checker의 경우 정해지 몇개의 모듈이 존재하고, 해당 모듈을 사용하거나, 사용하지 않거나로 구현이 나뉜다.

예를 들어 새로운 체커가 필요할 경우, 그 체커 자체를 사용한다기 보다, 해당 체커가 정의되고, 해당 체거가 필요한 행동만이 해당 체커를 선택해 사용한다. 이 Checker는 팩토매서드 패턴을 적용했다.

위 그림은 최종적인 도메인 모델이고, 실질적인 구현은 2편에서 다루겠다.

(아직 PutTile이랑 Checker 밖에 구현못함)