2

前提

私は、オブジェクト指向設計手法の「良い」と「悪い」を客観的に定義する方法があり、コミュニティとしてこれらが何であるかを判断できると信じています。これはアカデミックな演習です。本気でやり遂げれば、コミュニティ全体に大きな利益をもたらすと信じています。コミュニティは、「このテクニックは『良い』か『悪い』かであり、特別な状況がない限り使用すべきか、使用すべきではない」と指摘できる場所を持つことで利益を得ることができます。

プラン

この取り組みでは、(関数型、セットベース、またはその他のタイプの言語とは対照的に) オブジェクト指向の原則に焦点を当てる必要があります。

私は 1 つの回答を受け入れるつもりはありません。代わりに、回答が最終的なコレクションに貢献するか、問題の合理的な議論になることを望んでいます。

これには賛否両論があるかもしれませんが、私たちは何かを解決できると信じています. ほとんどすべてのルールには例外があり、これが意見の相違の原因になると私は信じています。私たちは宣言を行い、関連する例外と反対者からの異議に注意する必要があります。

基本

「良い」と「悪い」の定義を試してみたいと思います。

  • 「良い」 - この手法は初めて機能し、永続的な解決策になります。後で簡単に変更でき、実装に費やした時間の投資をすぐに支払うことができます。これは一貫して適用でき、将来の保守プログラマーによって容易に認識されます。全体として、それは優れた機能に貢献し、製品の寿命全体にわたってメンテナンスのコストを削減します.

  • 「悪い」 - この手法は短期的にはうまくいくかもしれませんが、すぐに不利になります。すぐに変更するのが難しいか、時間の経過とともにより困難になります。初期投資は少額でも多額でもかまいませんが、すぐにコストが増大し、最終的にはサンク コストになり、削除するか、常に回避する必要があります。これは主観的に適用されたものであり、一貫性がなく、将来、メンテナンス プログラマーが驚くか、容易に認識できないものになる可能性があります。全体として、それは製品の保守および/または操作の最終的な増加コストに寄与し、製品への変更を抑制または防止します。変化を阻害または防止することにより、それは単なる直接費用ではなく、機会費用および重大な責任になります。

スターター

優れた貢献とはどのようなものかを示す例として、「優れた」原則を提案したいと思います。

関心事の分離

[簡単な説明]

[コードまたはその他のタイプの例]

目標

【この原理で防げるトラブルの解説】

適用性

[なぜ、どこで、いつこの原則を使用するのですか?]

例外

[この原則を使用しない場合、または実際に害を及ぼす可能性があるのはどのような場合ですか?]

反対意見

[コミュニティからの反対意見や反対意見はこちらに記入してください]

4

3 に答える 3

3

適切な出発点となる、十分に理解されている原則がいくつかあります。

また、既存の設計パターンを研究してその背後にある原則を見つけることも良い考えです。最も重要なのは、(一般に) 継承よりも構成を優先することです。

于 2008-12-14T18:33:21.547 に答える
1

関心事の分離

Mixin スタイルの継承よりも集約を優先する

機能はユーティリティ クラスから継承することで取得できますが、多くの場合、そのクラスのメンバーを使用してすべてを取得できます。

例 (Boost.Noncopyable):

Boost.Noncopyable は、コピー コンストラクターまたは代入演算子がない C++ クラスです。サブクラスがコピーまたは割り当てられるのを防ぐために、基本クラスとして使用できます (これは一般的な動作です)。ダイレクト会員としてもご利用いただけます

これを変換します:

class Foo : private boost::noncopyable { ... };

これに:

class Foo {
    ...
private:
    boost::noncopyable noncopyable_;
};

例 (ロック可能なオブジェクト):

Java は、synchronized任意のオブジェクトをスレッドセーフな方法で使用できるようにするイディオムとしてキーワードを導入しました。これを他の言語にミラーリングして、任意のオブジェクトにミューテックスを提供できます。一般的な例はデータ構造です:

class ThreadsafeVector<T> : public Vector<T>, public Mutex { ... };

代わりに、2 つのクラスを一緒に集約することができます。

struct ThreadsafeVector<T> {
    Vector<T> vector;
    Mutex mutex;
}

目標

継承は、コードを再利用するメカニズムとして悪用されることがよくあります。Is-A 関係以外に継承が使用されると、全体的なコードの明瞭さが低下します。

より深いチェーンでは、ミックスイン基本クラスは、サブクラスがミックスイン クラスの複数のコピーを継承することになる「死のダイアモンド」シナリオの可能性を大幅に高めます。

適用性

多重継承をサポートする任意の言語。

例外

mixin クラスがメンバーのオーバーロードを提供または必要とするすべてのケース。この場合、継承は通常、Is-Implemented-In-Term-Of 関係を意味し、集約は十分ではありません。

反対意見

この変換の結果は、パブリック メンバーにつながる可能性があります (たとえば、コンポーネントとしてMyThreadSafeDataStructureパブリックにアクセスできる可能性Mutexがあります)。

于 2008-12-14T17:59:11.790 に答える
1

簡単に言えば、「優れた」オブジェクト指向設計は変更に対して堅牢であり、要件の変更に対するコードの破損が最も少ないということだと思います。すべての通常のルールを考慮すると、それらはすべて同じ結論になる傾向があります。

難点は、コンテキストなしではデザインの「良さ」を評価できないことです。モジュール化の場合、破損を最大化する要件の変更が存在し、各メソッドですべてのクラスが変更されるというのは定理だと私は信じています。

それについて厳密にしたい場合は、「変更ケース」のコレクションを作成し、それらを確率順に並べることができます。これにより、変更の可能性が最も高い場合の破損を最小限に抑えることができます。

ただし、ほとんどの場合、十分に発達した直感が大いに役立ちます。デバイス固有またはプラットフォーム固有のものが変更される傾向があり、ビジネス ルールとビジネス プロセスが変更される傾向がありますが、算術などの実装が変更されることはほとんどありません。(ご想像のとおり、決してそうではありません。たとえば、プラットフォームでサポートされている BCD 演算を利用できる場合と利用できない場合があるビジネス システムを考えてみてください。)

于 2008-12-14T18:32:51.393 に答える