ほとんどの場合、特定の関数呼び出しの応答を処理するコードを書いているとき、次のコード構造が得られます。
例:これはログインシステムの認証を処理する関数です
class Authentication{
function login(){ //This function is called from my Controller
$result=$this->authenticate($username,$password);
if($result=='wrong password'){
//increase the login trials counter
//send mail to admin
//store visitor ip
}else if($result=='wrong username'){
//increase the login trials counter
//do other stuff
}else if($result=='login trials exceeded')
//do some stuff
}else if($result=='banned ip'){
//do some stuff
}else if...
function authenticate($username,$password){
//authenticate the user locally or remotely and return an error code in case a login in fails.
}
}
問題
- ご覧のとおり、コードは
if/else
構造に基づいて構築されています。つまり、新しい障害ステータスはelse if
、Open Closed Principleに違反するステートメントを追加する必要があることを意味します。 - 1つのハンドラーでログイントライアルカウンターを増やすだけで、別のハンドラーではより深刻な処理を行うため、関数の抽象化レイヤーが異なるように感じます。
increase the login trials
たとえば、一部の機能が繰り返されています。
複数if/else
をファクトリパターンに変換することを考えましたが、動作を変更せずにオブジェクトを作成するためにのみファクトリを使用しました。誰かがこれのためのより良い解決策を持っていますか?
注意:
これはログインシステムを使用した例にすぎません。十分に構築されたOOパターンを使用して、この動作に対する一般的な解決策を求めています。この種のif/else
ハンドラーはコードの非常に多くの場所に表示されており、単純に説明しやすい例としてログインシステムを使用しました。私の実際の使用例はここに投稿するのが非常に複雑です。:D
PHPコードへの回答を制限せず、希望する言語を自由に使用してください。
更新
私の質問を明確にするための別のより複雑なコード例:
public function refundAcceptedDisputes() {
$this->getRequestedEbayOrdersFromDB(); //get all disputes requested on ebay
foreach ($this->orders as $order) { /* $order is a Doctrine Entity */
try {
if ($this->isDisputeAccepted($order)) { //returns true if dispute was accepted
$order->setStatus('accepted');
$order->refund(); //refunds the order on ebay and internally in my system
$this->insertRecordInOrderHistoryTable($order,'refunded');
} else if ($this->isDisputeCancelled($order)) { //returns true if dispute was cancelled
$order->setStatus('cancelled');
$this->insertRecordInOrderHistory($order,'cancelled');
$order->rollBackRefund(); //cancels the refund on ebay and internally in my system
} else if ($this->isDisputeOlderThan7Days($order)) { //returns true if 7 days elapsed since the dispute was opened
$order->closeDispute(); //closes the dispute on ebay
$this->insertRecordInOrderHistoryTable($order,'refunded');
$order->refund(); //refunds the order on ebay and internally in my system
}
} catch (Exception $e) {
$order->setStatus('failed');
$order->setErrorMessage($e->getMessage());
$this->addLog();//log error
}
$order->setUpdatedAt(time());
$order->save();
}
}
機能目的:
- 私はebayでゲームを販売しています。
- 顧客が彼の注文のキャンセルを希望し、彼の返金(つまり、払い戻し)を希望する場合、最初にebayで「紛争」を開かなければなりません。
- 異議申し立てが開始されたら、お客様が払い戻しに同意することをお客様が確認するのを待つ必要があります(返金するように私に言ったのは愚かですが、それがebayでの動作です)。
- この機能は、私がすべての紛争を解決し、そのステータスを定期的にチェックして、顧客が紛争に返信したかどうかを確認します。
- お客様は同意する(払い戻しする)か拒否する(その後ロールバックする)か、7日間応答しない場合があります(異議申し立てを閉じてから払い戻します)。
getOrderStrategy
を返すファクトリメソッドですstrategy
が、preProcess()
およびpreProcess()
関数は何ですか。また、なぜあなたはパス$this
しましたupdateOrderHistory($this)
か?