一連の操作に最適なOOP設計パターン


11

私はアプリケーションに取り組んでおり、そのモジュールは次の財務操作を順番に実行します。

ユーザーが特定の金額を自分の銀行口座に送金するように要求した場合:

  1. トランザクションが発生するかどうかを確認しますか?(一定期間のみ取引可能)
  2. ユーザーが最小金額の引き出しを要求しているかどうかを確認します
  3. ユーザーがデフォルトのアカウントを持っているかどうかを確認します

上記のすべてのアクションの結果がログに記録されます。

上記の条件をすべて満たしている場合、トランザクションが実行されます。将来的には、いくつかのチェックが追加される可能性があります。

上記のケースに最適なオブジェクト指向のデザインパターンはどれですか。


3
問題を解決するために設計パターンを探すことはありません。設計パターンを使用して、正しいソリューションを伝えます。programmers.stackexchange.com/questions/70877/…SOLIDの原則に従ってください。
pdr

2
同意しません。パターンには、コミュニケーションを容易にする名前があり、ソリューションのコミュニケーションにも使用する必要があります。しかし、「問題を解決するための設計パターンを決して見ない」には同意しません。それらは特定の問題を解決するだけでなく、さまざまな力や制約にも対処します。「プロキシ」と「デコレータ」をご覧ください。それらは同じように見えますが、異なる問題を解決します。したがって、私の意見では、問題を自分で解決する前に、両方のメリットを享受するために、よく知られている設計パターン、問題を解決するための標準的なアプローチ、およびそれを伝達する簡単な方法を少なくとも確認する必要があります。
Jonny Dee

10
「パターンは、組織的なものからプログラミングのコンテキストまで、ソフトウェア開発中の特定の状況で繰り返し発生する問題に対して、実用的で具体的で適応可能なソリューションを提供します。」[POSA5、p。30]したがって、この観点から、パターンを適応可能なソリューションとして探すことは正当なアプローチであることは完全に明らかです。
ジョニーディー

3
昔ながらの手続き型プログラミングを説明するために、オブジェクト指向の構築を求めていますか?
mouviciel 2013

4
KISSの原則に従ってください。これまでのところ、問題は1つのメソッドの3つの「if」ステートメントで解決できます。クールにするためだけにデザインパターンを使用しないでください。追加のクラスを作成するたびに、常に考えます。本当に必要なのですか?
2013年

回答:


13

あなたが探しているのは責任の連鎖だと思います。この場合、次のクラスを使用できます。

  • TransactionValidatorBase 抽象基本クラス
  • TransactionTimeValidator
  • TransactionAmountValidator
  • TransactionAccountValidator

これはチェーンされて、指定した多くのルールが適用されます。

ファーター・リーディング


11
私の理解は、責任の連鎖はフィルターのようなものです-つまり、責任に対処する準備ができている人が見つかるまで連鎖をたどり、その「リンク」が責任を処理して終了します。CORの実際的な欠点の1つは、値を返すようにするのが難しいことです。
エイミーブランケンシップ2013年

Rの1レベルのチェーンを使用できると思います。少しの吸引で、チェーンから値を返すのは難しいことではないと思います。各レベルは、特定のプリミティブインターフェイスに準拠して通信する必要があり、そのような入力がプリミティブインターフェイスに準拠している場合、下からの入力を受け入れる必要があります。より密接に結合された2つのチェーンレベル間でインターフェイスの豊富さが必要な場合、それをサポートするために、抽象化をポリモーフィングすることができます。
Andyz Smith 2013

2

ここでの正しいパターンは、実際にはコンテキストによって異なります。固執する特定のパターンを選択する前に、それらの質問に対する答えを見つけようとします。

  • 実行時に(1,2,3)チェックのさまざまな組み合わせを作成する必要がありますか?
  • アクションを実行するために同じ変数が必要ですか、それとも大きく異なりますか?
  • エラーメッセージはどの程度正確でなければなりませんか?
  • 失敗した場合、ユーザーは常に(1)の最初のステップから再試行しますか?
  • 並行性はどのように処理されますか?
  • 各メソッドはリクエストに何かを追加しますか、それとも単に検証しますか?(デフォルトのアカウントIDと言いますか?)

直感に基づいて、エラーコードの集約パラメーターを持つプレーンメソッドとしてコーディングします。

public void DoTransaction(IErrorAgregator error, TransactionRequest request)
{
    if(!IsTransactionInCertainTimePeriod(request, error)) return;
    if(!IsTransactionAmountInUserBounds(request, error)) return;
    if(!UserHaveDefaultAccount(request, error)) return;
    bankingTransactor.PerformTransaction(request);
}

DoTransactionを "ITransactionValidationStragegy"インターフェイスに配置して、検証ボイラープレートコードを含むレイヤーのスーパータイプを作成することをお勧めします。

ただし、この設計では、検証ロジックはコンパイル時に決定されると想定しています。


1

@pswgによる回答で説明されているように、入力シーケンスを変更せずに、一連のステップが主に検証作業を行っている場合(それはあなたがそうであるように)、「責任のチェーン」パターンが実際にあると思います。

しかし、あなたの質問はもう少し一般的であるため、「パイプライン処理」も追加したいと思います。これにより、ステップは次のステップの入力になる出力を生成します(したがって、元の入力を変更します)。 。

これに関する2つの記事を次に示します
。Martin Fowlerによるパイプラインコレクション
パターンに関するより理論的な議論


0

ここではすでにパターンについて説明していますが、使用しているフレームワークに基づいて、アプリケーションでパターンをどのように使用するかを検討することをお勧めします。

たとえば、実行する検証は、ほとんどの場合、時間の経過とともに変化し続けます(将来、トランザクションを1日10に制限する新しい検証を追加する場合があります)。また、実際のビジネスサービスまたは統合コードが実行される前に検証を実行したくない場合もあります。検証を構成可能な検証として追加できるとよいでしょう。

Strutsを使用している場合は、インターセプターを使用することをお勧めします。春の場合、依存関係としての豆の注入により、柔軟性が向上します。私の提案は、パターン/イディオムだけでなく、アプリケーションを構築するために使用するフレームワークを見て、未来的な観点から要件にどのように最適に適合できるかを見ることです。


-2

私の理解によると、必要なものはすべて以下のようなコマンドパターンに組み込むことができます。クラスの設計は以下のように行うことができます。

interface Transaction{
void performAction();
}

class Banking{

void moneyValidation(){
//Validate Here
}

void timeValidation(){
//validate Here
}
}

class TimeValidation implements Transaction{

public Banking bank;

public TimeValidation (Banking bnk){
bank=bnk;
}

void performAction(){
bnk.timeValidation();
}


class MoneyValidation Implements Transaction{

public Banking bank;

public MoneyValidation(Banking bnk;){
bank=bnk;
}

void performAction(){
bnk.moneyValidation();
}
}


class Control{

private List val_list=new ArrayList();

void storeValidation(Transaction trans){
val_list.add(trans);
trans.performAction(val_list.getFirstAndRemove());
}
}

//Same for other validation classes

クライアントクラスには、次のコードスニペットが含まれます。

Banking bnk = new Banking();
MoneyValidation m_val = new MoneyValidation (bnk);
TimeValidation t_val = new TimeValidation (bnk);
Control ctrl = new Control();
ctrl.storeValidation(m_val);
ctrl.storeValidation(t_val);

これは私の理解によると、上記のシナリオで。


お金の検証が失敗した場合、時間の検証は役に立たないのでそれは悪いですが、それはとにかく行われます
Ewoks
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.