web-dev-qa-db-ja.com

別の問題へのより簡単な解決策を認めるなら、コードのにおいをかいても大丈夫ですか?

友人のグループと私はここしばらくの間プロジェクトに取り組んでおり、私たちはニースOOP製品固有のシナリオを表す方法を発明したいと考えました。基本的には、 Touhou-stylebullet hell game に取り組んでおり、私たちが思いつく可能性のある弾丸の動作を簡単に表現できるシステムを作りたかったのです。

それがまさに私たちがしたことです。弾丸の動作をさまざまなコンポーネントに分割して、弾丸インスタンスに自由にアタッチできる、非常にエレガントなアーキテクチャを作成しました。これは nity's コンポーネントシステムのようなものです。うまく機能し、簡単に拡張でき、柔軟性があり、すべてのベースをカバーしましたが、わずかな問題がありました。

このアプリケーションには、大量の手続き型生成も含まれます。つまり、弾丸の動作を手続き型で生成します。なぜこれが問題なのですか?まあ、私たちのOOP弾丸の振る舞いを表現するためのソリューションはエレガントですが、人間なしで作業するには少し複雑です。人間は論理的で賢い問題の解決策を考えるのに十分賢いです。手続き型生成アルゴリズムはまだそれほど賢くなく、OOPアーキテクチャを最大限に活用するAIを実装するのは難しいことがわかりました。確かに、これはアーキテクチャの欠点です。すべての状況で直感的ではないこと。

したがって、この問題を解決するために、さまざまなコンポーネントによって提供されるすべての動作を箇条書きクラスに入れました。これにより、想像できるすべてのものが、他の関連するコンポーネントインスタンスではなく、各箇条書きインスタンスで直接提供されます。これにより、手続き型生成アルゴリズムの操作が少し簡単になりますが、今や弾丸クラスは巨大な god object になっています。これは、他の何よりも5倍以上多くのコードを含む、これまでのプログラムで最大のクラスです。維持するのも少し面倒です。

別の問題を扱いやすくするために、クラスの1つが神のオブジェクトに変わっても大丈夫ですか?一般に、別の問題に対するより簡単な解決策を認めている場合、コードにコードの匂いが含まれていても大丈夫ですか?

31
user3002473

実際のプログラムを構築する場合、一方では実用的であり続けることと、もう一方では100%クリーンであることにトレードオフがしばしばあります。清潔に保つことが間に合わずに製品を出荷することが禁止されている場合は、少し duct-tape を使用してd *** dをドアから出すことをお勧めします。

あなたの説明は違うように聞こえます-それはあなたが追加するつもりはないようです少しダクトテープ、それはあなたがあなたを台無しにしようとしているように聞こえますより良いソリューションを実現するのに十分な長さと難しさを備えていなかったため、アーキテクチャ全体。したがって、PSEでこれについて祝福してくれる人を探す代わりに、詳細な問題の詳細を説明する別の質問をして、誰かが神を避けているアイデアを提供しているかどうかを確認することをお勧めします。クラスのアプローチ。

多分、弾丸クラスは他の多くのクラスのファサードになるように設計できるため、弾丸クラスは小さくなります。多分、戦略パターンが役立つので、弾丸は異なる動作を異なる戦略オブジェクトに委任できます。たぶん、あなたはあなたの弾丸コンポーネントとあなたの手続きジェネレーターの間にただアダプターが必要です。しかし、正直なところ、システムの詳細を知らなければ、推測することしかできません。

74
Doc Brown

興味深い質問です。私は以前の経験のために少し偏っていますが、いいえと答えるように促します。

短い答え:私たちは決して学習を止めません。そのような壁にぶつかったとき、それはあなたの建築/デザインスキルを向上させるチャンスであり、コードの匂いを追加する口実ではありません。

長いバージョンは、現在、私の作業中のプロジェクトで何度も同様の質問をされていますが、必然的に、問題をより深く議論することになり、その後、元の質問者がそれを認めました。根本原因分析のようなメンタリティーをそれに含める必要があります。

5つの理由 が特に役立ちました。ここでの説明は、最初の理由と同じです。

  • 「私たちはこの神のクラスを今持っています」なぜ?
  • 「手続き型生成アルゴリズムを簡素化するため」

単純化されたのは正確には何ですか?そしてそれはなぜですか?その線に沿って進み続けると、通常起こることは、より根本的な問題を認識し始めることですが、同時に、より根本的な解決策も同様に可能にします。

手短に言えば、手元の問題、特にその原因についてより深く考えた後、私の経験では、元の質問は無効になり、すべての参加者にとってまったく興味がなくなりました。疑いがある場合は、それらに挑戦してください。そうすれば、それらがなくなるか、何をすべきかがわかります。心に留めておいてください。コード/デザインについてこれらの疑問を持つことは、私の意見では良い兆候です。他の人はそれを直感と呼びますが、これらの問題に挑戦するには、まずそれらを認識しなければなりません。最初の一歩を踏み出したので、おめでとうございます!さあ、うさぎの穴を下りて......

25
Frank

このような神のクラスを持つことは決して望ましいことではありません。これは、弾丸がモノリシックオブジェクトになっただけでなく、手続き型生成アルゴリズムにも同じことが当てはまるためです。

最初のステップは分析でしたが、なぜあなたのAIはあなたのパターンの複雑さに対処するのにそれほど多くの問題を抱えていたのでしょうか?

偶然にも、AIを神クラスのオブジェクトに変えようとしましたが、可能なすべてのプロパティのセマンティクスを完全に認識していましたか?もしそうなら、それが問題の原因です。

その場合、ソリューションはすべての戦略を弾丸クラス自体に統合するのではなく、AIのヒントをAIコアから戦略実装自体にオフロードすることでした。

これにより、従来の動作で副作用が発生する恐れなしに、新しい戦略でシステムを拡張するオプションを含め、当初希望した柔軟性が得られます。

代わりに、あなたは今、神オブジェクトに関連するすべての問題を抱えています:あなたの神クラス自体が理解しにくく、モノリスをデバッグするのが難しいだけでなく、そのような神クラスにアクセスする他のすべてのコンポーネントについても同じことが言えます。抽象化の欠如により、AIは今や、すべての冗長な個々のプロパティを認識しなければならないため、同様の複雑さの嫌悪に変わるはずです。

現在でも、メンテナンスで問題が発生しています。これらの問題は、そのクラスがどのように機能するかについての認知モデルをまだ持っているチームメンバーを失うとすぐに悪化します。

これまでのところ、このような神のクラスまたは神の関数を使用するすべてのプロジェクトは、例外なく、完全にゼロから書き直されたか中止されました。

9
Ext3h

黎明期以降のすべての悪いコードには、その進化の背後に、段階的に合理的に見えるストーリーがあります。あなたのものも例外ではありません。コーダーはコーディングによって学びます。あなたが予見できなかったあなたの問題の側面には、現在明白に見えるものがあります。あなたが下した決定は漸進的に完全に合理的でしたが、アーキテクチャを全体的に間違った方向に導きました。あなたはそれらの決定を識別して再検討する必要があります。

人々がそれを修正する方法について何かアイデアを持っているかどうかあなたのオフィスの周りに尋ねてください。私が働いたほとんどの場所で、プログラマの約10〜20%がその種のことについて本当の才能を持っており、ちょうどチャンスを待っています。それらの人々が誰であるかを理解してください。多くの場合、最も簡単に選択肢を確認できるのは、歴史的に現在のアーキテクチャに投資していない新入社員です。それらをあなたの退役軍人の一人とペアにすると、あなたは彼らが一緒に思いつくものに驚くかもしれません。

8
Karl Bielefeldt

場合によっては、これは間違いなく許容できます。ただし、手続き型生成と、Nice添付/コンポーネントベースの動作アーキテクチャの両方を使用する優れたソリューションがないとは思えません。すべての動作が弾丸クラスに引き込まれた場合、godオブジェクトときちんとしたアーキテクチャバージョンの間に機能的な違いはありません。手続き型生成アルゴリズムを使用するのが難しいのはなぜですか。

新しい質問(多分ここ、またはgamedev.stackexchange.com?)で、procと組み合わせたアーキテクチャで発生した問題の概要を説明します。世代は、本当に面白いでしょう。新しい質問をする場合は、こちらもお知らせください。

2
Roy T.

インスピレーションを得るために、関数型プログラミング、より正確には厳密に調整された型を確認することをお勧めします。物事が機能しないという考えは、利用可能な型システムで表現することは不可能です。たとえば、「弾丸を発射する」と「弾丸を保持する」というコンポーネントを持つ銃があるとします。それらが2つの別個のコンポーネントである場合、意味のない構成があります-弾丸を発射するが保管庫にはない銃、または弾丸を保管するが発射しない銃を持つことができます。

このレベルの複雑さで、あなたは「そうです、人間はこれが役に立たないことを理解し、不可能な組み合わせを避けます」と考えています。より良い方法は、これを完全に不可能にすることかもしれません。たとえば、「弾丸を撃つ」のコンポーネントはrequire「弾丸を保持する」コンポーネントへの参照です(または、それ自体を完全なものの一部として保持しますが、それ自体に問題があります)。

例はもっと複雑になるかもしれませんが、重要なのは、可能な組み合わせを制限し、制約を追加することです。ある意味で、手続き型の生成を正しく行うには複雑すぎる場合は、とにかく複雑すぎるでしょう。武器を設計するときに自分を制約するすべての方法について考えてください。「この銃にはすでに火炎放射器があり、手榴弾ランチャーを追加しても意味がない」と自分に言い聞かせますか?これは、ヒューリスティックスに組み込むことができるものです。各コンポーネントが存在する一定のチャンスを与えるよりも少し複雑な確率メカニズムを使用したい場合があります。お互いを除外する傾向があるコンポーネントや、一緒に機能する傾向があるコンポーネントがある場合があります。したがって、既存のコンポーネントに基づいて新しいコンポーネントを選択する確率を変更できます。

そして最後に、それが実際に十分に大きな問題であるかどうかを検討します。ゲームの面白さを台無しにしていますか?結果の銃は役に立たないか、圧倒されていますか?いくら? 10のうち1つは無意味ですか?国境地帯のようなゲーム(手続き的に生成された武器の効果を伴う)は、無意味な効果の組み合わせを無視することがよくあります。16倍のスコープを持つショットガンを持っていることの意味は何ですか?しかし、それはボーダーランドで非常に頻繁に発生します。それは、生成メカニズムの失敗と見なされるのではなく、笑いのために演奏されただけです:)

0
Luaan