Saya mewarisi basis kode baru-baru ini yang memiliki beberapa pelanggar Liskov besar di dalamnya. Di kelas-kelas penting. Ini telah menyebabkan saya sangat sakit. Biarkan saya jelaskan alasannya.
Saya punya Class A
, yang berasal dari Class B
. Class A
dan Class B
berbagi banyak properti yang Class A
menimpa dengan implementasinya sendiri. Pengaturan atau mendapatkan Class A
properti memiliki efek berbeda untuk pengaturan atau mendapatkan properti yang sama persis dari Class B
.
public Class A
{
public virtual string Name
{
get; set;
}
}
Class B : A
{
public override string Name
{
get
{
return TranslateName(base.Name);
}
set
{
base.Name = value;
FunctionWithSideEffects();
}
}
}
Mengesampingkan fakta bahwa ini adalah cara yang benar-benar mengerikan untuk melakukan terjemahan dalam .NET, ada sejumlah masalah lain dengan kode ini.
Dalam hal Name
ini digunakan sebagai indeks dan variabel kontrol aliran di sejumlah tempat. Kelas-kelas di atas berserakan di seluruh basis kode dalam bentuk mentah dan turunannya. Melanggar prinsip substitusi Liskov dalam hal ini berarti bahwa saya perlu mengetahui konteks setiap panggilan tunggal ke masing-masing fungsi yang mengambil kelas dasar.
Kode menggunakan objek keduanya Class A
dan Class B
, jadi saya tidak bisa membuat Class A
abstrak untuk memaksa orang untuk menggunakan Class B
.
Ada beberapa fungsi utilitas yang sangat berguna yang beroperasi Class A
dan fungsi utilitas lain yang sangat berguna yang beroperasi Class B
. Idealnya saya ingin dapat menggunakan fungsi utilitas yang dapat beroperasi pada Class A
pada Class B
. Banyak fungsi yang mengambil a Class B
bisa dengan mudah diambil Class A
jika bukan karena pelanggaran LSP.
Hal terburuk tentang ini adalah bahwa kasus khusus ini sangat sulit untuk diperbaiki karena seluruh aplikasi bergantung pada dua kelas ini, beroperasi pada kedua kelas setiap saat dan akan pecah dalam ratusan cara jika saya mengubah ini (yang akan saya lakukan bagaimanapun).
Apa yang harus saya lakukan untuk memperbaikinya adalah membuat NameTranslated
properti, yang akan menjadi Class B
versi Name
properti dan sangat, sangat hati-hati mengubah setiap referensi ke Name
properti yang diturunkan untuk menggunakan NameTranslated
properti baru saya . Namun, jika salah satu dari referensi ini salah, seluruh aplikasi bisa meledak.
Mengingat basis kode tidak memiliki unit test di sekitarnya, ini hampir menjadi skenario paling berbahaya yang bisa dihadapi pengembang. Jika saya tidak mengubah pelanggaran, saya harus menghabiskan banyak energi mental untuk melacak jenis objek apa yang sedang dioperasikan pada setiap metode dan jika saya memperbaiki pelanggaran, saya bisa membuat seluruh produk meledak pada waktu yang tidak tepat.