Gambar ini diambil dari Menerapkan Desain dan Pola Berbasis Domain: Dengan Contoh di C # dan .NET
Ini adalah diagram kelas untuk Pola Negara di mana a SalesOrder
dapat memiliki status yang berbeda selama masa pakainya. Hanya transisi tertentu yang diizinkan antara negara yang berbeda.
Sekarang OrderState
kelas adalah abstract
kelas dan semua metodenya diwarisi ke subclass-nya. Jika kita menganggap subclass Cancelled
yang merupakan keadaan akhir yang tidak memungkinkan transisi ke negara lain, kita harus override
semua metode di kelas ini untuk membuang pengecualian.
Sekarang, bukankah itu melanggar prinsip substitusi Liskov karena seorang sublcass seharusnya tidak mengubah perilaku orang tua? Apakah mengubah kelas abstrak menjadi antarmuka memperbaiki ini?
Bagaimana ini bisa diperbaiki?
cancel()
mengubah status untuk dibatalkan.Jawaban:
Implementasi khusus ini, ya. Jika Anda membuat kelas konkret daripada implementor abstrak maka Anda akan lolos dari ini.
Namun pola keadaan yang Anda maksudkan yang secara efektif adalah desain mesin negara pada umumnya adalah sesuatu yang tidak saya setujui dari cara saya melihatnya tumbuh. Saya pikir ada cukup alasan untuk mengutuk ini sebagai pelanggaran prinsip tanggung jawab tunggal karena pola manajemen negara ini akhirnya menjadi repositori sentral untuk pengetahuan tentang keadaan terkini dari banyak bagian lain dari suatu sistem. Bagian manajemen negara ini yang tersentralisasi akan lebih sering membutuhkan aturan bisnis yang relevan dengan banyak bagian sistem yang berbeda untuk mengoordinasikannya secara wajar.
Bayangkan jika semua bagian sistem yang peduli tentang negara berada dalam layanan yang berbeda, proses berbeda pada mesin yang berbeda, manajer status pusat yang merinci status untuk masing-masing tempat secara efektif menghambat semua sistem terdistribusi ini dan saya pikir bottleneck adalah tanda pelanggaran SRP serta desain yang umumnya buruk.
Sebaliknya, saya akan menyarankan seseorang membuat objek lebih cerdas seperti pada objek Model dalam pola MVC di mana model tahu bagaimana menangani sendiri, tidak perlu orkestra luar untuk mengelola cara kerjanya atau alasannya.
Bahkan menempatkan pola keadaan seperti ini di dalam objek sehingga hanya mengelola sendiri, rasanya seperti Anda akan membuat objek itu terlalu besar. Alur kerja harus dilakukan melalui komposisi berbagai objek yang bertanggung jawab sendiri, saya katakan, alih-alih dengan satu pengaturan yang mengatur aliran objek lain, atau aliran kecerdasan dalam dirinya sendiri.
Tetapi pada titik itu lebih merupakan seni daripada teknik dan karenanya sangat subyektif pendekatan Anda untuk beberapa hal, yang mengatakan prinsip-prinsipnya adalah panduan yang baik dan ya implementasi yang Anda daftarkan adalah pelanggaran LSP, tetapi bisa diperbaiki untuk tidak dilakukan. Berhati-hatilah dengan SRP saat menggunakan pola apa pun ini dan Anda cenderung aman.
sumber
Itu salah interpretasi umum dari LSP. Subkelas dapat mengubah perilaku induk, asalkan tetap benar untuk tipe induk.
Ada penjelasan panjang yang baik di Wikipedia , menyarankan hal-hal yang akan melanggar LSP:
Secara pribadi, saya merasa lebih mudah untuk mengingat ini: Jika saya melihat parameter dalam metode yang memiliki tipe A, akankah seseorang yang melewati subtipe B membuat saya terkejut? Jika mereka mau maka ada pelanggaran terhadap LSP.
Apakah melempar Eksepsi merupakan kejutan? Tidak juga. Itu adalah sesuatu yang dapat terjadi kapan saja, apakah saya memanggil metode Kapal di OrderState atau Diberikan atau Dikirimkan. Jadi saya harus menjelaskannya dan itu bukan pelanggaran LSP.
Yang mengatakan , saya pikir ada cara yang lebih baik untuk menangani situasi ini. Jika saya menulis ini dalam C #, saya akan menggunakan antarmuka dan memeriksa implementasi antarmuka sebelum memanggil metode. Misalnya, jika OrderState saat ini tidak mengimplementasikan IShippable, jangan panggil metode Kirim di atasnya.
Tetapi kemudian saya juga tidak akan menggunakan pola Negara untuk situasi khusus ini. Pola keadaan jauh lebih tepat untuk keadaan aplikasi daripada keadaan objek domain seperti ini.
Jadi, singkatnya, ini adalah contoh yang buruk dari Pola Negara dan bukan cara yang sangat baik untuk menangani keadaan suatu pesanan. Tapi itu bisa dibilang tidak melanggar LSP. Dan pola Negara, dalam dan dari dirinya sendiri, tentu saja tidak.
sumber
CircleWithFixedCenterButMutableRadius
sebagai kemungkinan pelanggaran LSP jika kontrak konsumen untukImmutablePoint
menetapkan bahwa jikaX.equals(Y)
, konsumen dapat dengan bebas mengganti X untuk Y, dan sebaliknya, dan dengan demikian harus menahan diri dari menggunakan kelas sedemikian rupa sehingga substitusi tersebut akan menyebabkan masalah. Jenis ini mungkin dapat mendefinisikan secara sahequals
sehingga semua contoh akan dibandingkan sebagai berbeda, tetapi perilaku tersebut kemungkinan akan membatasi kegunaannya.(Ini ditulis dari sudut pandang C #, jadi tidak ada pengecualian yang diperiksa.)
Menurut artikel Wikipedia tentang LSP , salah satu syarat LSP adalah:
Bagaimana Anda memahaminya? Apa sebenarnya “pengecualian yang dilemparkan oleh metode supertipe” ketika metode supertipe itu abstrak? Saya pikir itu adalah pengecualian yang didokumentasikan sebagai pengecualian yang dapat dilemparkan oleh metode supertype.
Apakah ini berarti bahwa jika
OrderState.Ship()
didokumentasikan sebagai sesuatu seperti "melemparInvalidOperationException
jika operasi ini tidak didukung oleh keadaan saat ini", maka saya pikir desain ini tidak merusak LSP. Di sisi lain, jika metode supertype tidak didokumentasikan dengan cara ini, LSP dilanggar.Tapi ini tidak berarti ini adalah desain yang baik, Anda tidak boleh menggunakan pengecualian untuk aliran kontrol normal, yang sepertinya sangat dekat. Juga, dalam aplikasi nyata, Anda mungkin ingin tahu apakah suatu operasi dapat dilakukan sebelum Anda mencoba melakukannya, misalnya untuk menonaktifkan tombol "Kirim" di UI.
sumber