Sık sık karşılaştığım bir sorun var: Ürün sınıfı olan bir web mağazası projesi olsun. Kullanıcıların bir ürüne yorum göndermesine olanak tanıyan bir özellik eklemek istiyorum. Bu yüzden bir ürünü referans alan bir Review sınıfım var. Şimdi bir ürün için tüm değerlendirmeleri listeleyen bir yönteme ihtiyacım var. İki olasılık vardır:
(A)
public class Product {
...
public Collection<Review> getReviews() {...}
}
(B)
public class Review {
...
static public Collection<Review> forProduct( Product product ) {...}
}
Koda bakarak, (A) seçerim: Statik değildir ve bir parametreye ihtiyaç duymaz. Ancak, (A) 'nın Tek Sorumluluk İlkesini (SRP) ve Açık-Kapalı İlkesini (OCP) ihlal ettiğini;
(SRP) Bir ürün için incelemelerin toplanma şeklini değiştirmek istediğimde, Ürün sınıfını değiştirmem gerekiyor. Ancak Ürün sınıfını değiştirmenin tek bir nedeni olmalı. Ve bu kesinlikle değerlendirme değil. Ürün'teki ürünlerle ilgili her özelliği paketlersem, yakında işlenecektir.
(OCP) Bu özellik ile genişletmek için Product sınıfını değiştirmem gerekiyor. Bence bu ilkenin 'Değişim için kapalı' kısmını ihlal ediyor. Müşterinin yorumları uygulamak için isteğini almadan önce, Ürünü bitmiş olarak kabul ettim ve "kapattım".
Daha da önemlisi: SOLID ilkelerini takip etmek veya daha basit bir arayüze sahip olmak?
Yoksa burada yanlış bir şey mi yapıyorum?
Sonuç
Vay, tüm harika cevapların için teşekkürler! Resmi cevap olarak birini seçmek zor.
Cevaplardan ana argümanları özetleyeyim:
- pro (A): OCP, yasaların da okunabilirliği ve yasa değildir.
- pro (A): varlık ilişkisi gezilebilir olmalıdır. Her iki sınıf da bu ilişkiyi bilebilir.
- pro (A) + (B): her ikisini de yapın ve (A) ila (B) arasında temsilci seçin, böylece Ürünün tekrar değiştirilmesi daha az olasıdır.
- pro (C): bulucu yöntemlerini statik olmadığı üçüncü sınıfa (hizmet) koyun.
- kontra (B): testlerde alay etmeyi engeller.
İş hayatındaki kolejlerimin katkıda bulunduğu birkaç şey daha:
- pro (B): ORM çerçevemiz otomatik olarak (B) kodunu oluşturabilir.
- pro (A): ORM çerçevemizin teknik nedenlerinden ötürü, bazı durumlarda "kapalı" varlığı, bulucunun gittiği yerden bağımsız olarak değiştirmek gerekecektir. Bu yüzden her zaman SOLID'e bağlı kalamam.
- kontra (C): çok karışıklık ;-)
Sonuç
Mevcut projem için delegasyonla her iki (A) + (B) kullanıyorum. Ancak hizmet odaklı bir ortamda (C) ile devam edeceğim.
Assert(5 = Math.Abs(-5));
Abs()
etmek sorun değil, ona bağlı bir şeyi test etmek. Bir sahte kullanmak için Bağımlı Test Altında Kodunu (CUT) izole etmek için bir dikişiniz yok. Bu, onu bir atom birimi olarak test edemeyeceğiniz anlamına gelir ve tüm testleriniz, birim mantığını test eden entegrasyon testleri haline gelir. Bir testteki başarısızlık CUT'ta veya Abs()
(veya bağımlı kodunda) olabilir ve birim testlerin teşhis faydalarını ortadan kaldırır.