Sebagian besar waktu ketika saya sedang menulis beberapa kode yang menangani respons untuk panggilan fungsi tertentu saya mendapatkan struktur kode berikut:
contoh: Ini adalah fungsi yang akan menangani otentikasi untuk sistem login
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.
}
}
Masalah
- Seperti yang Anda lihat, kode tersebut dibuat berdasarkan
if/else
struktur yang berarti status kegagalan baru akan berarti bahwa saya perlu menambahkanelse if
pernyataan yang merupakan pelanggaran terhadap Prinsip Terbuka Terbuka . - Saya merasa bahwa fungsi ini memiliki lapisan abstraksi yang berbeda karena saya hanya dapat meningkatkan penghitung percobaan masuk di satu handler, tetapi melakukan hal-hal yang lebih serius di yang lain.
- Beberapa fungsi diulang
increase the login trials
misalnya.
Saya berpikir untuk mengubah banyak if/else
ke pola pabrik, tapi saya hanya menggunakan pabrik untuk membuat objek tidak mengubah perilaku. Adakah yang punya solusi yang lebih baik untuk ini?
catatan:
Ini hanya contoh menggunakan sistem login. Saya meminta solusi umum untuk perilaku ini menggunakan pola OO yang dibangun dengan baik. Semacam ini if/else
penangan muncul di terlalu banyak tempat di kode saya dan saya hanya menggunakan sistem login sebagai sederhana mudah untuk menjelaskan contoh. Kasing asli saya sangat rumit untuk dikirim di sini. : D
Tolong jangan membatasi jawaban Anda ke kode PHP dan jangan ragu untuk menggunakan bahasa yang Anda inginkan.
MEMPERBARUI
Contoh kode lain yang lebih rumit hanya untuk memperjelas pertanyaan saya:
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();
}
}
tujuan fungsi:
- Saya menjual game di ebay.
- Jika seorang pelanggan ingin membatalkan pesanannya dan mendapatkan kembali uangnya (yaitu Pengembalian Uang), saya harus membuka "Perselisihan" di ebay terlebih dahulu.
- Setelah perselisihan dibuka, saya harus menunggu pelanggan untuk mengkonfirmasi bahwa dia setuju untuk pengembalian dana (konyol karena dia orang yang mengatakan kepada saya untuk mengembalikan uang, tetapi begitulah cara kerjanya di ebay).
- Fungsi ini membuat semua sengketa dibuka oleh saya dan memeriksa status mereka secara berkala untuk melihat apakah pelanggan telah menjawab perselisihan atau tidak.
- Pelanggan dapat menyetujui (lalu saya mengembalikan) atau menolak (kemudian saya kembalikan) atau mungkin tidak menanggapi selama 7 hari (saya menutup sendiri perselisihan lalu mengembalikan uang).
getOrderStrategy
adalah metode pabrik yang mengembalikanstrategy
objek tergantung pada status pesanan, tetapi apa sajapreProcess()
danpreProcess()
fungsinya. Juga mengapa Anda lulus$this
keupdateOrderHistory($this)
?Pola strategi adalah saran yang baik jika Anda benar-benar ingin mendesentralisasikan logika Anda, tetapi sepertinya tipuan berlebihan untuk contoh sekecil milik Anda. Secara pribadi, saya akan menggunakan pola "tulis fungsi yang lebih kecil", seperti:
sumber
Ketika Anda mulai memiliki banyak pernyataan if / then / else untuk menangani status, pertimbangkan Pola Negara .
Ada pertanyaan tentang cara tertentu untuk menggunakannya: Apakah penerapan pola negara ini masuk akal?
Saya baru mengenal derai ini, tetapi saya tetap memberikan jawaban untuk memastikan saya mengerti kapan harus menggunakannya (Hindari "semua masalah terlihat seperti paku pada palu.").
sumber
Seperti yang saya katakan di komentar saya, logika kompleks tidak benar-benar mengubah apa pun.
Anda ingin memproses pesanan yang disengketakan. Ada banyak cara untuk melakukan itu. Jenis pesanan yang disengketakan dapat
Enum
:Ada banyak cara untuk melakukan ini. Anda dapat memiliki hirarki warisan dari
Order
,DisputedOrder
,DisputedOrderLessThan7Days
,DisputedOrderCanceled
, dll Hal ini tidak baik, tetapi juga akan bekerja.Dalam contoh saya di atas saya melihat jenis pesanan dan mendapatkan strategi yang relevan untuk itu. Anda bisa merangkum proses itu menjadi sebuah pabrik:
Ini akan melihat jenis pesanan dan memberi Anda strategi yang benar untuk jenis pesanan itu.
Anda mungkin berakhir dengan sesuatu di baris:
Jawaban Asli, tidak lagi relevan karena saya pikir Anda mencari sesuatu yang lebih sederhana:
Saya melihat kekhawatiran berikut di sini:
Saya akan melakukan hal berikut:
Saat ini teladan Anda memiliki terlalu banyak tanggung jawab. Yang saya lakukan, adalah merangkum tanggung jawab itu dalam metode. Kode terlihat lebih bersih dan Anda tidak memiliki pernyataan kondisi di mana-mana.
Pabrik merangkum konstruksi benda. Anda tidak perlu merangkum konstruksi apa pun dalam contoh Anda, yang perlu Anda lakukan adalah memisahkan kekhawatiran Anda.
sumber