SOLID原則の一部またはすべてがコードをきれいにするのに相反するOOPのフレーバーはありますか?


26

私は最近、ビデオゲーム開発におけるOOPについて友人と議論しました。

友人の驚いたことに、多くの小さなクラスといくつかの抽象化レイヤーを含むゲームのアーキテクチャを説明していました。これは、すべてに単一の責任を与え、コンポーネント間の結合を緩めることに集中した結果だと主張しました。

彼の懸念は、多数のクラスがメンテナンスの悪夢につながることでした。私の見解では、それはまったく逆の効果をもたらすだろうということでした。何世紀にもわたって思われたものについてこれについて議論を続け、最終的には同意しないことに同意し、SOLID原則と適切なOOPが実際にうまく混合されない場合があったと考えています。

SOLID原則に関するWikipediaのエントリでさえ、それらは保守可能なコードの作成を支援するガイドラインであり、アジャイルおよび適応プログラミングの全体的な戦略の一部であると述べています。

だから、私の質問は:

OOPで、SOLID原則の一部またはすべてがコードのクリーン化に役立たない場合はありますか?

Liskov Substitution Principleが安全な継承の別のフレーバーと競合する可能性があることはすぐに想像できます。つまり、誰かが継承を通じて実装された別の有用なパターンを考案した場合、LSPがそれと直接競合する可能性が非常に高いです。

他にありますか?おそらく、特定のタイプのプロジェクトまたは特定のターゲットプラットフォームは、より少ないソリッドアプローチでより適切に機能しますか?

編集:

私は自分のコードを改善する方法を尋ねていないことを指定したいだけです;)私がこの質問でプロジェクトに言及した唯一の理由は、少しコンテキストを与えることでした。私の質問は、一般的に OOPと設計原則についてです。

あなたは私のプロジェクトについて興味している場合は、参照これを

編集2:

この質問には、次の3つの方法のいずれかで答えると思いました。

  1. はい、SOLIDと部分的に競合するOOP設計原則が存在します
  2. はい、SOLIDと完全に競合するOOP設計原則が存在します
  3. いいえ、SOLIDはミツバチのひざであり、OOPは永遠に優れています。しかし、すべてと同様に、万能薬ではありません。責任を持って飲んでください。

オプション1と2は、長くて興味深い回答を生成する可能性があります。一方、オプション3は、短くて面白くないが、全体的に安心できる答えです。

オプション3に収束しているようです。


「クリーンコード」をどのように定義していますか?
GrandmasterB 14

この質問の範囲内のクリーンコードは、OOPの目標と選択された一連の設計原則を満たす方法でのコード構造です。ですから、OOP + SOLIDによって設定された目標に関して、クリーンコードに精通しています。OOPで動作するが、SOLIDと完全または部分的に互換性のない設計原則の別のセットがあるかどうか疑問に思っています。
メタファイト14

1
私はあなたのゲームのパフォーマンスについて他の何よりもずっと心配しています。テキストベースのゲームについて話していない限り。
陶酔14

1
このゲームは本質的に実験です。私はさまざまな開発アプローチを試しています。また、ゲームを書くときにエンタープライズYコードが機能するかどうかを確認しようとしています。パフォーマンスが問題になることを期待していますが、まだそうではありません。もしそうなれば、次に実験するのは、コードをパフォーマンスコードに適合させる方法です。たくさんの学習!
メタファイト14

1
ダウンボートのリスクがあるので、「なぜ」という質問に戻りたいと思います。ゲーム開発における OOP です。ゲーム開発の性質上、「従来の」OOPは、エンティティ/コンポーネントシステムのさまざまなフレーバーを好む傾向から脱落しているようです。たとえば、ここでは興味深いバリエーションです。これはむしろ、質問が「SOLID + OOP」ではなく、「OOP + Game Development」であるべきだと思うようにします。ゲーム開発者のオブジェクトインタラクションのグラフを見ると。N層アプリケーションと言うと、違いは新しいパラダイムが良いことを意味するかもしれません。
Jトラナ14

回答:


20

OOPで、SOLID原則の一部またはすべてがコードのクリーン化に役立たない場合はありますか?

一般的に、いいえ。歴史から、SOLIDの原則はすべて、デカップリングの増加に大きく貢献していることがわかりました。これにより、コードの柔軟性が向上し、変更に対応し、コードを推論、テスト、再利用しやすくすることができます。 。要するに、あなたのコードをきれいにしてください。

現在、SOLIDの原則が、DRY(繰り返さないでください)、KISS(単純な愚かさを保つ)、またはその他の優れたオブジェクト指向設計の原則と衝突する場合があります。そしてもちろん、要件の現実、人間の制限、プログラミング言語の制限、その他の障害と衝突する可能性があります。

要するに、SOLIDの原則は常にコードをきれいにするのに役立ちますが、いくつかのシナリオでは、競合する代替案よりも役に立たないでしょう。彼らは常に良いですが、時には他のものがより良いです。


14
私は好きですが、时々他のものがより良いです。「動物農場」の雰囲気があります。;)
FrustratedWithFormsDesigner 14

12
+1 SOLIDの原則を見たとき、5つの「良い」がわかりました。しかし、それらのいずれも、DRY、KISS、および「あなたの意図を明確にしない」に勝っていません。ソリッドを使用しますが、注意と懐疑を示します。
user949300 14

同意する。従うべき正しい原則は明らかに状況に依存すると思いますが、常に他のすべてよりも優先される厳しいパフォーマンス要件を除いて(これは特にゲーム開発で重要です)、DRYとKISSは通常どちらもより重要だと思う傾向がありますソリッドより。もちろん、コードをよりきれいにすればするほど、コードはより良くなるので、競合することなくすべての原則に従うことができれば、より良い結果になります。
ベン・リー

統合の分離と集約の効率的な設計についてはどうですか?基本的な「シーケンス」インターフェース(IEnumerable CountなどasImmutable)におよびのようなメソッドとgetAbilities[そのようなものCountが「効率的」であるかどうかを示す戻り値)のようなプロパティが含まれる場合、複数のシーケンスを取得してそれらを集約する静的メソッドを使用できます'単一の長いシーケンスとして動作します。そのような能力は、彼らが唯一のチェーンの実装をデフォルトにしても、基本的なシーケンスタイプに存在している場合、その集合体は...それらの能力を公開することができます
supercat

...そして、そうすることができる基本クラスで使用されるとき、それらを効率的に実装します。カウントを知っている1,000万のアイテムリストと、アイテムを順番に取得できるだけの5つのアイテムリストを集約する場合、10,000,003番目のエントリのリクエストは、最初のリストからカウントを読み取り、2番目から3つのアイテムを読み取る必要があります。キッチンシンクインターフェイスはISPに違反する可能性がありますが、一部の構成/集約シナリオのパフォーマンスを大幅に改善できます。
supercat

13

私は金融とゲームの両方で働いてきたという点で、私は異常な視点を持っていると思います。

私がゲームで会ったプログラマーの多くは、ソフトウェアエンジニアリングでひどいものでしたが、SOLIDのようなプラクティスは必要ありませんでした。伝統的に、彼らはゲームを箱に入れました-それで終わりです。

金融では、開発者はゲームで行うパフォーマンスを必要としないため、本当にずさんで無規律なことがあります。

上記のステートメントは両方とももちろん一般化されすぎていますが、実際には、どちらの場合もクリーンなコードが重要です。最適化には、明確でわかりやすいコードが不可欠です。保守性のために、同じものが必要です。

それは、SOLIDに批判がないわけではないということではありません。それらは原則と呼ばれていますが、ガイドラインのように従うことになっていますか?それで、いつそれらに従うべきですか?いつルールを破るべきですか?

おそらく2つのコードを見て、どちらがSOLIDに最も適合するかを言うことができます。しかし、単独では、コードをSOLIDに変換する客観的な方法はありません。開発者の解釈に間違いありません。

「多数のクラスがメンテナンスの悪夢につながる可能性がある」と言うのは、非馬鹿です。ただし、SRPが正しく解釈されない場合、この問題が簡単に発生する可能性があります。

私は、ほとんど責任のない多くのレイヤーを持つコードを見てきました。あるクラスから別のクラスに状態を渡すこと以外に何もしないクラス。間接参照の層が多すぎるという古典的な問題。

悪用された場合のSRPは、コードの結束性の欠如に終わる可能性があります。機能を追加しようとするときにこれを伝えることができます。常に複数の場所を同時に変更する必要がある場合、コードにはまとまりがありません。

Open-Closedには批評家がいないわけではありません。たとえば、Jon SkeetのOpen Closed Principlesに関するレビューを参照してください。ここでは彼の議論を再現しません。

LSPについてのあなたの議論はかなり仮説的なようであり、安全な継承の別の形態があなたの意味を本当に理解していませんか?

ISPはSRPをいくらか複製しているようです。インターフェースのすべてのクライアントが何をするか予測できないので、それらは同じように解釈されなければなりません。今日のまとまりのあるインターフェイスは、明日のISP違反者です。唯一の非論理的な結論は、インターフェイスごとに1つのメンバーしか持たないことです。

DIPは使用できないコードにつながる可能性があります。DIPの名前で大量のパラメーターを持つクラスを見てきました。これらのクラスは通常、コンポジットパーツを「更新」していましたが、テスト可能性の名前は、新しいキーワードを二度と使用してはならないことです。

SOLIDだけでは、きれいなコードを書くのに十分ではありません。Robert C. Martinの本「Clean Code:A Handbook of Agile Software Craftsmanship」を見たことがあります。最大の問題は、この本を読みやすく、ルールとして解釈しやすいことです。もしそうするなら、あなたはポイントを逃しています。匂い、ヒューリスティック、および原理の大規模なリストが含まれています-SOLIDの5つだけではありません。これらの「原則」はすべて、ガイドラインではなく原則です。ボブおじさんは、彼ら自身をコンセプトの「キュービックホール」として説明します。彼らはバランスのとれた行為です。盲目的にガイドラインに従うと、問題が発生します。


1
コンストラクターパラメーターが多数ある場合は、SRPに違反していることを示しています。それでも、DIコンテナーは、とにかく多数のコンストラクターパラメーターに関連する苦痛を取り除きます。そのため、DIPに関する声明には同意しません。
スティーブン

これらの「原則」はすべて、ガイドラインではなく原則です。彼らはバランスのとれた行為です。SRPに続く私の投稿でも述べたように、極端な問題自体が問題になる可能性があります。
デイブヒリアー

良い答え、+ 1。私が付け加えたいことが一つあります。私は、スキートのレビューを、OCPの背後にある中核的なアイデアではなく、OCPの標準的な教科書の定義に対する批判者として読みました。私の理解では、保護されたバリエーションのアイデアは、OCPがそもそも本来あるべきものでした。
Doc Brown

5

私の意見は次のとおりです。

SOLIDの原則は、非冗長で柔軟なコードベースを目指していますが、クラスとレイヤーが多すぎる場合、これは可読性と保守のトレードオフになる可能性があります。

特に抽象化の数についてです。少数の抽象化に基づいている場合、多数のクラスで問題ありません。プロジェクトのサイズと詳細がわからないため、わかりにくいですが、多数のクラスに加えていくつかのレイヤーに言及するのは少し心配です。

SOLIDの原則はOOPに異議を唱えるものではないと思いますが、それらに準拠したクリーンでないコードを記述することはまだ可能です。


3
+1定義により、ほとんどの場合、柔軟性の高いシステムは柔軟性の低いシステムよりも保守性が低くなければなりません。柔軟性は複雑さを増すため、コストがかかります。
アンディ14

@アンディは必ずしもそうではありません。私の現在の仕事では、コードの最悪の部分の多くは乱雑です。なぜなら、「単純なことをして、一緒にハックして、動作させて、それほど複雑にならないようにする」ことによって単に投げ込まれているからです。その結果、システムの多くの部分は100%剛性です。それらの大部分を書き換えずに、それらをまったく変更することはできません。維持するのは本当に難しいです。保守性は、システムの柔軟性に起因するものではなく、高い凝集性と低い結合に起因します。
サラ

3

開発初期の頃、私はC ++でローグライクを書き始めました。私は教育から学んだ優れたオブジェクト指向の方法論を適用したかったので、すぐにゲームアイテムがC ++オブジェクトであると考えました。PotionSwordsFoodAxeJavelinsなど、すべての基本的なコア由来Itemのもののようなもの、名前、アイコン、重量を扱う、コード。

次に、バッグロジックをコーディングし、問題に直面しました。Itemsバッグに入れることはできますが、1つ選んだ場合、それがa Potionかa Swordかをどのように知ることができますか?アイテムをダウンキャストする方法をインターネットで調べました。実行時情報を有効にするためにコンパイラオプションをハッキングして、抽象化されたItem真の型が何であるかを知り、許可する操作を知るために型のロジックを切り替え始めました(例:飲酒Swordsを避けPotionsて足に乗る)

それは本質的に、半分コピーコピーされた泥の大きなボールにコードを向けました。プロジェクトが進むにつれて、私は設計の失敗とは何かを理解し始めました。起こったことは、クラスを使用して値を表現しようとしたことです。私のクラス階層は意味のある抽象化ではありませんでした。私がやるべきことは行っているItemような関数のセットを実装Equip ()Apply ()およびThrow ()、および値に基づいて各動作させることができ。列挙型を使用して装備スロットを表します。列挙を使用してさまざまな武器の種類を表します。私のサブクラスにはこれらの最終値を入力する以外の目的がないため、より多くの値を使用し、より少ないクラスを使用します。

あなたは抽象化レイヤーの下でオブジェクトの乗算に直面しているので、私の洞察はここで価値があると思います。オブジェクト型が多すぎるように見える場合は、型とすべき値を混同している可能性があります。


2
問題は、タイプと値のクラスを混同することでした(注:クラスのOOP / C ++の概念を参照するために、ワードクラスを使用していません。)デカルト平面(長方形座標、極座標)が、それらはすべて同じタイプの一部です。ただし、主流のOOP言語は、値の自然な分類をサポートしていません。それに最も近いのはC / C ++の結合ですが、そこに何を入れるかを知るためだけに追加のフィールドを追加する必要があります。
ドーバル14

4
あなたの経験は反例として使用できます。SOLIDもモデリング手法も使用しないことで、保守不能で拡張不可能なコードを作成しました。
陶酔14

1
@Euphoric頑張った。オブジェクト指向の方法論がありました。方法論を持つこととそれをうまく実装することには違いがありますが、:)
アーサーハヴリチェク14

2
これは、OOPのクリーンコードに反して実行されるSOLID原則の例ですか?誤った設計の例のように思われます-これはOOPに直交しています!
アンドレス

1
基本ITEMクラスには、すべてがデフォルトでFALSEになっている多数の「canXXXX」ブールメソッドが必要でした。次に、Javelinクラスで「canThrow()」をtrueに設定し、PostionクラスでcanEat()をtrueに設定します。
ジェームズアンダーソン14

3

彼の懸念は、多数のクラスがメンテナンスの悪夢につながることでした。私の見解では、それはまったく逆の効果をもたらすだろうということでした。

私は絶対にあなたの友人の側にいますが、それは私たちの領域と私たちが取り組む問題やデザインの種類、特に将来どのような種類のものが変更を必要とする可能性が高いのかという問題かもしれません。さまざまな問題、さまざまな解決策。私は正しいか間違っているとは信じていません。プログラマーが特定の設計問題を最善に解決するための最善の方法を見つけようとしているだけです。私はゲームエンジンとあまり違いのないVFXで働いています。

しかし、少なくともSOLID準拠のアーキテクチャ(COMベースである)と呼ばれるもので苦労した私にとっての問題は、「クラスが多すぎる」または「機能が多すぎる」に大まかに要約されるかもしれません。あなたの友人が説明するかもしれません。具体的に言うと、「相互作用が多すぎる、誤動作する可能性がある場所が多すぎる、副作用を引き起こす可能性がある場所が多すぎる、変更が必要な場所が多すぎる、考えていることを実行できない場所が多すぎる」

いくつかのサブタイプのボートによって実装されたいくつかの抽象(および純粋な)インターフェイスがありました(ECSの利点について説明するコンテキストでこの図を作成し、左下のコメントを無視します)。

ここに画像の説明を入力してください

モーションインターフェイスまたはシーンノードインターフェイスは、ライト、カメラ、メッシュ、物理ソルバー、シェーダー、テクスチャ、ボーン、プリミティブシェイプ、カーブなど、何百ものサブタイプによって実装される可能性があります(多くの場合、それぞれに複数のタイプがありました)。そして究極の問題は、実際、これらの設計がそれほど安定していないことでした。要件が変わり、インターフェイス自体も変更する必要がありました。200のサブタイプで実装された抽象インターフェイスを変更する場合、それは非常にコストのかかる変更です。その間、抽象ベースクラスを使用することで、そのような設計変更のコストを削減することで、それを緩和し始めましたが、それでも依然として高価でした。

そこで、代わりに、ゲーム業界でかなり一般的に使用されているエンティティコンポーネントシステムアーキテクチャの調査を開始しました。これにより、すべてが次のように変更されました。

ここに画像の説明を入力してください

そしてすごい!それは保守性の点でそのような違いでした。依存関係は抽象化ではなく、データ(コンポーネント)に向かって流れていました。そして、少なくとも私の場合は、要件が変化しても、データははるかに安定しており、設計の観点から適切に取得するのが簡単でした(ただし、同じデータでできることは要件の変化に伴い常に変化しています)。

また、ECSのエンティティは継承ではなく構成を使用するため、実際に機能を含める必要はありません。それらは単なる「コンポーネントのコンテナ」です。これにより、モーションインターフェースを実装した200のサブタイプは、モーションコンポーネント(モーションに関連付けられたデータにすぎない)を格納する200のエンティティインスタンス(個別のコードを持つ個別のタイプではない)になります。A は、別個のクラス/サブタイプではなくなりました。クラスではありません。これは、空間内の場所(モーション)とポイントライトの特定のプロパティに関連するいくつかのコンポーネント(データ)を組み合わせたエンティティのインスタンスです。それらに関連付けられている唯一の機能は、システム内にあります。PointLightRenderSystem、シーン内のライトコンポーネントを探して、シーンのレンダリング方法を決定します。

ECSアプローチの下で要件が変更されると、多くの場合、そのデータで動作する1つまたは2つのシステムを変更するか、側に新しいシステムを導入するか、新しいデータが必要な場合は新しいコンポーネントを導入するだけで済みました。

したがって、少なくとも私のドメインでは、すべての人ではないことはほぼ確実です。依存関係が安定性(まったく頻繁に変更する必要のないもの)に向かって流れていたため、これは非常に簡単になりました。COMアーキテクチャーでは、依存関係が抽象化に向かって一様に流れていたときはそうではありませんでした。私の場合、モーションに必要なすべてのことよりも、前もってモーションに必要なデータを把握する方がはるかに簡単です。これは、新しい要件が入ってきて数か月または数年かけて少し変更されることがよくあります。

ここに画像の説明を入力してください

OOPで、SOLID原則の一部またはすべてがコードのクリーン化に役立たない場合はありますか?

まあ、きれいなコードはきれいなコードをSOLIDと同一視する人もいるので言えませんが、ECSのように機能からデータを分離し、抽象化からデータに依存関係をリダイレクトすることで間違いなく物事がはるかに簡単になる場合がありますデータが抽象化よりもはるかに安定している場合は、明らかな結合理由のために変更します。もちろん、データへの依存関係によって不変式を維持することは困難になりますが、ECSは、特定のタイプのコンポーネントにアクセスするシステムの数を最小限に抑えるシステム組織で不変式を最小限に抑える傾向があります。

DIPが示唆するように、依存関係が抽象化に向かって流れるとは限りません。依存関係は、将来の変更が必要になる可能性が非常に低いものに向かって流れる必要があります。それはすべての場合において抽象化であるかもしれないし、そうでないかもしれない(それは確かに私のものではなかった)。

  1. はい、SOLIDと部分的に競合するOOP設計原則が存在します
  2. はい、SOLIDと完全に矛盾するOOP設計原則が存在します。

ECSが本当にOOPのフレーバーかどうかはわかりません。一部の人々はそれをそのように定義していますが、私は本質的に、カップリング特性と、機能(システム)からのデータ(コンポーネント)の分離とデータのカプセル化の欠如と非常に異なっていると思います。OOPの形式と見なされる場合、SOLID(少なくともSRP、オープン/クローズ、liskov置換、およびDIPの最も厳密なアイデア)と非常に矛盾していると思います。しかし、これは、少なくとも人々が一般にそれらをより認識可能なOOPコンテキストで解釈するので、SOLIDの最も基本的な側面がそれほど適切ではない1つのケースとドメインの合理的な例であることを願っています。

小さなクラス

友人の驚いたことに、多くの小さなクラスといくつかの抽象化レイヤーを含むゲームのアーキテクチャを説明していました。これは、すべてに単一の責任を与え、コンポーネント間の結合を緩めることに集中した結果だと主張しました。

ECSは私の意見に挑戦し、大きく変えました。あなたのように、私は保守性の考えが可能なものに対して最も単純な実装を持っていると考えていました。これは多くのことを意味し、さらに多くの相互依存的なものを意味します(相互依存関係が抽象化の間であっても)。1つのクラスまたは関数のみにズームインして、最も単純で単純な実装を確認したい場合に最も意味があります。1つも表示されない場合は、リファクタリングし、さらに分解することもできます。しかし、結果として外の世界で起こっていることを見逃すのは簡単です。なぜなら、比較的複雑なものを2つ以上のものに分割するときはいつでも、それらの2つ以上のものは不可避的に相互作用する必要があるからです*(以下を参照)方法、または外部の何かがそれらすべてと対話する必要があります。

最近では、何かの単純さと、存在するものの数と、必要な相互作用の量との間にバランスのとれた行為があることがわかりました。ECSのシステムは、PhysicsSystemRenderSystemなどのデータを操作するための非自明な実装ではかなり重い傾向がありGuiLayoutSystemます。ただし、複雑な製品に必要なものはごくわずかであるという事実により、コードベース全体の全体的な動作を簡単に後戻りしたり推論したりする傾向があります。そこに何かがありますが、それは、より少ないかさばるクラス(依然としてほぼ間違いなく単一の責任を実行しています)の側に寄りかかることは悪い考えではないかもしれないことを示唆するかもしれませんシステム。

相互作用

抽象化を使用して2つの具体的なオブジェクトを切り離すことができますが、それらは相互に通信するため、「結合」ではなく「相互作用」と言います(相互作用を減らすことは両方を減らすことを意味します)。それらは、この間接的なコミュニケーションの過程で副作用を引き起こす可能性があります。そして、しばしば、システムの正確さを推論する能力は、「結合」よりもこれらの「相互作用」に関連していると感じます。インタラクションを最小限に抑えると、物事が鳥瞰図のすべてについて推論するのがはるかに簡単になる傾向があります。つまり、物事はお互いにまったく話していないことを意味し、その意味から、ECSはまた、最小限の最小値への結合だけでなく、「相互作用」を本当に最小化する傾向があります(少なくとも私は持っていません)

とはいえ、これは少なくとも部分的には私と私の個人的な弱点かもしれません。巨大な規模のシステムを作成し、それについて自信を持って推論し、ナビゲートし、予測可能な方法でどこでも潜在的な望ましい変更を行うことができると感じている最大の障害は、状態とリソース管理です副作用。数万のLOCから数十万のLOCから数百万のLOCに移行するとき、それは私が完全に自分で作成したコードであっても、発生し始める最大の障害です。何かが何よりもクロールを遅くする場合、アプリケーションの状態、データ、副作用の面で何が起こっているのか理解できなくなります。それ' システムが私の思考能力を超えて成長した場合、変更の完全な影響を理解することができないほど私を遅くする変更を行うのに必要なロボットの時間ではありません。インタラクションを減らすことは、私にとって、これらのことに圧倒されることなく、より多くの機能を備えた製品をより大きく成長させるための最も効果的な方法です。アプリケーションの状態を変更し、副作用を大幅に引き起こす可能性さえあります。

このようなものに変えることができます(ダイアグラムのすべてに機能があり、明らかに実際のシナリオにはオブジェクトの数が何倍もあり、これはカップリングとしてではなく「相互作用」ダイアグラムです。間に抽象化があります):

ここに画像の説明を入力してください

...これには、システムのみに機能があります(青色のコンポーネントは単なるデータであり、現在は結合図です)。

ここに画像の説明を入力してください

そして、これらのすべてについて浮上している考えがあり、SOLIDとより互換性のあるより準拠したOOPコンテキストでこれらの利点のいくつかを組み立てる方法がありますが、デザインと言葉はまだ見つかっていません。私はOOPに直接関連するすべての用語を使い回すのに慣れていたので、難しい。私はここで人々の答えを読んでそれを理解しようとし続け、また自分自身を策定するために最善を尽くしていますが、ECSの性質について非常に興味深いことがあります。それを使用しないアーキテクチャにもより広く適用できるかもしれません。また、この回答がECSプロモーションとして実現しないことを願っています!ECSの設計が私の考えを大きく変えたので、私はそれが非常に面白いと感じています


相互作用と結合の区別が好きです。最初の相互作用図は難読化されていますが。これは平面グラフなので、交差する矢印は必要ありません。
D Drmmr

2

固い原則は良いですが、KISSとYAGNIは対立の場合に優先されます。SOLIDの目的は複雑さを管理することですが、SOLID自体を適用することでコードがより複雑になると、その目的に反します。例を挙げると、クラスがわずかしかない小さなプログラムがある場合、DI、インターフェイス分離などを適用すると、プログラムの全体的な複雑さが非常に大きくなる可能性があります。

オープン/クローズドの原則は特に議論の余地があります。基本的に、サブクラスまたは同じインターフェースの別個の実装を作成することにより、クラスに機能を追加する必要がありますが、元のクラスはそのままにしておきます。調整されていないクライアントが使用するライブラリまたはサービスを維持している場合、既存のクライアントが依存する可能性のある動作を壊したくないため、これは理にかなっています。ただし、独自のアプリケーションでのみ使用されるクラスを変更する場合は、クラスを単純に変更する方がはるかに簡単でクリーンです。


OCPの説明では、構成によってクラスの動作を拡張する可能性を無視します(たとえば、クラスで使用されるアルゴリズムを変更できるように戦略オブジェクトを使用する)。 。
ジュール

1
KISSとYAGNIが常に優先される場合、1と0でコーディングする必要があります。アセンブラーは、うまくいかない可能性のある何かです。KISSとYAGNIは、設計作業の多くのコストのうち2つを指摘していません。そのコストは、設計作業の利益と常にバランスが取れていなければなりません。SOLIDには、場合によっては費用を補う利点があります。いつ線を越えたかを伝える簡単な方法はありません。
candied_orange

@CandiedOrange:機械語コードは高水準言語のコードよりも簡単だということに同意しません。マシンコードには、抽象性がないために偶発的な複雑さが多く含まれるため、マシンコードで典型的なアプリケーションを作成することを決定するのは間違いなくKISSではありません。
ジャックB

@Jules:はい、コンポジションが望ましいですが、コンポジションを使用してカスタマイズできるように元のクラスを設計する必要があります。したがって、将来どのような側面をカスタマイズする必要があるか、どのような側面について仮定する必要がありますカスタマイズできません。場合によってはこれを行う必要があります(たとえば、配布用のライブラリを作成している場合)が、コストがかかるため、SOLIDに従うことは常に最適とは限りません
ジャックB

1
@JacquesB-true。そして、OCPはYAGNIに対抗する中核にあります。どのように達成しようとしても、拡張ポイントを設計して後で改善できるようにする必要があります。2つの理想の間で適切なバランスポイントを見つけるのは難しいことです。
ジュール

1

私の経験では:-

大規模なクラスは、規模が大きくなると保守が指数関数的に難しくなります。

小さなクラスは維持が容易であり、小さなクラスのコレクションを維持することの難しさは、クラスの数に対して算術的に増加します。

大きなクラスが避けられない場合もあれば、大きな問題が大きなクラスを必要とする場合もありますが、読みやすく理解するのははるかに困難です。わかりやすい名前の小さなクラスの場合、理解にはクラス名だけで十分です。クラスに特別な問題がない限り、コードを見る必要さえありません。


0

ソリッドの「S」と、オブジェクトにそれ自体のすべての知識を持たせる必要がある(昔ながらの)必要性との間に線を引くことは、常に難しいと思います。

15年前、私はすべてを含むクラスを持つために聖杯を持っていたデプリーの開発者と仕事をしました。したがって、住宅ローンの場合は、保険と支払い、収入とローン、税情報を追加できます。また、税金と支払い、税金と控除を計算し、それ自体をシリアル化し、ディスクなどに保存できます。

そして今、私は同じオブジェクトをたくさんの小さなクラスに分けています。それらははるかに簡単でより良いユニットテストができるという利点がありますが、ビジネスモデル全体の良い概要を提供しません。

そして、はい、あなたはあなたのオブジェクトをデータベースに結びつけたくないことを知っていますが、あなたはそれを解決するために大きな住宅ローンクラスにリポジトリを注入することができます。

それに加えて、小さなことだけを行うクラスに適した名前を見つけるのは必ずしも簡単ではありません。

ですから、「S」が常に良いアイデアであるかどうかはわかりません。

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