소샤게의 서버 측에서 if 문과 결합 정도를 줄일 수있는 디자인

3210 단어 파이썬디자인
※본 기사는 어디까지나 게임의 내부 설계에 관한 고찰입니다. 실제 게임과는 무관합니다.

흔한 광경



일반적인 게임의 선물 상자를 생각해보십시오.


아이템명
취득 이유
수령 기한


약초 × 10
던전 4의 클리어 보상입니다
앞으로 100일

마석
4일째 로그인 보너스입니다.
앞으로 100일

10000골드
6일째 로그인 보너스입니다.
이후 99일

약초 × 5
던전3의 클리어 보상입니다
이후 99일

5000 골드
셋째 날 로그인 보너스입니다.
이후 96일

전사 키타
첫날 로그인 보너스입니다.
이후 93일


이 DB의 스키마는 이런 느낌입니까?


item_type 에 의해 아이템이나 돈등의 구별을 합니다.
만일 이렇게 되어 있다고 합니다.


item_type
내용


1


2
아이템

3
캐릭터

4
마석


이것을 받을 때(선물 상자에서 소지로 옮길 때)의 코드는 이렇게 될까요.
def acquire_present(user, present):
  if present.item_type == 1:
    """お金を受け取る処理"""
  elif present.item_type == 2:
   """アイテムを受け取る処理"""
  elif present.item_type == 3:
    """キャラを受け取る処理"""
  ...
  else:
     raise Exception()

if 문 지옥입니다.
게다가 각각의 수취 처리로 여러가지 할 가능성대입니다(소지 확인이나 로그라든지).
그렇게 되면 acquire_present 함수와 각각의 데이터 클래스에서 확실히 결합도가 높아집니다.

또한 향후 게임의 확장으로 item_type이 늘어나면 더 길어집니다.
긴 if문과 밀접합은 유지보수성이 좋지 않기 때문에 어떻게든 하고 싶습니다.

수신 처리 분리



그래서 선물의 수취 처리를 위양하는 클래스를 생각합니다.
class AqruireDalegatorBase(object):
  """受け取り処理委譲ベースクラス"""
  @classmethod
  def acquire(user, present):
     raise NotImplementedError()

수신의 공통 인터페이스를 정의했습니다.
상속해 각각의 수취 처리 위양 클래스를 구현합니다.
class MoneyAqruireDalegator(AqruireDalegatorBase):
 """お金の受け取り処理委譲クラス"""
  @classmethod
  def acquire(user, present):
     user.add_money(present.item_quantity)

class ItemAqruireDalegator(AqruireDalegatorBase):
 """アイテムの受け取り処理委譲クラス"""
  @classmethod
  def acquire(user, present):
     user.add_item(present.item_id, present.item_quantity)

... その他に続く

실제로 수신 함수에 통합해 보겠습니다.
def acquire_present(user, present):
  if present.type == 1:
    MoneyAqruireDalegator.acquire(user, present)
  elif present.type == 2:
    ItemAqruireDalegator.acquire(user, present)
  elif ...

각각의 타입마다 받는 로직을 잘라서 소결합감이 나왔습니다!

확장도 편해지려고



하지만 아직 if문이 길어지고 타입이 추가될 때마다 이 함수를 수정해야 하기 때문에,
DELEGATOR_MAP = {
  1: MoneyAqruireDalegator,
  2: ItemAqruireDalegator,
  ...
}

와 타입과 위양 클래스의 매핑을 합니다.
def acquire_present(user, present):
  delegator_class = DELEGATOR.get(present.item_type)
  delegator_class.acquire_present(user, present)

꽤 짧아졌습니다!
그리고 이것으로 타입이 늘어난 경우에도,
  • AqruireDalegatorBase를 상속받은 수락 위양 클래스를 구현한다
  • DELEGATOR_MAP에 추가

  • 에서 확장 가능합니다. acquire_present 함수를 수정할 필요가 없습니다!
    테스트도 추가한 위양 클래스분만 하면 OK입니다!

    요약(?)



    긴 if문은 결함 조사시도 확장시도 귀찮아서 느슨하게 결합된 느낌이 되고 있으면 현재와 미래의 사람들에게 상냥하네요!

    (이것은 파사드 패턴일까・・・? 약간 DI같은 생각도 한다)

    좋은 웹페이지 즐겨찾기