chatgpt가 템플릿 매서드 패턴을 쓰라고 한 건에 대하여

PenguinGod·2023년 1월 26일
0
post-custom-banner

게임 튜토리얼을 만들다가 이전에 작성한 코드를 수정해야 하는 일이 있었습니다.

if (PhotonNetwork.OfflineMode) // 오프라인 모드 전용
    OnEvent?.Invoke();
PhotonNetwork.RaiseEvent(_eventId, null, 
	new RaiseEventOptions() { Receivers = receiverGroup }, SendOptions.SendReliable);

추가로 작성한건 초반에 if문입니다. 튜토리얼 로직을 실제 코드에 넣는게 유쾌하지는 않지만 기존 코드에 영향을 주는 부분이 이게 유일했기 때문에 이 정도는 괜찮다고 판단했습니다.

문제는 그게 아니었습니다. 저 if문을 4군데에 복붙해야 하는게 진짜 문제였습니다.

저 매서드가 있는 클래스는 RPCAtion이라는 함수로 Action을 매핑해서 event를 멀티로 뿌려주는 역할을 합니다. 근데 Action은 제네릭 타입을 17개까지 넣을 수 있고 저는 3개의 타입이 필요했습니다. 그래서 RPCAction, RPCAction, RPCAction<T1, T2>, RPCAction<T1, T2, T3>이렇게 총 4개의 class가 있었습니다.

그러면 4개의 class에 공통된 부분을 함수로 만들어서 상속을 받으면 되지 않느냐? 라고 할 수 있지만 문제는 class의 인터페이스가 모두 다르다는 겁니다.

RPCAtion class...
public void RaiseEvent(value)
  
RPCAtion<T> class...
public void RaiseEvent(T value)

RPCAtion<T1, T2> class...
public void RaiseEvent(T value, T2 value2)
  
RPCAction<T1, T2, T3> class...
public void RaiseEvent(T value, T2 value, T3 value3)

이런 식으로 함수의 시그니처가 다르고 저 값들을 사용해야 하다보니 이 코드를 작성할 당시에 저는 별다른 방법이 없고 일단 쓰자고 판단을 했습니다. 그리고 거의 반년 동안 이 코드를 볼 일이 없었는데 오랜만에 통수를 맞았죠.

허나 반년이 지났다고 해서 갑자기 완벽한 해결책이 떠오를 일은 없었습니다. 하지만 대신 이 세상에는 chatgpt가 탄생했죠. "혹시 얘라면?" 라는 생각으로 코드를 복붙해서 중복을 줄일 수 있겠냐고 물어봤습니다.


그랬더니 답변이 왔죠.

중요한 건 2번째 문단의 첫 번째 줄입니다. 템플릿 매서드 패턴을 쓰라고 나와있죠. 애초에 함수 시그니처가 다른데 어떻게 쓰라는 것인지 코드를 보여달라고 하니 이러한 답변이 왔습니다.

abstract RPCActionBase class...
// 템플릿 매서드
protected void RaiseEvent(params object[] values)
{
	if (PhotonNetwork.IsMasterClient) // 마스터면 실행, 아니면 전달
        RecevieEvent(values);
    else
		RaiseEvent(values, ReceiverGroup.Others);
}
  
void RaiseEvent(object[] values, ReceiverGroup receiverGroup)
{
	if (PhotonNetwork.OfflineMode) // 오프라인 모드 전용
		RecevieEvent(values);
	PhotonNetwork.RaiseEvent(_eventId, values, 
  		new RaiseEventOptions() { Receivers = receiverGroup }, SendOptions.SendReliable);
}

protected abstract void RecevieEvent(object[] values);
  
  
RPCAtion<T> class...
public void RaiseEvent(T1 value) => base.RaiseEvent(value);

RPCAtion<T1, T2> class...
public void RaiseEvent(T1 value1, T2 value2) => base.RaiseEvent(value1, value2);
  
RPCAction<T1, T2, T3> class...
public void RaiseEvent(T1 value1, T2 value2, T3 value3) => base.RaiseEvent(value1, value2, value3);

RPCAction들은 RPCActionBase을 상속받아 RecevieEvent()를 구현합니다. 일반적인 템플릿 메서드 패턴이라면 이걸로 끝나겠지만 클래스 간의 인터페이스가 다르기 때문에 이를 object[]로 일치시켜 줍니다. 이러면 오버라이드된 RaiseEvent() 함수 2개의 중복이 제거되게 됩니다. 실제로 210줄이었던 코드가 130줄로 줄어들게 되었고 이해하기도 훨씬 편해졌습니다.

저는 함수 시그니처가 다르다는 이유로 벽에 막혀 있었는데 chatgpt는 바로 우회 방법을 설명해주더군요. chatgpt를 사용한지 별로 되지는 않았는데 디자인 패턴을 추천해 준 부분도 그렇고 코드 분석력과 예시를 작성해주는 능력이 정말 뛰어난 것 같습니다.

물론 처음에 200줄 넘는 코드를 읽으라고 하니까 맛이 가기도 하고, 코드를 작성하다가 자꾸 끊기는 건 살짝 답답하기는 했지만 그래도 이러한 아이디어를 준다는 사실 자체가 너무나 좋네요.

profile
수강신청 망친 새내기 개발자
post-custom-banner

0개의 댓글