제가 개최한 코딩 테스트 3회에서 5번 문제였던 가희와 btd5 2는 난이도가 높았던 문제였습니다. 입력 크기와 사이즈를 보니, brute force 솔루션으로 검수진 코드와 제 코드를 교차 검증 가능했습니다. 오래 걸려 봤자 1시간 내외로 수행이 가능한 사이즈였기 때문입니다. 제가 검수했던 문제 중 하나인 시철이가 사랑한 수식 또한 비슷한 이유로 brute force 솔루션을 작성했던 적이 있었습니다.

 

 제가 깃허브에 올린 솔루션은, 당연하게도 객체 지향 같은 건 무시한 코드였는데요. brute force 솔루션 또한 객체 지향적으로 구현하지 못했습니다. 이 문제의 출제 의도 중 하나가 객체 지향 설계 능력을 보는 것이였는데 출제자가 그걸 못 했다니. 앞으로 몇 개의 글에 걸쳐서 brute force 솔루션을 제가 올린 솔루션보다는 조금 더 객체 지향적으로(?) 구현해 볼 거에요. 그 과정에서 제가 했던 고민들도 풀어볼 예정입니다.

 

 


 먼저 처음에 했던 고민은 접근 제어자에 관한 것이였습니다. 문제를 잘 읽어보면 게임 시스템이 유닛에게 공격 명령을 내린다고 했어요. 내가 직접 유닛에게 공격을 내리지 못하게 하려면 어떻게 해야 하나요? 이런 고민을 하다가, 접근 제어자 protected, default가 있다는 것을 떠오르게 되었어요.

 

 

 먼저, 패키지 구조입니다. my.testA 밑에 A와 A2가 있고, my.testB 밑에 B와 tempA 클래스가 있습니다. 다음에 testC 패키지 밑에는 tempA2 클래스가 있습니다. 이것을 그림으로 나타내면 아래와 같습니다.

 

 

 여기서 tempA는 A를 상속 받고, tempA2는 tempA를 상속 받습니다. 그러므로, 그림은 아래와 같이 그려집니다.

 

 

 이제 tempA 클래스를 보겠습니다.

 

 

 a1, a2, a3, a4가 있는데요. 각각 private, protected, 접근 제어자가 없는 default, public으로 되어 있어요.

 

 

 같은 패키지 안에 있는 class B에서는 tempA의 a2, a3, a4를 볼 수 있어요. a1은 private가 붙어 있는데요. 해당 클래스 내에서만 볼 수 있습니다. 일례로 arrayList에서 ensureCapacity 같은 친구들이 이에 속해요.

 

 

 A2는 tempA와 패키지가 달라요. 그리고, subClass도 아닙니다. 그렇기 때문에, default, protected, private로 선언된 친구들을 못 보게 됩니다. 즉, A2는 tempA의 패키지 바깥에 있었고, subclass도 아니기 때문에 a1, a2, a3을 못 보게 됩니다. 여기서 의문이 하나 듭니다. protected랑 default는 뭐가 다를까요? 

 

 

 tempA2는 tempA를 상속받습니다. my.testB에 있는 tempA에 있는 필드들 중에서 a2, a4를 불러오게 되는데요. a1은 private라 불러오지 못해요. 그리고 a3은 default로 선언되어 있었는데요. my.testB의 outside에 있었으므로 visible 하지 않아요. 반면 a2는 protected로 되어 있는데요. subclass여서 볼 수 있었던 셈입니다. 보통 field들은 특별한 경우를 제외하고는 보통 private로 선언하니 별 다른 문제가 되지는 않았습니다. 상수일 때에는 public으로 때우면 될 거고요. 이건 튜토리얼 문서에도 나와 있어서, 필드들에 대해서는 별로 고민을 하지 않았습니다.

 

 


 문제는 기능이였습니다. 유닛이 targetting을 하는 것은, 공격을 하는 것 안에 넣어버리면 되니까 private로 때워버리면 될 겁니다. 공격을 하는 기능을 game system 바깥의 패키지에서 마음대로 접근을 할 수 있게 해도 되느냐? 라는 질문에서 막혔는데요. 문제의 명세를 보면 전혀 그렇지 않음을 알 수 있어요. 게임 시스템이 작동시킨다고 되어 있어요. 그러므로, 유저가 직접 원숭이가 타겟팅 하게 만든다던지 하면 안 됩니다.

 

 

 처음 구조는 Unit 아래에 public으로 선언된 attack 메서드가 있었습니다. 이 경우, 유저 패키지에서 직접 Unit에게 attack을 내리는 상황이 발생하기 때문에 제외하였습니다. 이 부분은 default나 protected로 막아버리면 무난하게 처리할 수 있어요. private는 Unit 내에서만 쓸 수 있으니, 고려 대상은 아닌 듯 합니다. 즉, outside에서 볼 수 없게 하기 위해 default나 protected로 막습니다.

 

 문제는, 게임 시스템 내부에서 Unit에게 attack 명령을 내려야 한다는 것인데요. default로 막자니, 게임 시스템 패키지에서 접근하지 못합니다. protected로 풀자니, 어디에 Unit 관련한 것을 extend 할 지 고민이였습니다. 잘 생각해 보면, targetting 한 대상을 공격하는 것 또한 게임 내의 시스템에 포함됩니다.

 

 

 그러니 Unit 패키지에는 그냥 유닛 인터페이스와 실제 유닛 모델들만 넣어 놓습니다. 게임 시스템 내부에서 Unit에 대한 정보를 얻어온다면 타겟 우선 순위를 가지고 명령을 내리면 됩니다. 그러면 아마도, 조금 더 자연스러울 겁니다.

 

 

 이제 game.system 패키지 내부에서만 attack 명령을 떨어트릴 수 있도록, 메서드 앞에 default나 protected를 붙이면 될 듯 싶네요. 다음에 계속 이어서 해 보겠습니다.