pygame
数年前にゲームを作りました。それは機能しましたが、最適なコーディング スタイルではなく、古典的なコードの匂いがたくさんありました。私は最近それを取り戻し、今回はより規律を持ってリファクタリングしようとしています。
pygame.sprite.DirtySprite
大きなコード臭の 1 つは、以下に関連する多くのコードを継承する巨大なクラス、GameObjectを持っていたことです。
- スプライトを動かすさまざまな方法
- スプライトをアニメーション化するさまざまな方法
- スプライトを爆発させるさまざまな方法
- 等
スプライトが動作する方法について私が頭を悩ませていたほど、コードの重複が増え、変更がより困難になっていました。そこで、機能を多数の小さなクラスに分割し、オブジェクトの作成時にそれらを渡し始めました。
class GameObject(DirtySprite):
def __init__(initial_position, mover_cls, imager_cls, exploder_cls):
self.mover = mover(self, initial_position)
self.imager = imager(self)
self.exploder = exploder(self)
...
spaceship = GameObject(pos, CrazyMover, SpaceshipImager, BasicExploder)
より多くのコードをこれらのヘルパー クラスに分解するにつれて、コードは確実に改善され、柔軟性が増し、重複が少なくなりました。ただし、ヘルパー クラスの種類ごとに、パラメーターの数がどんどん長くなっていきました。スプライトの作成は雑用になり、コードは見苦しくなりました。そのため、別のリファクタリング中に、構成を行うために非常に小さなクラスの束を作成しました。
class GameObjectAbstract(MoverAbstract, ImagerAbstract, \
ExploderAbstract, DirtySprite):
def __init__(self, initial_position):
...
...
class CrazySpaceship(CrazyMover, SpaceshipImager, BasicExploder, GameObjectAbstract):
pass # Many times, all the behavior comes from super classes
...
spaceship = CrazySpaceship(pos)
私はこのアプローチの方が好きです。これは一般的なアプローチですか?すべてのロジックを小さなクラスに分割することには同じ利点があるようですが、オブジェクトの作成ははるかにクリーンです。
ただし、このアプローチはそれほど動的ではありません。たとえば、実行時に新しいマッシュアップを決定することはできません。しかし、これは私が実際に行っていたことではありませんでした。私は多くのマッシュアップを行っていますが、それらがクラス ステートメントを使用して静的に定義されていることは問題ないようです。
将来の保守性と再利用に関して、何か欠けているものはありますか? 継承よりも合成の方がいいと聞きますが、これは継承を使って合成しているような気がするので、これでいいのかなという感じです。
私が使用すべき別のパターンはありますか?