10

私はボードゲームのソフトウェアバージョンをプログラミングしてきました。これまで、ゲームボード上の物理オブジェクトに対応するクラスを作成しました。私はプログラムロジックの作成に精通していますが、ロジッククラスの多くが同じオブジェクトにアクセスする必要があることがわかりました。

最初は、呼び出されたときに適切なオブジェクトをメソッドに渡していましたが、特にメソッドがタスクを実行するために多くのオブジェクトを必要とする場合、これは非常に面倒になりました。これを解決するために、必要なすべてのオブジェクトを初期化して保存するクラスを作成しました。これにより、たとえばAssets.dice()を呼び出すことで、任意のクラスからオブジェクトにアクセスできます。

しかし、私がそれについて考えた今、これは正しくないようです。これが私がここにいる理由です、私はある種の神のクラスを作成したのではないかと恐れています。この恐怖は根拠のないものですか、それとも私は災害のレシピを作成しましたか?

4

5 に答える 5

7

基本的にシングルトンパターンにぶつかりました。ほとんどの場合、それは悪いパターンです。アプリの任意の部分がほぼいつでもこのような本質的にグローバルなデータにアクセスできるようにすることで、保守、デバッグ、そして何よりもテストが難しいコードのスパゲッティの混乱に終わります。

現在のサイコロやピースなどを含む「コンテキスト」を作成し、必要に応じて、それを使用する必要のあるメソッド/クラスにコンテキストを渡す方がよいと思います。これははるかにクリーンですが、はい、どこにでも渡さなければならないのは面倒です。ただし、誰がいつコンテキストにアクセスしているかを追跡できるという利点があります。また、テスト目的でモックコンテキストを作成することもできます。コンテキストを高レベルのオブジェクトに渡し、それをそのサブコンポーネントに渡す必要がある場合、コンテキストが何であり、どこから来たのかを最初から最後まで知っています。

また、理想的には、コンテキストを不変にするのは良いことです。それは不可能かもしれません。ただし、特定のターンごとに、現在の状態をキャプチャして不変である新しいコンテキストを作成できる場合は、アプリからの驚きをさらに減らすことができます。

于 2010-04-23T15:29:59.457 に答える
2

オブジェクト指向プログラミングの一般的な哲学について質問しているようです。一般に、実際のオブジェクトをクラスにモデル化することが、コードにとって常に最適であるとは限らないことがわかります。

このことを理解するのに役立ったガイドラインの1つは、2つの擬人化クラス間の対話です(誰かがこの引用の元のソースを知っている場合は、リンクをいただければ幸いです!):

クラスAはクラスBに「xの値を教えてください」と言います。

クラスB:「なぜxの値が必要なのですか?」

クラスA:「フランジを付けることができます。」

クラスB:「私に聞いてください。フランジを付けます。」

これは、クラスがデータをカプセル化し、そのデータに対して操作を実行することを目的としているという点を理解するのに役立ちます。一般的に、これは私のコードをよりよく整理するのに役立つたとえ話です。

あなたが見たいと思うかもしれないもう一つのことは、いくつかの一般的なオブジェクト指向のデザインパターンです。ゲームのサイコロのようなものは、複数のインスタンスを必要としないため、シングルトンとしてより理にかなっている可能性があります。

デザインパターンの良い紹介が必要な場合は、優れたヘッドファーストデザインパターンの本を手に入れることをお勧めします。

于 2010-04-23T15:31:46.897 に答える
0

それは本当に「神」クラスなのか、それとも単に「コンテキスト」であり、1つのゲームの相互に関連するすべてのオブジェクトインスタンスの「コンテナ」であり、その後、さまざまなメソッド呼び出しに渡されます(つまり、引数は1つだけです)。後者はかなり一般的で、何も問題はありませんが、この場合、コンテナー自体には実際の機能はありません。

于 2010-04-23T15:31:22.320 に答える
0

この質問を持ってきてくれてありがとう。私はしばらくの間同じ問題について疑問に思っていました。メソッド間でオブジェクトを渡し、パラメーターを制限しておくには、これらすべてのオブジェクトを保持できるクラスを作成する必要があります。

それでも、複数のレイヤーを通過するDomainクラスが必要なので、設計は悪くないと思います。このドメインクラスに必要なオブジェクトがなく、ロジックを実行していない場合は、問題ありません。

于 2010-04-23T15:31:33.823 に答える
0

すべてにアクセスできるこの種のコンテキストクラスを持つことは、グローバル変数を持つことと非常に似ています。同じ欠点が当てはまります。グローバル変数は、任意の方法で読み取ったり変更したりできます。これにより、グローバル変数を使用するすべてのものが相互に結合されます。物事が結合されるとき、一方のオブジェクトの変更がもう一方のオブジェクトに何かを引き起こす可能性があるため、結合は悪いです。結合度が高くなると、複雑さを管理するのが非常に難しくなります(私たちのプレーヤークラスで蝶が羽ばたくと、サイコロクラスで例外が発生する可能性があります)。変更と追加の開発はより困難になります。バグを検出して不明瞭にすることは避けられなくなります。

したがって、たとえば、ある日、アプリケーションをテストしているときに、サイコロオブジェクトが奇妙に動作していることに気付く場合があります。dice.roll()を呼び出すと、1が返されることがあります。ただし、この場合、プレーヤーが2つをロールしているため、これは不可能です。デバッグすると、ある時点でnumberOfDiceプロパティが1に変更されたことがわかります。あなたのようなコンテキストメソッドでは、誰もがあなたのコンテキストオブジェクトを介してサイコロにアクセスできるため、numberOfDiceを1に変更した人を見つけるのは簡単ではありません。ポイントはわかりますか?

それで、解決策は何ですか?私がオブジェクト指向プログラミングで好きな比喩の1つは、分割統治法です。相互に分離できる動作、プロセス、オブジェクトを見つける必要があります。問題を管理しやすい部分に分割して、アプリケーションで行われている残りの部分から分離できるようにする必要があります。

これを行う方法を学ぶことはもちろん簡単ではなく、多くの勉強、読書、思考、議論、そしてもちろんコーディングが必要です。

于 2010-04-23T22:05:51.607 に答える