タグ付けされた質問 「design-patterns」

設計パターンは、ソフトウェア設計で一般的に発生する問題に対する一般的な再利用可能なソリューションです。

5
設計パターンのオープンクローズの原則
オープンクローズの原則を実際にどのように適用できるかについて、少し混乱しています。時間の経過とともにビジネスの要件は変化します。Open-Closedの原則に従って、既存のクラスを変更する代わりにクラスを拡張する必要があります。クラスを延長するたびに、要件を満たすのは現実的ではないように思えます。列車予約システムの例を挙げましょう。 列車予約システムでは、チケットオブジェクトがあります。通常のチケット、割引チケットなど、さまざまなタイプのチケットが存在する可能性があります。チケットは抽象クラスで、RegularTicketとConcessionTicketsは具象クラスです。すべてのチケットには共通のPrintTicketメソッドがあるため、基本抽象クラスであるチケットで記述されます。これが数か月間うまくいったとしましょう。ここで、チケットのフォーマットを変更するように要求する新しい要件が発生します。印刷されたチケットにいくつかのフィールドが追加されるか、形式が変更される場合があります。この要件を満たすために、次のオプションがあります チケット抽象クラスのPrintTicket()メソッドを変更します。しかし、これは開閉原理に違反します。 子クラスのPrintTicket()メソッドをオーバーライドしますが、これは印刷ロジックを複製します。これは、DRY(自分を繰り返さないでください)の原則に違反しています。 だから質問は オープン/クローズの原則に違反せずに、上記のビジネス要件を満たすにはどうすればよいですか。 クラスが変更のために閉じられることになっているとき?クラスが変更のために閉鎖されていると見なすための基準は何ですか?それは、クラスの初期実装後ですか、それとも本番環境での最初のデプロイメント後か、それとも別の場合があります。

2
MVP(監視コントローラー)ビューはモデルを更新しますか?
私はMVPについて、特にコントローラーの監督について読んでいます。ビューをモデルとどのようにやり取りするかは、頭を抱え込むのが難しい点の1つです。 プレゼンターがモデルを更新する必要があり、ビューがモデルから読み取ることは私の理解でした。プレゼンターは、インターフェイスを介してビューを更新することもできます。これに関するマーティンファウラーの記事は、まさにそれを示しているようです(http://martinfowler.com/eaaDev/SupervisingPresenter.html)。 ただし、他の記事/ブログは、モデルを直接更新するビューを示しています(https://blogs.msdn.microsoft.com/erwinvandervalk/2009/08/14/the-difference-between-model-view-viewmodel-and-other-分離表示パターン/)。 これらは単なるパターンであることを知っているので、さまざまな実装がありますが、モデルを更新するビューは、必要以上に多くのことを行っているようです。 たとえば、名前と電話番号を含む人物クラスがあったとします。ビューには、この名前と番号、および個人の名前と番号を変更するための送信ボタンを表示できます。送信ボタンをクリックすると、ビューではなくプレゼンターで更新が処理されると思います。ただし、私が参照した記事は、ビューがモデルを直接更新できることを提案しています。 それで、ビューはモデルを更新する必要がありますか?それとも、プレゼンターだけが処理する必要がありますか? 編集: MSDN記事のコード: public class PersonalDataView : UserControl, IPersonalDataView { protected TextBox _firstNameTextBox; public void SetPersonalData(PersonalData data) { _firstNameTextBox.Value = data.FirstName; } public void UpdatePersonalData(PersonalData data) { data.FirstName = _firstNameTextBox.Value; } }

2
DDD:再利用可能なモジュールとサービスタイプの区別(ドメイン、インフラストラクチャ、アプリケーション)の作成
したがって、「Vaughn Vernonによるドメイン駆動設計の実装」を読んだ後、コアドメインの概念と思われるものを個別のモジュールに分離することにより、再利用性を高めるためにコードをリファクタリングすることにしました。 各モジュールには、ドメイン、インフラストラクチャ、アプリケーション/プレゼンテーションレイヤーを含む独自のアーキテクチャレイヤーのセットが含まれています(ヴォーンの推奨に従って、アプリケーションレイヤーの責任をルート、MVCコントローラー+テンプレートに存在するテンプレートからさらに分離することにしましたプレゼンテーション層)。 これらの各レイヤーを独自のパッケージ内に配置することにしました。各パッケージは、その下のレイヤーを依存関係として参照しています。つまり、プレゼンテーション層はアプリケーション層に依存し、アプリケーションはインフラストラクチャに依存します。リポジトリはドメインの一部であるため、各リポジトリインターフェースはドメイン層/パッケージ内に存在し、実装はインフラストラクチャ層/パッケージ(Doctrine 、など)。 この方法でコードを再構築することで、アプリケーションレイヤーをスワップアウトし、複数のWebアプリケーション間でドメインを再利用できることを願っています。 最終的にコードは再び形を整え始めているように見えますが、それでも私を混乱させるのは、アプリケーション、インフラストラクチャ、ドメインサービスのこの違いです。 ドメインサービスの一般的な例の1つは、パスワードのハッシュに使用するものです。ユーザーエンティティは、ユーザーの資格情報を格納するために使用される可能性のあるさまざまなハッシュアルゴリズムに関与する必要がないため、これはSRPの観点からは理にかなっています。 そのことを念頭に置いて、私はこの新しいドメインサービスを私のリポジトリと同じように扱いました。ドメインでインターフェースを定義し、実装をインフラストラクチャ層に任せることにより。しかし、私は今、アプリケーションサービスで何をすべきかについて考えています。 現在のところ、各エンティティには独自のアプリケーションサービスがあります。つまり、ユーザーエンティティにはアプリケーション層内にUserServiceがあります。この場合のUserServiceは、プリミティブデータ型の解析と一般的なユースケース「UserService :: CreateUser(string name、string email、etc):User」の処理を担当します。 私が気になるのは、アプリケーション層を交換することにした場合、複数のアプリケーションにわたってこのロジックを再実装する必要があるという事実です。だから私はこれが私の次のいくつかの質問につながると思います: ドメインサービスは、インフラストラクチャレイヤーとモデル間の抽象化レイヤーを提供するために存在する単なるインターフェイスですか?例:リポジトリ+ HashingServicesなど 私はこのようなアプリケーションサービスを持っていると述べました: Access / Application / Services / UserService :: CreateUser(string name、string email、etc):User メソッドシグネチャは、プリミティブデータ型の引数を受け入れ、新しいユーザーエンティティ(DTOではない!)を返します。 これは、ドメインレイヤー内で定義されたいくつかのインターフェイスの実装としてインフラストラクチャレイヤーに属しますか、それともプリミティブデータ型の引数などにより、実際にはアプリケーションレイヤーがより適切ですか? 例: Access/Domain/Services/UserServiceInterface そして Access/Infrastructure/Services/UserService implements UserServiceInterface 個別のモジュールが一方向の関係をどのように処理するか。モジュールAは、モジュールBのアプリケーションレイヤー(現在行っているように)またはインフラストラクチャの実装(個別のインターフェイスを介して)を参照する必要がありますか? アプリケーション層サービスには別のインターフェースが必要ですか?答えが「はい」の場合、それらはどこに配置する必要がありますか?

7
単一の日付と日付範囲の両方を表すことができるプロパティ:適切にモデル化する方法は?
私は2つの方法で「送料見積もり」を表すことができるシステムで働いています。 特定の日付:アイテムはその日付で出荷されることが保証されています 日間隔:アイテムは今日から「X to Y」日で発送されます モデルに関する情報は、意味的には同じで、「発送予定」です。配送見積もりの​​情報をシステムから取得すると、見積もりが最初の形式か2番目の形式かがわかります。 このための現在のモデルは次のようになります。 class EstimattedShippingDateDetails { DateTime? EstimattedShippingDate {get; set;} Range? EstimattedShippingDayRange {get; set;} } Range 整数の「始まり->終わり」をラップする単純なクラスです。 struct Range { int Start {get; set} int End {get; set} public override ToString() { return String.Format("{0} - {1}", Start, End); } } 推定モデルのプロパティの1つだけが入力されるため、このアプローチは好きではありません。一方のプロパティでnullをテストし、もう一方のプロパティにデータがあると仮定する必要があります。 各プロパティは、ユーザーには異なる方法で表示されますが、現在のスイッチングロジックが存在するカスタムMVC DisplayTemplateを使用して、UIの同じ場所に表示されます。 @Model EstimattedShippingDateDetails @if …

3
コードの重複や不明確なパラメーターの通過を回避するためのクライアントAPIのリファクタリング
APIを開発する必要があります。APIの機能は、サーバーによって公開されているサービスを呼び出すリクエストです。 最初、APIは次のように機能しました。 class Server: def firstRequest(self, arg1, arg2): # block of code A async = Async() async.callFirstRequest(arg1, arg2) # block of code B def secondRequest(self, argA, argB, argC): # block of code A (identical to that of firstRequest) async = Async() async.callSecondRequest(argA, argB, argC) # block of code B (identical …

7
「オブジェクトが特定の状態にある場合にのみ許可されるオブジェクトの操作」の設計パターン
例えば: まだレビューまたは承認されていない求人応募のみを更新できます。言い換えれば、人は、HRがレビューを開始するまで、またはすでに承認されるまで、ジョブアプライアンスフォームを更新できます。 したがって、求人応募は次の4つの状態になります。 APPLIED(初期状態)、IN_REVIEW、APPROVED、DECLINED どうすればこのような動作を実現できますか? 確かに、Applicationクラスにupdate()メソッドを記述し、アプリケーションの状態を確認し、アプリケーションが必要な状態でない場合は何もしないか、例外をスローすることができます しかし、この種のコードは、そのようなルールが存在することを明らかにしていません。それにより、だれでもupdate()メソッドを呼び出すことができ、クライアントが失敗した後にのみ、そのような操作が許可されなかったことがわかります。したがって、クライアントはそのような試みが失敗する可能性があることを認識する必要があるため、注意が必要です。クライアントがそのようなことを認識していることは、ロジックが外部にリークしていることも意味します。 状態ごとに異なるクラス(ApprovedApplicationなど)を作成して、許可されたクラスにのみ許可された操作を実行してみましたが、この種のアプローチも間違っているように感じます。 そのような振る舞いを実装するための公式の設計パターン、または単純なコードはありますか?

1
DataMapperパターンのどのアプローチが複数のテーブルまたは結合されたテーブルに適していますか?
通常、Data Mapperは1つの特定のテーブルのデータをマップします。(理論的には、ストレージとドメインオブジェクトの間で通信する必要がありますが、私の場合は不可能なので、テーブルと直接通信しています。) Table1Mappper> Table1 ただし、そのテーブルで別のテーブルからデータを結合する必要がある場合は、1つのテーブルからのマッピングのみを想定していたデータマッパーのスコープを拡張します。 Table1Mapper> Table1:inner-join:Table2 Table2がTable2Mapperデータをマップする独自のマッパーを持っていれば、もっと良いのではないでしょうか? 考えた場合Yes、Table1Mapperからレコードのリストを表示し、後でTable2Mapperを使用して、結合されるはずだったデータを取得したい場合は、ループでクエリを実行することになりますが、どちらも適切ではありません。 この方法について、どのような洞察がありますか? 別の方法は、サブテーブルを処理するようにマッパーを変更することですか? class Table1Mapper { public main_table = 'table1'; public sub_table1 = 'table2'; } これは問題ないと思いますが、マッパー全体のスコープがアプリケーション内の1つの特定のエンティティを処理するまでのみです。たとえばpostとpost_author。しかし、postおよびのようにスコープが異なる場合、gallery上記は理想的なデータマッパーを提供しません。これを説明するには class PostMapper { public table_name = 'tbl_post'; public gallery_table_name = 'tbl_gallery'; } 正しくありませんか?ただし、1つのクエリで1つの投稿のギャラリーを取得する必要があります。ループでクエリのオーバーヘッドを追加することは、優れたソリューションパフォーマンスではないためです。 このようなケースを処理するより良い方法がある場合、DataMapperパターンまたは他のパターンでこれを解決する正しい方法は何だと思いますか?

3
サービスレイヤーのあるリポジトリパターン-分離が多すぎますか?
リポジトリパターンを使用するMVCサイトがあります。MVCスタイルを十分に使用しているようには思えないので、その一部を再構築する準備をしています。しかし、私もそれを実行したいので、フロントエンドが変更された場合は、交換しやすくなります。 これが私が現在持っているものです モデル-一部のモデルには、エンティティ/クラスが直接含まれています。(ログインモデルにはCustomerクラスが含まれます。これは、Customerテーブル/リポジトリクラスと直接相関しています)ビュー-ビューの一部にリポジトリクエリが含まれています-つまり _customerRepo.Query().FirstOrDefault(c => c.Login == User.Identity.Name); コントローラー-ここではそれほど大きな問題ではありません。コントローラーはいくつかのレポクエリを呼び出します。一部のコントローラーはいくつかのサービスを使用してレポを呼び出します-すなわち _customerService.GetAllCustomers() 呼び出す _customerRepo.Query().All(); これが私の考えです。 1)モデルには、ビューに表示する必要があるデータのみを含める必要があります。Customerテーブル/オブジェクトのすべてのプロパティがビューに表示されている場合でも、ビューがデータベースアーキテクチャまたはバックエンドオブジェクトについて何も認識しないように、それらを独自のモデル/クラスに書き直す必要があります。 2)ビューはモデルオブジェクトにのみアクセスする必要があります 3)(そして、これは私がとるべき道に苦労しているところです) a)コントローラー(またはMVC側のどこか)は、repo / servicesから返されたオブジェクトデータを変換してモデルに変換するコードである必要があります。このコードをモデルコンストラクターに配置できると想定していますが、検証エラーがある場合に備えて、DIはデフォルトの空のコンストラクターを想定していることに気付きました b)コントローラは、データを取得するための適切な名前の付いたメソッド(つまり、_customerRepo.GetAllCustomers())でrepoインターフェースを呼び出します c)コントローラはサービス層にのみアクセスします。サービスレイヤーは、リポジトリレイヤーとやり取りする唯一のものです。 モデル、コントローラー、サービス、リポジトリのレイヤーを抽出しすぎていますか?サービスレイヤーはすべてリポジトリで実行できるため、オーバーヘッドが多すぎませんか? オブジェクト/ビジネスエンティティをモデルに変換するための推奨アプローチは何ですか?

2
オプション機能:デフォルトのメソッドまたは分離されたインターフェース
専用インターフェースは、ドメイン固有のタイプ階層でオプション機能を公開するための良い方法のようです。ただし、これらはデコレータおよび複合パターンの使用を妨げます。これは、この種の階層でも一般的です。 特に、おそらくこれらのインターフェイスの可能な組み合わせごとにデコレータ/コンポジットを実装する必要はないでしょう。そのため、多くの場合、すべてのオプションのインターフェイスを実装し、型チェックを使用して呼び出しを選択的に転送します。これにより、インターフェイスを分離する目的が損なわれます。 Javaコレクションフレームワークが使用する別の方法は、すべての操作を基本型に含め、それらをダミーの実装で埋めることです。Java 8のデフォルトメソッドは、この使用をさらに容易にします。 ある意味で、これは、データベースの世界では、null許容列の議論のように感じられます。より実用的な後者のアプローチに対して強い議論はありますか?

3
設計パターン-戦略ごとのDLL
私は通常、次の方法でアプリケーションを設計していることに気づきました。 必要なサブシステムのインターフェースを含む1つのDLL。たとえば、Company.Framework.Persistence.dll。 上記のサブシステムの各戦略(または実装)ごとに1つの新しいDLL 。例えば: Company.Framework.Persistence.MSSQL.dll Company.Framework.Persistence.MySQL.dll Company.Framework.Persistence.FileSystem.dll これにより、多くのプロジェクトで非常に大きなソリューションが得られますが、一方で、消費者は自分のニーズに適したDLLを選択する機会が与えられます。 と呼ばれる単一のDLLがある場合Company.Framework.Persistence.dll、消費者は彼が決して使用しない可能性がある多くの戦略をロードする必要があります。DLLをモジュール化すると、この問題を解決できます。 これは良い習慣ですか?この設計には欠点がありますか?

3
ハンドルやManagerを渡さずにオブジェクトのハンドルを管理するのに最適なデザインパターンはどれですか。
OpenGLを使用してC ++でゲームを作成しています。 知らない人のために、OpenGL APIを使用して、などの多くの呼び出しをglGenBuffers行いますglCreateShader。これらの戻り値の型は、GLuint作成したものに対する一意の識別子です。作成されるものはGPUメモリ上に存在します。 GPUメモリが制限されている場合があることを考えると、複数のオブジェクトで使用されるときに同じものを2つ作成したくない場合があります。 たとえば、シェーダー。あなたは、シェーダプログラムをリンクして、あなたが持っていますGLuint。シェーダーを使い終わったら、呼び出す必要がありますglDeleteShader(またはそれに影響を与える何か)。 ここで、次のような浅いクラス階層があるとします。 class WorldEntity { public: /* ... */ protected: ShaderProgram* shader; /* ... */ }; class CarEntity : public WorldEntity { /* ... */ }; class PersonEntity: public WorldEntity { /* ... */ }; 私が今まで見たどのコードでも、すべてのコンストラクターにShaderProgram*渡して、に格納する必要がありWorldEntityます。ShaderProgramは、GLuintOpenGLコンテキストでの現在のシェーダー状態へののバインディングと、シェーダーを使用するために必要な他のいくつかの役立つことをカプセル化する私のクラスです。 私がこれで持っている問題は: を構築するために必要な多くのパラメーターがありますWorldEntity(メッシュ、シェーダー、多数のテクスチャーなどがあると考えてください。これらはすべて共有できるため、ポインターとして渡されます) どのような作成されたWorldEntityかを知る必要性をShaderProgramそれが必要 これはおそらく、異なるエンティティに渡すもののインスタンスを知っているある種のgulp EntityManagerクラスを必要としますShaderProgram。 つまりManager、クラスが必要なインスタンスEntityManagerとともにに自分自身を登録する必要があるかShaderProgram、switch新しいWorldEntity派生型ごとに更新する必要がある、マネージャの大物が必要なためです。 私が最初に考えたのは作成することでしたShaderManager(私は管理者が不良である、知っている)私はへの参照やポインタで渡すというクラスをWorldEntityので、彼らは何でも作成することができますクラスShaderProgramを経由して、彼らが望むShaderManagerとShaderManager、既存のトラックに保つことができShaderProgram、それができるよう、秒すでに存在するものを返すか、必要に応じて新しいものを作成します。 (私ShaderProgramはShaderProgramsの実際のソースコードのファイル名のハッシュを介してsを保存できます) だから今: …

2
コマンドにどれだけのロジックを入れることができますか?または別の言い方をすると、コマンドパターンはどのような種類のロジックですか?
私はかなり前からコマンドパターンを使用していますが、実際にExecuteメソッドにどれだけのロジックを入れることができるか本当にわかりません。 コマンドパターンの現在の実装は次のようになります。 public abstract class Command { public static event EventHandler Completed = delegate { }; public bool Success { get; private set; } public Exception Exception {get; private set; } public abstract bool Execute(); protected bool OnCompleted(bool success, Exception ex = null) { Success = success; Exception = ex; …

1
Nullオブジェクトパターンと入力検証-実際の実装をコピーするか、すべてを黙って受け入れますか?
私が持っているWifiComponent私にはCamera私のクライアントアプリケーションで。カメラのWifi関連の機能を処理します。Cameraは実際のカメラを表します。 これWifiComponentは、有効にすることができます(この場合、接続ステータスのチェックやスキャンなど、それを使って行うことができます)または無効にすることができます(この場合、有効かどうかを確認する以外は、何もできません)。 作成するときCamera、私の中のクライアントアプリケーションを、私はそのかどうかを尋ねるカメラWifiComponent有効になっています。次にWifiComponent、WifiComponentImplまたはの適切なサブクラスを作成しますNullWifiComponent。 supportedWifiTypes()およびwifiScan()メソッドの実装は簡単です。NullWifiComponent任意の種類をサポートしていない、すぐには結果をスキャンしないと発見して行われます。 しかし今、私はbool connect(WifiNetwork network, String password)メソッドを実装する必要があります。接続に失敗したと言いたいのですが...でWifiEncryptionType提供されているものもサポートしていませんWifiNetwork。実際の実装ではIllegalArgumentException、サポートされていないWifiEncryptionTypewifiネットワークを渡すとスローされます。 私は... リクエストをIllegalArgumentExceptionサポートしていないため、スローWifiEncryptionTypeしますか? return false何が提供されていても、接続に失敗します()。 一般的な質問: 実際の実装が契約を満たし、この契約の一部が特定の入力に対して例外をスローすることである場合、null実装はその中立性または契約を優先する必要がありますか?

2
アクセストークンを使用したAPIの設計、GETリクエストの処理方法
さまざまな部門間の使用状況を追跡したり、アクセス制御を行うために、アクセストークンを利用するAPIを構築しています。私の計画は、HTTP動詞を適切に利用することです- GET情報の取得、POST追加、DELETE削除などを行います。 私の質問は、GET呼び出しでアクセストークンをどのように処理する必要があるかです。 オプション1: クエリ文字列の一部としてアクセストークンを提供することです/api/users/?token=ACCESSTOKEN。これで私が抱えている問題は、ACCESSTOKENがサーバーログに表示されることです。このメソッドは、本文を介してトークンが渡されるPOSTまたはDELETEリクエストとも異なります。 オプション2: (POSTリクエストで行うように)リクエストに本文を指定します。パラメータの1つはトークンです。ここでの問題は、社内の他の開発者が、データを渡しているため、これは「真のGETリクエスト」ではないと言っていることです。彼らが呼び出すURLは単純にこのように/api/users/なりtoken=ACCESSTOKEN、本文内に提供されます。 オプション3: 使用GETを中止し、すべてをに強制しますPOST。これらのAPI呼び出しの多くでは、新しいリソースを作成していないため、このアイデアは好きではありません。私は単に、承認が必要なAPIの背後にあるデータを返すだけです。 私が見当たらない、または調整する必要があるオプションはありますか?私はオプション2が好きですが、他の部門の開発者の懸念に敏感です。

1
これはHaskellメイン関数の有効なデザインパターンですか?
いくつかのHaskellアプリケーションを開発した後、純粋でないコードと完全なコードから、不純なコードと失敗する可能性のある(部分)関数を厳密に分離していることに気付きました。これらの取り組みにより、アプリケーションに関連するメンテナンスコストが大幅に削減されました。私は、時間の経過とともに、この分離を実施するために同じ高レベルの構造に依存していることに気づきました。main 一般的に、私mainは次のような構造になります。 import System.Environment data ProgramParameters = P () data ComputationResult = I () main :: IO () main = getArgs -- Collect arguments >>= andOrGetUserInput -- Collect user input >>= impureOrFailableComputations -- Possible non-recoverable error(s) >>= either -- "Branch" putStrLn -- Print Any Failure(s) pureNotFailableComputations -- Finish the work …

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