Saya membaca Objek PHP, Pola, dan Praktek . Penulis sedang mencoba membuat model pelajaran di sebuah perguruan tinggi. Tujuannya adalah untuk menghasilkan jenis pelajaran (kuliah atau seminar), dan biaya untuk pelajaran tergantung pada apakah itu pelajaran harga per jam atau tetap. Jadi hasilnya seharusnya
Lesson charge 20. Charge type: hourly rate. Lesson type: seminar.
Lesson charge 30. Charge type: fixed rate. Lesson type: lecture.
ketika inputnya adalah sebagai berikut:
$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');
Saya menulis ini:
class Lesson {
private $chargeType;
private $duration;
private $lessonType;
public function __construct($chargeType, $duration, $lessonType) {
$this->chargeType = $chargeType;
$this->duration = $duration;
$this->lessonType = $lessonType;
}
public function getChargeType() {
return $this->getChargeType;
}
public function getLessonType() {
return $this->getLessonType;
}
public function cost() {
if($this->chargeType == 'fixed rate') {
return "30";
} else {
return $this->duration * 5;
}
}
}
$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');
foreach($lessons as $lesson) {
print "Lesson charge {$lesson->cost()}.";
print " Charge type: {$lesson->getChargeType()}.";
print " Lesson type: {$lesson->getLessonType()}.";
print "<br />";
}
Tetapi menurut buku itu, saya salah (saya cukup yakin saya juga). Sebagai gantinya, penulis memberikan hierarki kelas yang besar sebagai solusinya. Dalam bab sebelumnya, penulis menyatakan 'empat rambu-rambu' sebagai waktu ketika saya harus mempertimbangkan untuk mengubah struktur kelas saya:
- Duplikasi kode
- Kelas yang tahu terlalu banyak tentang konteksnya
- The jack semua perdagangan - kelas yang mencoba untuk melakukan banyak hal
- Pernyataan bersyarat
Satu-satunya masalah yang bisa saya lihat adalah pernyataan kondisional, dan itu juga secara samar-samar - jadi mengapa refactor ini? Menurut Anda, masalah apa yang mungkin muncul di masa depan yang belum saya ramalkan?
Pembaruan : Saya lupa menyebutkan - ini adalah struktur kelas yang penulis berikan sebagai solusi - pola strategi :
sumber
Jawaban:
Lucu bahwa buku itu tidak menyatakannya dengan jelas, tetapi alasan mengapa buku ini menyukai hierarki kelas jika pernyataan di dalam kelas yang sama mungkin adalah prinsip Terbuka / Tertutup Aturan desain perangkat lunak yang terkenal ini menyatakan bahwa kelas harus ditutup untuk modifikasi tetapi terbuka untuk ekstensi.
Dalam contoh Anda, menambahkan jenis pelajaran baru berarti mengubah kode sumber kelas Pelajaran, menjadikannya rapuh dan rentan mengalami regresi. Jika Anda memiliki kelas dasar dan satu turunan untuk setiap jenis pelajaran, Anda hanya perlu menambahkan subkelas lain, yang umumnya dianggap lebih bersih.
Anda dapat meletakkan aturan itu di bawah bagian "Pernyataan Bersyarat" jika Anda mau, namun saya menganggap bahwa "rambu" agak kabur. Jika pernyataan pada umumnya hanya kode bau, gejala. Mereka dapat dihasilkan dari berbagai macam keputusan desain yang buruk.
sumber
Saya kira apa yang ingin diajarkan buku ini adalah untuk menghindari hal-hal seperti:
Interpretasi saya terhadap buku ini adalah Anda harus memiliki tiga kelas:
Anda kemudian harus mengimplementasikan kembali
cost
fungsi pada kedua subkelas.Pendapat pribadi saya
untuk kasus sederhana seperti itu: jangan. Aneh bahwa buku Anda mendukung hierarki kelas yang lebih dalam untuk menghindari pernyataan kondisional yang sederhana. Terlebih lagi, dengan spesifikasi input Anda,
Lesson
harus menjadi pabrik dengan pengiriman yang merupakan pernyataan bersyarat. Maka dengan solusi buku Anda akan memiliki:Itu lebih rumit tanpa manfaat tambahan.
sumber
SemesterLesson
,MasterOneWeekLesson
, dll Sebuah kelas akar abstrak, atau lebih baik lagi interface, pasti cara untuk pergi kemudian. Tetapi ketika Anda hanya memiliki dua kasus, itu tergantung pada kebijaksanaan penulis.Contoh dalam buku ini sangat aneh. Dari pertanyaan Anda, pernyataan aslinya adalah:
yang, dalam konteks bab tentang OOP, akan berarti bahwa penulis mungkin ingin Anda memiliki struktur berikut:
Tapi kemudian muncul input yang Anda kutip:
yaitu sesuatu yang disebut kode yang diketik secara ketat , dan yang, jujur, dalam konteks ini ketika pembaca dimaksudkan untuk belajar OOP, mengerikan.
Ini juga berarti bahwa jika saya benar tentang maksud dari penulis buku (yaitu membuat kelas-kelas abstrak dan diwariskan yang saya sebutkan di atas), ini akan menyebabkan kode duplikat dan sangat tidak dapat dibaca dan jelek:
Adapun "rambu-rambu":
Duplikasi Kode
Kode Anda tidak memiliki duplikasi. Kode yang penulis harapkan agar Anda tulis.
Kelas Yang Tahu Terlalu Banyak Tentang Konteksnya
Kelas Anda hanya meneruskan string dari input ke output, dan tidak tahu apa-apa. Kode yang diharapkan di sisi lain dapat dikritik karena tahu terlalu banyak.
Jack of All Trades - Kelas yang mencoba melakukan banyak hal
Sekali lagi, Anda hanya melewati string, tidak lebih.
Pernyataan bersyarat
Ada satu pernyataan kondisional dalam kode Anda. Itu mudah dibaca dan mudah dimengerti.
Mungkin, pada kenyataannya, penulis mengharapkan Anda untuk menulis kode yang jauh lebih refactored daripada yang dengan enam kelas di atas. Misalnya Anda dapat menggunakan pola pabrik untuk pelajaran dan biaya, dll.
Dalam hal ini, Anda akan mendapatkan sembilan kelas, yang akan menjadi contoh sempurna arsitektur berlebih .
Alih-alih, Anda berakhir dengan kode yang mudah dipahami dan bersih, yang sepuluh kali lebih pendek.
sumber
Pertama-tama Anda dapat mengubah "angka ajaib" seperti 30 dan 5 dalam fungsi cost () menjadi variabel yang lebih bermakna :)
Dan jujur saja, saya pikir Anda tidak perlu khawatir tentang ini. Ketika Anda perlu mengubah kelas maka Anda akan mengubahnya. Cobalah untuk menciptakan nilai terlebih dahulu kemudian beralih ke refactorization.
Dan mengapa Anda berpikir bahwa Anda salah? Bukankah kelas ini "cukup baik" untukmu? Mengapa Anda khawatir tentang buku;)
sumber
Sama sekali tidak perlu menerapkan kelas tambahan apa pun. Anda memiliki sedikit
MAGIC_NUMBER
masalah dalamcost()
fungsi Anda , tetapi hanya itu. Yang lainnya adalah over-engineering besar-besaran. Namun, sayangnya itu umum untuk saran yang sangat buruk diberikan- Circle mewarisi Shape, misalnya. Jelas tidak efisien untuk menurunkan kelas untuk warisan sederhana dari satu fungsi. Anda bisa menggunakan pendekatan fungsional sebagai gantinya.sumber