別の問題のより簡単な解決策を認めた場合、コードの匂いを嗅いでも大丈夫ですか?[閉まっている]


31

友人のグループと私は過去少しの間プロジェクトに取り組んでおり、私たちは私たちの製品に固有のシナリオを表現する素晴らしいOOP方法を発明したかったのです。基本的に、私たちは東方スタイルの 弾丸地獄ゲームに取り組んでおり、私たちが思いつく可能性のある弾丸のあらゆる行動を簡単に表現できるシステムを作りたかったのです。

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

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

したがって、この問題を解決するために、さまざまなコンポーネントによって提供されるすべての動作を基本的にbulletクラスに押し込みました。これにより、想像できるすべてが、他の関連するコンポーネントインスタンスではなく、各bulletインスタンスで直接提供されます。これにより、手続き生成アルゴリズムの操作が少し簡単になりますが、現在の弾丸クラスは巨大な神オブジェクトです。これは、他のコードの5倍以上のコードを持つ、これまでのプログラムで簡単に最大のクラスです。維持するのも少し苦痛です。

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


1
まあ...これはちょっと答えが難しいです。私の意見では 特に、他の人と一緒に作業する場合。あなたが一人で働いているなら、あなたは何でもしたいことができます。しかし、一般的にそれはあなたが誰と働くかに依存します。
皮肉ジャガイモ

13
「それが愚かで機能する場合、それは愚かではありません。」そうは言っても、それがあなたが望むように正確に機能していても、あなたがそれを修正することを決めたために、その神のクラスの将来のコーディングをほぼ不可能にしないかどうかを考慮する必要があります。
フラット

8
臭いを嗅いで、あなたが悪臭を放つことを知ってから、他の人だけが気づく匂いを嗅ぐほうがよい。:)
Reactgular

1
手続き型コードへの非OOインターフェースを提供するアダプタークラスが必要なように思えるので、コードの残りをきれいに保つことができます。
ニキエ

1
すばらしいシステムを構築し、すべてを地獄に吹き飛ばすことに決めたようです。それは本当にあなたが望むものですか?あなたの仕事を誇りに思ってください!
マスト

回答:


74

現実のプログラムを作成する場合、一方で実用的であり続けることと、他方で100%クリーンであり続けることとの間にトレードオフがしばしばあります。清潔に保つことが時間内に製品を出荷することを禁じている場合、ドアからd *** dのものを取り出すために、少しダクトテープを使用する方が良いでしょう。

あなたの説明は異なるように聞こえます-それはあなたがダクトテープを少し追加するつもりはないようです、あなたはより良い解決策のために長くて十分に見えなかったので、あなたはアーキテクチャ全体を台無しにしようとしているように聞こえます。ここでPSEで祝福を与えてくれる人を探す代わりに、別の質問をして、問題の詳細を詳しく説明し、神を避けるアイデアを誰かが提供してくれるかどうかを調べた方がよいでしょう。クラスのアプローチ。

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


6
この答えを再確認するために、私はまったく同じ2つの推奨事項で何かを書くつもりでした。最後の段落に関して、OPが記述するものは、それ自体が別のレベルの間接化が必要であることを示すコードの匂いのようです。それがより良い工場クラス、ファサード、またはAIが生成できる本格的なDSLであるかどうかは、OPに任されています。
ダニエルB

2
コードを小さなチャンクに分割するためのファサード/戦略に関する良い提案。詳細を知らなくても、何を提案すべきかを知ることは困難です。
user949300

25

興味深い質問。私は以前の経験のために少し偏見があります。

簡単な答え:学習を停止することはありません。あなたがそのような壁にぶつかったとき、それはあなたの建築/設計スキルを向上させるチャンスであり、コードの匂いを追加する言い訳ではありません。

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

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

  • 「今、この神のクラスがあります」なぜですか?
  • 「手続き生成アルゴリズムを簡素化するため」

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

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


9

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

最初のステップは分析することでした。なぜあなたのAIがパターンの複雑さに対処するのにそれほど苦労したのでしょうか。

あなたは、偶然にも、あなたのAIを神クラスのオブジェクトに変えようとしましたが、可能性のあるあらゆるプロパティのセマンティクスを完全に認識していましたか?そうした場合、そこから問題が発生します。

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

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

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

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

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


クラスの大きさや複雑さについての議論でしばしば欠けていることの1つは、「X型の参照を保持するコードでどれだけできるか」と「クラスファイルに多くのロジックを入れるべきか」の違いです。バツ"。クライアントがさまざまな機能をサポートするオブジェクトのコレクション(「fnorble」など)を持ち、コレクションのすべてのメンバーに「可能な場合はfnorble、そうでなければ何もしない」ように要求することがよくある場合このような多くの方法を組み合わせた方が、インターフェイスを分割しようとするよりもはるかに便利です。
-supercat

このようなインターフェイスがあれば、さまざまな組み合わせを個別に処理することなく、任意の機能の組み合わせでオブジェクトをカプセル化することができます。インターフェイスを分離すると、メソッドXをサポートする型のプロキシを使用してXができないオブジェクトをラップしたり、Xを使用できないオブジェクトをラップできるプロキシを使用したりできないため、多くの異なるプロキシクラスを記述する必要があります。メソッドXをサポートできるオブジェクトをラップしている場合でも、メソッドXを公開できる。
supercat

8

d明期からのすべての悪いコードには、その進化の背景にあるストーリーがあり、一歩一歩合理的に見えるようになっています。あなたも例外ではありません。コーダーはコーディングによって学習します。あなたが予見できなかったあなたの問題の側面があります。漸進的に完全に合理的であるが、全体的にアーキテクチャを間違った方向に導く決定があります。これらの決定を特定し、再検討する必要があります。

人々がそれを修正するためのアイデアを持っているかどうか、あなたのオフィスの周りに尋ねてください。私が働いたほとんどの場所で、プログラマーの約10-20%がその種のことの本当のコツを持っているので、チャンスを待っていました。それらの人々が誰であるかを把握してください。多くの場合、現在のアーキテクチャに歴史的に投資されていないのは、最も簡単に代替案を見ることができるのはあなたの新規採用です。あなたの退役軍人とそれらをペアリングすると、彼らが一緒に思いついたものに驚くかもしれません。


2

場合によっては、これは間違いなく受け入れられます。ただし、プロシージャ生成と、アタッチ/コンポーネントベースの優れた動作アーキテクチャの両方を使用する良い解決策はないと信じることは難しいと思います。すべてのビヘイビアがbulletクラスに取り込まれた場合、godオブジェクトと、きちんとしたアーキテクチャバージョンとの間に機能的な違いはありません。手続き生成アルゴリズムを使用するのを難しくしたのはなぜですか?

新しい質問(おそらくここか、またはgamedev.stackexchange.comにありますか?)で、procと組み合わせてアーキテクチャにどのような問題が発生したかを概説します。gen。、本当に面白いでしょう。あなたが新しい質問をするならば、私たちもここで知らせてください!


3
このクラスは単なる個々のソースの自動コンパイルではないが、神のクラスを持つことは受け入れ可能で望ましい状況の例を提供できますか?
Ext3h

許容範囲内で、「別の問題のより簡単な解決策を認めた場合、コードの匂いがしても大丈夫ですか?」と言及していました。一般的に、神のクラスは作曲を使用して簡単に解決できます。しかし、確かに、常に100%除去する価値がないコードの匂いがあります。最後に、作業を完了するにはいくつかのプラグマティズムが必要です:)。(これは、気まぐれにベストプラクティスを捨てるべきだと思うということではありません。ほとんどのソフトウェアハウスは、ベストプラクティスをより厳密に守る方が良いと思います)。
ロイT.

0

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.