RPG考える「求めるな、命じよ」の法則の具体例

http://d.hatena.ne.jp/asakichy/20090505/1241476035
オブジェクト指向プログラミング「求めるな、命じよ」の原則。

# 駄目な例
class You
	attack: (enamy) ->
		# 敵のHPを『求めて』ダメージを与えている
		enamy.hp = enamy.hp - @attackPower

# 良い例
class You
	attack: (enamy) ->
		# 敵に『命じて』ダメージを与えている
		enamy.takeDamage(@attackPower)

class BasicEnamy
	takeDamage: (damage) ->
		@hp = @hp - damage



なぜ駄目かというと、敵の種類が増えた場合に駄目な例だとこうなるから。

# 駄目な例
class You
	attack: (enamy) ->
		# 通常の敵
		if enamy instanceof BasicEnamy
			enamy.hp = enamy.hp - @attackPower
		# 強い敵
		if enamy instanceof StrongEnamy
			enamy.hp = enamy.hp - (@attackPower / 2)
		# ダメージを吸収する敵
		if enamy instanceof StrangeEnamy
			enamy.hp = enamy.hp + @attackPower

ここで、踏むと10ダメージを受ける罠を作ることになったとしよう。

class SpikeTrap
	stepOn: (enamy) ->
		# 通常の敵
		if enamy instanceof BasicEnamy
			enamy.hp = enamy.hp - 10
		# 強い敵
		if enamy instanceof StrongEnamy
			enamy.hp = enamy.hp - (10 / 2)
		# ダメージを吸収する敵
		if enamy instanceof StrangeEnamy
			enamy.hp = enamy.hp + 10

……コードから嫌な臭いがしてくる。



これが「求めるな、命じよ」に従って作られた良い例の場合、はこうなる。
敵の種類が増えても呼び出し側のコードの変更が不要で、新たなダメージ源ができたときのコードの修正も抑えられる。

class You
	attack: (enamy) ->
		enamy.takeDamage(@attackPower)

class SpikeTrap
	stepOn: (enamy) ->
		enamy.takeDamage(10)

# 通常の敵
class BasicEnamy
	takeDamage: (damage) ->
		@hp = @hp - damage

# 強い敵
class StrongEnamy
	takeDamage: (damage) ->
		@hp = @hp - (damage / 2)

# ダメージを吸収する敵
class StrangeEnamy
	takeDamage: (damage) ->
		@hp = @hp + damage