Son zamanlarda içinde bazı büyük Liskov ihlal edenlerin bulunduğu bir kod temeli miras aldım. Önemli sınıflarda. Bu bana çok fazla acı verdi. Nedenini açıklamama izin ver.
Ben Class A
, türetilen var Class B
. Class A
ve kendi uygulamasıyla geçersiz kılan Class B
bir dizi mülkü paylaşın Class A
. Bir Class A
mülkün ayarlanması veya elde edilmesi, aynı mülkün ayarlanması veya elde edilmesi üzerinde farklı bir etkiye sahiptir 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();
}
}
}
Bunun .NET'te çeviri yapmak için tamamen berbat bir yol olduğu gerçeğini bir kenara bırakmak gerekirse, bu kodla ilgili başka birçok sorun var.
Bu durumda Name
, birçok yerde bir indeks ve bir akış kontrol değişkeni olarak kullanılır. Yukarıdaki sınıflar, kod tabanı boyunca hem ham hem de türetilmiş formları ile doldurulur. Bu durumda Liskov ikame ilkesini ihlal etmek, temel sınıfı alan işlevlerin her birine yapılan her bir çağrının içeriğini bilmem gerektiği anlamına gelir.
Kod her ikisinin nesnelerini kullanır Class A
ve Class B
bu yüzden Class A
insanları kullanmaya zorlamak için soyut yapamam Class B
.
Üzerinde çalışan bazı çok faydalı yardımcı işlevler Class A
ve üzerinde çalışan diğer çok yararlı yardımcı işlevler vardır Class B
. İdeal olarak, Class A
üzerinde çalışabilecek herhangi bir yardımcı işlevi kullanabilmek istiyorum Class B
. LSP'nin ihlali için olmasaydı, Class B
bir çok fonksiyonu alan bir şeyi kolayca alabilirdi Class A
.
Bununla ilgili en kötü şey, bu uygulamanın bu iki sınıfa dayandığı, her zaman her iki derste de çalıştığı ve yüzlerce şekilde bozulacağı için (ki bunu yapacağım) kırmak için gerçekten zor bir durum. Neyse).
Bunu düzeltmek için yapmam gereken , mülkün sürümü NameTranslated
olacak bir mülk oluşturmak ve yeni mülkümü kullanmak için türetilmiş mülke yapılan tüm referansları çok, çok dikkatli bir şekilde değiştiriyorum . Bununla birlikte, bu referanslardan bir tanesinin yanlış yapılması bile tüm başvuru patlayabilir.Class B
Name
Name
NameTranslated
Kod tabanının çevresinde birim testlerinin bulunmadığı göz önüne alındığında, bu, geliştiricinin karşılaşabileceği en tehlikeli senaryo olmaya oldukça yakın. İhlali değiştirmezsem, her yöntemde ne tür bir nesnenin kullanıldığını takip ederek büyük miktarda zihinsel enerji harcamam gerekir ve ihlali giderirsem ürünün tamamını uygun olmayan bir zamanda patlatabilirim.