web-dev-qa-db-ja.com

オブジェクト指向のコードを書くときは、常にデザインパターンに従っている必要がありますか?

オブジェクト指向プログラムに考えられるデザインパターンはありますか?最近私がDoorを含むLockクラスの実装を見たので、これを尋ねます。これはテストの一部であり、答えはコードがNull Objectパターンに従っていることです:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

これは私に考えさせました:このコードは説明が非常に単純であるにも関わらず(このクラスはロック付きのドアクラスを設計しています)良いデザインパターンに従っているので、もっと複雑なコードを書いているなら、そこにすべきです常に私がフォローしているデザインパターンですか?

36
user2030677

私がフォローしているデザインパターンは常にあるべきですか?

Dear God NO!

つまり、あなたはできます先に進んで、任意のランダムコードがいくつかのランダムXYZパターンに従っていると言いますが、それは私が王であると主張するよりも有用ではありません私のコンピュータチェア。それがの意味で、私の主張を正確に尊重しないものでさえ、誰も本当に知りません。

設計パターンはコミュニケーションツールであり、プログラマーは他のプログラマーに何回行われたか、何をすべきかを、時間をかけずに繰り返すことができます。そして、それらは何度も登場するものなので、プログラマーが「ちょっと、XYZを作成することは、良い/便利なため、常に登場するように見える」ことを学ぶのに役立つ概念です。

彼らはしないでくださいあなた自身のことを考える必要性を置き換え、あなたの目の前の固有の問題のパターンを調整します、または、Niceバケットに収まらないすべての避けられないことを処理します。

144
Telastyn

番号。

これは、ギャングオブフォー(元々はデザインパターンを普及させていた)がそれについて 彼らの本

notをどのように使用するかについて少し説明しなければ、デザインパターンの使用方法についての議論は完了しません。デザインパターンを無差別に適用しないでください。間接参照のレベルを追加することで柔軟性と可変性を実現します。これにより、設計が複雑になり、パフォーマンスが低下する可能性があります。設計パターンは、それが提供する柔軟性が実際に必要な場合にのみ適用してください。」

あなたが示す例は実際にはほとんど何もしません(私はそれが意図されていたとは思わない、それは単なる例であることを意図したと思います)。それ自体は、nullオブジェクトパターンを必要としません。より大きなプログラムのコンテキストでは、そうなる可能性があります。

間違ったアプローチは、「デザインパターン」とラベル付けされたからといって、それが良いはずであると想定し、さらに多くのパターンを詰め込む場所を探すことです。プログラムに適合し、実際に問題を解決するときにそれらを使用してください。

38
Michael Shaw

より複雑なコードを記述している場合、常に従う設計パターンが必要ですか?

いいえデザインパターンは、オブジェクト間の関係におけるpatternsです。言い換えれば、誰かが「ねえ、私たちはこれをたくさんやっているようです。名前を付けましょう」と言われるほど頻繁に使用および再利用される関係です。 OOPそして GOFによって受け継がれる !の初めに、デザインパターンのリストが一度に決定されなかった!それらは発見され、最終的に文書化され、その後、本。

とはいえ、デザインパターンの利点の大きな部分は、ソフトウェアデザインについてより高いレベルで考えることが容易になることです。実装の詳細について心配する必要がなく、全体像についてさらに考えることができます。その意味では、彼らはあなたをマニューシャから解放しますが、あなたがあなた自身を表現する方法があなたが知っている言葉によって制限されるのと同じ方法であなたを制限することもできます。だから、あなたが知っているパターンがあなたが考えている言葉だからこそ、あなたがするほとんどのことのためのデザインパターンがである時が来るかもしれません。パターンを悪用している可能性がある場合や、物事を行うためのより良い方法についてより深く考える必要がある場合には、目を開いておいてください。

また、実際には、オブジェクトフレームワークのような既存のコードのパターンを認識するほど、特定のデザインパターンを実装しないことがよくあります。一般的な設計パターンについて知ることで、すでに理解している用語でクラス間の関係を確認できるため、フレームワークの使用方法をより簡単に理解できます。

29
Caleb

デザインパターンには2つの利点があります。

  1. 人々は一般にパターンが何であるかについて同意するので、それらは他の開発者に説明するのが簡単です
  2. 彼らは私たちの前任者によってかなり思慮深く打たれた傾向があるので、彼らの長所と短所はよく理解されています。

すべてのプログラムの目標は

  1. できます。最終目標が何であれ、使用するデザインパターンの数は関係ありません。 OO設計パターンを使用すると、問題を簡単に理解できるビットに細かく分割できるので、機能することを簡単に証明できます。
  2. 読みやすいです。これがデザインパターンがいいところです。 OO彼らが解決する問題は複雑です。「標準的な」方法でそれらを解決すると、次の開発者にとっては簡単になります
  3. 成長しやすいです。ほぼすべての最新のプログラムが、誰もが計画したとおりに終了しています。すべてのプログラムは、最初のリリース後に成長します。 OOパターンは成長に不思議なことに優れていることで知られています。

つまり、OO設計パターンへのすべての参照は、「それらは仕事に優れている」ということです。それらは完璧ではありませんが、ニッチを非常に効果的に満たします。それらを使用してください。彼らが働くとき、彼らが働かないときそれらを避けなさい。

「複雑なコード」の例として、質問で述べたように、私が作成したスクリプト言語を取り上げます。そのほとんどはOOどこにでもデザインパターンがあります。しかし、ガベージコレクターを書くことになると、OOのすべてのふりを無茶苦茶に落としました。昔ながらのビットバッシングです。ファイナライザを書くまでは、OOパターンはありません。もう一度、OO再び便利なモデルです。何の威力も状況もないまま、コードは突然OOテクニックを再び使用するようにシフトバックしました。

製品を改善する場合は常に設計パターンを使用し、製品を悪化させる場合は使用しないでください。

10
Cort Ammon

答えは他の答えが許しているよりも微妙なので、私は傾向を少し後退させます。作成するすべてのクラスでデザインパターンを使用する必要はありませんが、ほとんどの重要なprogramsを使用する必要があります。

設計パターンのない重要なプログラムは、次のことを示しています。

  • あなたのプログラムは非常にユニークなので、プログラマーが以前に直面した一般的な問題に似ている部分はありません。または
  • プログラムにはこれらの一般的な問題が含まれていますが、これまで誰も考えていなかったより良い方法でそれらを解決しました。

どちらのシナリオも非常に可能性が低く、問題はありません。

これは、デザインパターンがデザインを駆動する必要があることを意味しません。そうしないと見た目が悪いと思われるため、無差別に挿入する必要があるということではありません。間違った設計パターンは、なしより悪いです。

つまり、プログラム全体のデザインパターンの欠如をコードのにおいとして見る必要があります。再検討して、デザインがよりクリーンにならないかどうかを再評価させるもの。その時点でプログラムから設計パターンを除外することにした場合、それは偶然ではなく、意図的な情報に基づく決定でなければなりません。

たとえば、「ドアとロックをモデリングする必要があります。どのデザインパターンを使用する必要がありますか?」ただし、デザインパターンを使用せずに最初にデザインした場合は、後で「このコードに非常に多くのnullチェックがあるので、それらを管理するのに役立つデザインパターンはあるのだろうか」と言われるはずです。

違いを見ます?微妙ですが重要な違いです。

5
Karl Bielefeldt

壊れた質問。 GoFによって解放された多くのダメージを取り消すデザインパターンの新しい定義を紹介しましょう:デザインパターンは優れたコーディング手法です。それでおしまい。

かなり複雑なモジュールには、いくつかの設計パターンがあります。あなたがキャッシュするときはいつでもそれはおそらくフライウェイトのパターンですが、あなたがそれを呼び出さないなら、私はプログラミングの学位を取り消すつもりはありません。その中にコールバックがあるときはいつでも、ある種のイベント/ファイア/コールバックパターンにいます。 etc.「静的」という言葉があれば、シングルトンを持っています。静的コンストラクタがある場合は、ファクトリパターンがあります。リソースがモジュールに渡される場合は、依存性注入を使用しています。

「デザインパターン」とは、GoFによって不人気な用語であり、すべてのパターンが同じレベルにあるように聞こえるか、クラスごとに3〜5の推奨医師を使用する必要があります。 他の誰かが正しく行ったことを正しく行うと、それはデザインパターンになりますfor(;;)は、たとえば無限ループを表すために使用される一般的なパターンです。

たくさんのデザインパターンを学ぼうとするべきではありません。 プログラミング知識はデザインパターンによって索引付けされていません!むしろ良いコードの書き方を学ぶ必要があります本やブログを読んだり、自分の分野の会議に参加したりします。たとえば、依存関係注入をすでに使用しているが、ラベルを付けていない場合、DIを使用するかIoCフレームワークを使用することでalwaysの恩恵を受ける可能性があります。または、イベントやコールバックでのコーディングに苦労している場合は、Haskellを学んで、機能的なデザインパターンに慣れれば、簡単になります。

そして、もしあなたのクラス全体が誰か他の人が正しかったことを一つの大きなものとして読むなら、なぜあなたは車輪を再発明するのですか?ちょうど彼らのものを使用してください。

4
djechlin

コードを書いているとき、意図的にできるだけ多くのデザインパターンを使用するつもりはありません。しかし、私は無意識のうちに、コーディングの問題が発生したときに、設計パターンの1つが適合しているように思われ、それを使用しています。そして、時には何も適合しません。私にとってより重要なのは、その仕事を実行し、維持と成長が容易なコードを書くことです。

これは、デザインパターンを使用したOOD原則の適用に関する article であり、C++のコード例も含まれています。クリーンなコードを作成するために、いつどのようにデザインパターンを適用するかを示しています。

0
rosewater

パターンは、一般的な問題の一般的な解決策です。私たちは常にいくつかのパターンに従っています。GoFによるパターンは、最も繰り返し発生するパターンに対応しています。つまり、ソフトウェアエンジニアに共通の理解と共通のアプローチを提供することです。

そうは言っても、私の答えは「いいえ」ですが、はい、あなたは常にあなた自身のいくつかのパターンに従っています。 GoFが正しくそれを置くように-

ある人のパターンは、別の人の原始的な構成要素です。

すばらしい引用。

0
Syed Priom

常に OO設計原則に従う必要があります(たとえば、モジュール性、情報の隠蔽、高度な結合など)。設計パターンは、OO設計原則、特に KISS原則 を考慮する場合)の比較的洗練されたニッチです。

パターンは、一般的な設計問題の解決策です。これらの問題は、問題領域(たとえば、企業の人事管理ソフトウェア)との2つの場所のいずれか(または両方の組み合わせ)から発生します。解空間。 OOプログラムは、ソリューションスペース内のインスタンスです(たとえば、OOプログラムを設計してHRの管理を容易にするためにプログラムを設計することができます)。

パターンをいつ使用するかを知るのはそれほど簡単ではありません。一部のパターンは低レベルで、コーディングとソリューション空間に近いものです(シングルトン、Nullオブジェクト、イテレーターなど)。その他の問題は、問題領域の要件に基づいています(たとえば、元に戻す/やり直しをサポートするコマンドパターン、複数の入出力ファイルタイプをサポートする戦略)。

多くのパターンは、将来ソフトウェアのバリエーションをサポートする必要性から生じます。これらのバリエーションを作成する必要がない場合は、パターンが過剰に設計されている可能性があります。たとえば、既存の外部HRデータベースを操作するためにアダプターパターンを使用します。現在のデータベースはOracleで動作し、将来的にNoSQLをサポートする必要があるため、アダプターを適用することにしました。 NoSQLが組織に登場しない場合、そのアダプターコードは役に立たない可能性があります。 [〜#〜] yagni [〜#〜] を参照してください。決して来ないバリエーションのサポートは、デザインパターンの誤用です。

0
Fuhrmanator