Consider a gift box for a common game.
Item name | Reason for acquisition | Deadline for receipt |
---|---|---|
Herbs x 10 | Clear reward for Dungeon 4 | 100 days left |
Magic stone | 4th day login bonus | 100 days left |
10000 gold | 6th day login bonus | 99 days left |
Herbs x 5 | Clear reward for Dungeon 3 | 99 days left |
5000 gold | This is the login bonus for the third day | 96 days left |
Warrior Kita | This is the login bonus for the first day | 93 days left |
Is the schema of this DB like this?
Items, money, etc. are distinguished by item_type. Let's assume that this is the case.
item_type | Contents |
---|---|
1 | money |
2 | item |
3 | Character |
4 | Magic stone |
What is the code when I receive this (when I move it from the present box to my hand)?
def acquire_present(user, present):
if present.item_type == 1:
"""Processing to receive money"""
elif present.item_type == 2:
"""The process of receiving an item"""
elif present.item_type == 3:
"""Processing to receive characters"""
...
else:
raise Exception()
if statement hell. Moreover, there is a high possibility of doing various things in each receiving process (hand-held confirmation, log, etc.). This will increase the tight coupling between the acquire_present function and each data class.
Furthermore, if item_type increases due to future game expansion, it will become even longer. I want to do something about long if statements and tight couplings because they are not easy to maintain.
Therefore, consider a class that delegates the process of receiving gifts.
class AqruireDalegatorBase(object):
"""Receive processing delegation base class"""
@classmethod
def acquire(user, present):
raise NotImplementedError()
You have defined a common interface for receiving. Inherit and implement each receiving processing delegation class.
class MoneyAqruireDalegator(AqruireDalegatorBase):
"""Money receipt processing delegation class"""
@classmethod
def acquire(user, present):
user.add_money(present.item_quantity)
class ItemAqruireDalegator(AqruireDalegatorBase):
"""Item receipt processing delegation class"""
@classmethod
def acquire(user, present):
user.add_item(present.item_id, present.item_quantity)
...Follow other
Let's actually incorporate it into the receiving function.
def acquire_present(user, present):
if present.type == 1:
MoneyAqruireDalegator.acquire(user, present)
elif present.type == 2:
ItemAqruireDalegator.acquire(user, present)
elif ...
By cutting out the logic to receive for each type, a feeling of loose coupling came out!
But the if statement is still long and I have to modify this function every time a type is added, so
DELEGATOR_MAP = {
1: MoneyAqruireDalegator,
2: ItemAqruireDalegator,
...
}
And type and delegation class mapping.
def acquire_present(user, present):
delegator_class = DELEGATOR.get(present.item_type)
delegator_class.acquire_present(user, present)
It's much shorter! And even if this increases the types
It is extensible with. No need to modify the acquire_present function! All you have to do is the delegation class with the added test!
Long if statements are troublesome both when investigating defects and when expanding, so if they are loosely coupled, they are kind to people now and in the future!
(Is this a facade pattern ...? It feels a bit like DI)
Recommended Posts