3.11. ADR Dragon Damage Take

  • Make 10 points damage to the dragon

  • Make 20 points damage to the dragon

  • Make 30 points damage to the dragon

  • Make 40 points damage to the dragon

  • Make 50 points damage to the dragon

3.11.1. Option 1

>>> dragon.set_damage(DMG)

Pros and Cons:

  • Good: easy to use

  • Good: clear intent

  • Good: encapsulation

  • Bad: the name indicates a setter of a damage attribute

  • Bad: not Pythonic way

  • Decision: rejected, method name indicates something else

3.11.2. Option 2

>>> dragon.set_health(DMG)

Pros and Cons:

  • Good: easy to use

  • Good: clear intent

  • Good: encapsulation

  • Bad: the name indicates a setter of a health attribute

  • Bad: not Pythonic way

  • Decision: rejected, telldontask

Problem:

>>> dmg = hero.make_damage()
>>> result = dragon.health - dmg
>>>
>>> dragon.change_health(result)

Use Case:

>>> file.change_content('hello world')
../../_images/designpatterns-telldontask-1.png

3.11.3. Option 3

>>> dragon.change_health(-10)
>>> dragon.change_health(-20)
>>> dragon.change_health(-30)
>>> dragon.change_health(-40)
>>> dragon.change_health(-50)

Pros and Cons:

  • Good: easy to use

  • Good: clear intent

  • Good: encapsulation

  • Bad: the name indicates a setter of a health attribute

  • Bad: abstraction

  • Bad: not Pythonic way

  • Decision: rejected, method name indicates something else

3.11.4. Option 4

>>> dragon.wound(DMG)       # dragon  -> enemy
>>> dragon.hurt(DMG)        # dragon <-  enemy
>>> dragon.hit(DMG)         # dragon <-> enemy
>>> dragon.damage(DMG)      # dragon  -> enemy

Pros and Cons:

  • Bad: Indication of direction is too weak dragon <-> enemy

  • Decision: rejected, indication of direction is too weak

Example:

>>> dragon.hit(10)  # bad, dragon make or take 10 damage?

Rationale:

dragon --> enemy
dragon  -> enemy
dragon <-> enemy
dragon <-  enemy
dragon <-- enemy

3.11.5. Option 5

>>> dragon.hurt_self(DMG)
>>> dragon.hurt_me(DMG)
>>> dragon.receive_damage(DMG)
>>> dragon.suffer_damage(DMG)

Pros and Cons:

  • Good: Explicit relation dragon --> enemy

  • Good: Consistent with deal_damage()

  • Bad: hurt_self() is too use-case specific

  • Bad: Inconsistent with make_damage()

  • Decision: rejected, method names are too use-case specific

Example:

>>> dragon.hurt_self(DMG)
>>> chair.hurt_self(DMG)
>>> barrel.hurt_self(DMG)
>>> dragon.receive_damage(DMG)
>>> chair.receive_damage(DMG)
>>> barrel.receive_damage(DMG)

3.11.6. Option 6

>>> dragon.take_damage(DMG)

Pros and Cons:

  • Good: Explicit relation dragon --> enemy

  • Good: Consistent with make_damage()

  • Decision: candidate

Example:

>>> dragon.take_damage(DMG)
>>> chair.take_damage(DMG)
>>> barrel.take_damage(DMG)

3.11.7. Option 7

>>> dragon.health - DMG
>>> dragon.health -= DMG

Pros and Cons:

  • Good: simple

  • Good: can use @property for validation if needed

  • Bad: requires knowledge of API

  • Bad: violates encapsulation

  • Decision: rejected, violates encapsulation

3.11.8. Option 8

>>> dragon.health - Damage(20)
>>> dragon.health -= Damage(20)

Pros and Cons:

  • Good: simple

  • Good: can use @property for validation if needed

  • Bad: requires knowledge of API

  • Bad: violates encapsulation

  • Decision: rejected, violates encapsulation

3.11.9. Option 9

>>> dragon - DMG
>>> dragon -= DMG

Pros and Cons:

  • Good: simple

  • Good: can use .__sub__() for validation if needed

  • Bad: requires knowledge of API

  • Decision: rejected, not explicit and requires knowledge of API

3.11.10. Option 10

>>> dragon - Damage(20)
>>> dragon -= Damage(20)

Pros and Cons:

  • Good: simple

  • Good: can use .__sub__() for validation if needed

  • Bad: requires knowledge of API

  • Decision: rejected, not explicit and requires knowledge of API

3.11.11. Option 11

>>> dragon < Damage(20)
>>> dragon <= Damage(20)
>>> dragon << Damage(20)

Pros and Cons:

  • Good: simple

  • Good: can use .__lt__(), .__le__() for validation if needed

  • Bad: requires knowledge of API

  • Decision: rejected, not explicit and requires knowledge of API

3.11.12. Decision

>>> dragon.take_damage(DMG)

Pros and Cons:

  • Good: provides encapsulation

  • Good: easy to use

  • Good: explicit relation dragon --> enemy

Implementation:

>>> class Dragon:
...     def take_damage(damage: int, /) -> None: ...