オブジェクト指向コードを書くとき、私は常にデザインパターンに従うべきですか?


37

オブジェクト指向プログラムに考えられる設計パターンはありますか?これは、最近、の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;
};

このコードは、私は、より複雑なコードを書いていますので、もし、そこにする必要があり、説明は(このクラスは、ロックとドアのクラスを設計している)簡単なようであっても良いデザインパターンに従います。これは私が考えて作られた、常に私はいくつかのデザインパターンがあることもフォローしていますか?


3
非常に関連する:右のデザインパターンの選択

51
完全にイディオムで話せると思いますか?いや?次に、デザインパターンを組み合わせてプログラムを構築しないでください。
キリアンフォス

4
あなたの例では、Nullオブジェクトパターンは学術目的でのみ追加され、このコードに「良いデザイン」を導入しません。
ドックブラウン14年

4
@djechlin:言い換えると、「2ワード」のデザインパターンを使用します:)
マイケルショー14年

11
問題は、設計パターンが思考の代替であり、経験の代替であると信じている人が多すぎることです(ある程度の試行錯誤を意味します)。デザインパターンが満載の本をTinker Toysのようにまとめて、サイズや複雑さ、質の良いアプリケーションを作成することはできません。経験豊富なプログラマでさえ、機能するデザインを見つける前に2つまたは3つのデザインを試す必要があります。
ダニエルRヒックス14年

回答:


143

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

親愛なる神NO!

私が意味する、あなたがすることができます先に行くんし、任意のランダムなコードはいくつかのランダムなXYZパターンに従っていることを言うが、私は私のコンピュータの椅子の王であると主張するよりも、それが何より便利です。他の誰もそれが何を意味するのか本当に知りません。

設計パターンはコミュニケーションツールであるため、プログラマは他のプログラマに、何回も繰り返して時間を費やすことなく、何をしたか、何をすべきかを伝えることができます。そして、それらは多くの場合に出てくるものなので、プログラマーが「やあ、XYZを作ることは常に良い/有用だから常に出てくるようだ」ということを学ぶのに役立つ概念です。

彼らはしていない仕立て屋に、あなたの前にユニークな問題のためのパターンをあなた自身のために考えるようにする必要性を置き換える、または素敵なバケットに適合しない必然的なもののすべてを処理するために。


5
あなたの最初の段落は私がこれに答える方法の一部です。繰り返されると何かがパターンになります。コミュニケーションを必要とするのに十分な回数繰り返される場合、それはパターンであり、名前の恩恵を受けます。抽象化が欠落しているためにパターンが開発されるだけであると主張する人もいます。パターンの追求は、自慢のカーゴカルトの一員としての悪名高い道です。
メイガス14年

11
@Cerad:もちろん、神のクラスも書かないことを約束する限りです!
yatima2975 14年

9
ジョン・ドウ-技術エンジニア、ジェネリックコードモンキーと彼のコンピュータの椅子の王
HJK

1
おそらく、設計では適切なパターンを使用する必要があり、クラスにはそのような名前を付ける必要があります。それらは重要なツールです。the_cult(tm)を恐れることは同じくらい危険です。
ガスドール14年

25
素晴らしい答えです!私の唯一の批判は、「親愛なる神NO!」十分な大きさではありません。
tobyink

37

いや

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

「デザインパターンの使用方法についての議論は、それらを使用しない方法についていくつかの言葉がなければ完了しません。デザインパターンは無差別に適用されるべきではありません。パフォーマンスにいくらかのコストがかかります。設計パターンは、それが提供する柔軟性が実際に必要な場合にのみ適用する必要があります。

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

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


7
Erich Gamma、Richard Helm、Ralph Johnson、John Vlissidesによる「デザインパターン:再利用可能なオブジェクト指向ソフトウェアの要素」という本。
developerwjk 14年

4
+1実際に設計パターンのソースを引用するため。
ファラプ14年

29

もっと複雑なコードを書いている場合、私が従うデザインパターンは常にあるべきですか

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

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

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


10

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

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

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

  1. できます。最終目標が何であれ、それを使用する必要があります。または、使用するデザインパターンの数は関係ありません。オブジェクト指向のデザインパターンを使用すると、問題を簡単に理解しやすいビットに分割できるため、その動作を簡単に証明できます。
  2. 読みやすいです。これは、デザインパターンが優れているところです。彼らが解決するオブジェクト指向の問題は複雑です。「標準」の方法でそれらを解決する場合、次の開発者にとって簡単です
  3. 成長は簡単です。ほぼすべての最新プログラムが、誰もが計画した場所で終了します。すべてのプログラムは、最初のリリース後に成長します。オブジェクト指向のパターンは、不思議なことに成長が得意であることが知られています。

言われているとおり、OOデザインパターンへのすべての参照は「彼らは仕事にちょうど良い」ことに注意してください。それらは完璧ではありませんが、非常に効果的にニッチを埋めます。動作するときは使用し、動作しないときは使用しないでください。

「複雑なコード」の例として、あなたが質問で述べたように、私が書いたスクリプト言語を取り上げます。そのほとんどは、あらゆる場所にデザインパターンを持つオブジェクト指向です。ただし、ガベージコレクターの作成に関しては、OOのふりをすべて断念して削除しました。これは、必要な特定の処理が、従来のビットバッシングとしてモデル化されたためです。ファイナライザーの作成に至るまで、オブジェクト指向のパターンはありませんでした。そこでは、オブジェクト指向が再び有用なモデルになり始めました。威勢も状況もなければ、コードは突然オブジェクト指向技術を使用するようになりました。

製品を改善するたびにデザインパターンを使用します。それらが製品を悪化させる場合は避けてください。


2
最後の文は太字または要約として一番上にあるべきだと思います。
ファラプ14年

5

答えは他の答えが与えるよりも微妙なので、私は傾向を少しバックします。あなたが書くすべてのクラスはデザインパターンを使うべきではありませんが、あなたが書くほとんどの非自明なプログラムはそうすべきです。

設計パターンのない自明でないプログラムは以下を示します。

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

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

だからといって、デザインパターンがデザインを推進する必要があるわけではありません。そうしないと見た目が悪いと思うので、無差別にデザインパターンを挿入する必要があります。間違ったデザインパターンは、どれよりも悪いです。

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

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

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


5
設計パターンよりも多くの一般的な問題(およびそれらの一般的な解決策)があります。設計パターンは、すべての一般的なソリューションのセットではなく、一般的なオブジェクト指向ソリューションのカタログ化されたサブセットです。
マイケルショー14年

1
「非自明」とはどういう意味かを定義してもらえますか。
ファラプ14年

1
主観的です。職場のチームで書くようなプログラムで、継続的に複数のメンテナーが必要です。
カールビーレフェルト14年

後であなたの問題を見るのに十分幸運なら。ヌルチェック、確かに。セキュリティの脆弱性?メンテナンス中にプログラムが中断する他の陰湿な方法は?次のエンジニアだけが発見する問題?もっと不愉快。
djechlin

「ドアと鍵をモデル化する必要があります。インターフェースはどうあるべきですか?パフォーマンスは契約の一部になりますか?サービスまたはライブラリを使用する必要がありますか?リソースはどのように渡されますか?」すべてを尋ねる必要があり、基本的に設計パターンと見なされる回答が必要です。
djechlin

4

壊れた質問。GoFによってリリースされた多くの損害を取り消すデザインパターンの新しい定義を紹介しましょう。デザインパターンは優れたコーディングの実践です。それでおしまい。

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

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

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

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


2
for(;;)慣用語はどの言語ですか?それはおそらく誰かが「正しい」ことをした最良の例ではありません。
テラスティン14年

1
@Telastyn C、C ++、Java、Javascript、C#。
djechlin

2
私は見たことがない、誰もがそれを超える好むwhile(true)(またはwhile(1)プログラミングの私の20年以上にC、C ++、Javaの、またはC#で)。
Telastyn 14年

1
@Telastyn stackoverflow.com/a/2611744/1339987 fwiw読みやすいように見えるので、while(true)を好み始めました。
djechlin 14年

1
私は常に(;;)に使用します。特に理由はないが、おそらくどこかで読んだ。変数や定数が関係していないという事実が好きです。とにかく、@ Telastynは誰かに会いました。
アリ14年

0

常にオブジェクト指向の設計原則(モジュール性、情報の隠蔽、高い凝集性など)に従う必要があります。設計パターンは、特にKISS原則を考慮する場合、オブジェクト指向設計原則の比較的洗練されたニッチです。

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

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

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


0

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

とはいえ、私の答えは「いいえ」ですが、はい、あなたは常に自分のパターンに従っています。GoFが正しく言うと、

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

素晴らしい引用。


これは作られたポイントを超える大幅な提供の何にも思えるし、前7つの回答で説明していません
ブヨ

いいよ 注意してください、私は一般的な点を指摘しました...それは理論的な議論としてデザインパターンに適用可能です。
サイードPriom

「このサイトはすべて答えを得るためのものです。ディスカッションフォーラムではありません...」(ツアー
gnat 14年

私は質問に答えました。ありがとうございました。この会話はここで終わります。
Syed Priom 14年

しかし、@ gnatは、はるかに簡潔なものです。
djechlin 14

0

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

ここに、デザインパターンを使用したOOD原則の適用に関する記事があり、コード例(C ++)もあります。クリーンなコードを作成するために、いくつかのデザインパターンを適用する方法とタイミングを示しています。


2
その記事は昨日書かれました。あなたはまったくブログと提携していますか?もしそうなら、その所属を開示してください。
マーティンピーターズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.