Sadece bir sistemin karmaşık olması, onu karmaşık hale getirmeniz gerektiği anlamına gelmez . Bunun gibi çok fazla bağımlılığa (veya Ortak çalışanlara) sahip bir sınıfınız varsa:
public class MyAwesomeClass {
public class MyAwesomeClass(IDependency1 _d1, IDependency2 _d2, ... , IDependency20 _d20) {
// Assign it all
}
}
... o zaman çok karmaşık hale geldi ve gerçekten SRP'yi izlemiyorsun , değil mi? Bahse girerim MyAwesomeClass
, bir CRC kartında bir indeks kartına sığmayacak ne yazdığını ya da gerçekten okunaksız küçük harflerle yazmak zorunda kaldığınızı söylersiniz.
Burada sahip olduğun şey, adamlarının yerine Arayüz Ayrıştırma İlkesini takip etmeleriydi ve onu aşırı uç noktaya götürmüş olabilirdi, ama bu başka bir hikaye. Bağımlılıkların etki alanı nesneleri olduğunu söyleyebiliriz (ki bu da), ancak aynı zamanda 20 etki alanı nesnesini işleyen bir sınıfa sahip olmak onu biraz fazla uzatıyor.
TDD size bir sınıfın ne kadarının yapıldığının iyi bir göstergesi olacaktır. Açıkça koymak; Bir test yönteminin yazması sonsuza kadar sürecek bir kurulum koduna sahipse (testleri yeniden yerleştirseniz bile) MyAwesomeClass
muhtemelen yapacak çok şeyiniz olur.
Peki bu bilmeceyi nasıl çözersiniz? Sorumlulukları diğer sınıflara taşırsınız. Bu sorunu olan bir sınıfa atabileceğiniz bazı adımlar vardır:
- Sınıfınızın bağımlılıklarıyla yaptığı tüm eylemleri (veya sorumlulukları) tanımlayın.
- Eylemleri yakından ilişkili bağımlılıklara göre gruplayın.
- Redelegate! Yani, tanımlanmış eylemlerin her birini yeni sınıflara (veya daha önemlisi) başka sınıflara yönlendirmek.
Sorumlulukların yeniden düzenlenmesi üzerine soyut bir örnek
Let C
birkaç bağımlılıkları olan bir sınıf olmak D1
, D2
, D3
, D4
daha az kullanmak gözden geçirmeniz gerekebilir söyledi. C
Bağımlılıkları hangi yöntemlerle çağıracağımızı belirlediğimizde, bunun basit bir listesini yapabiliriz:
D1
- performA(D2)
,performB()
D2
- performD(D1)
D3
- performE()
D4
- performF(D3)
Listeye baktığımızda bunu görebiliriz D1
ve D2
sınıf bir şekilde birlikte ihtiyaç duydukları için birbirleriyle ilişkilidir. Bu D4
ihtiyaçları da görebiliriz D3
. Yani iki grubumuz var:
Group 1
- D1
<->D2
Group 2
- D4
->D3
Gruplamalar, sınıfın şimdi iki sorumluluğu olduğunun göstergesidir.
Group 1
- Biri birbirine ihtiyaç duyan çağıran iki nesneyi kullanmak için. Belki de sınıfınızın C
her iki bağımlılığı da kullanma ihtiyacını ortadan kaldırabilir ve bunun yerine bu aramaları yapmalarından birini bırakabilirsiniz. Bu gruplandırmada D1
referans alabileceği açıktır D2
.
Group 2
- Diğer sorumluluğun diğerini çağırmak için bir nesneye ihtiyacı var. Can not D4
işlemek D3
sınıfın yerine? Öyleyse muhtemelen aramaları yapmasına izin vererek D3
sınıftan C
uzaklaşabiliriz D4
.
Cevabımı, çok soyut olduğu ve çok fazla varsayımda bulunduğu gibi, taştan olduğu gibi almayın. Bunu yeniden alevlendirmenin daha fazla yolu olduğundan eminim, ama en azından adımlar, sınıfları bölmek yerine sorumlulukları yerine getirme konusunda bir çeşit süreç edinmenize yardımcı olabilir.
Düzenle:
Yorumlarından @Emmad Karem diyor ki:
"Sınıfınızda yapıcıda 20 parametre varsa, ekibiniz SRP'nin ne olduğunu tam olarak biliyor gibi görünmüyor. Sadece bir şeyi yapan bir sınıfınız varsa, 20 bağımlılığı nasıl olur?" - Bence Müşteri sınıfına sahipseniz, yapıcıda 20 parametreye sahip olmak garip değildir.
DAO nesnelerinin kurucunuzda ayarlamanız gereken birçok parametreye sahip olduğu ve parametrelerin genellikle dizge gibi basit tipler olduğu doğrudur. Ancak bir Customer
sınıf örneğinde, işleri daha basit hale getirmek için özelliklerini diğer sınıfların içinde gruplandırabilirsiniz. Address
Sokakları olan bir sınıf ve Zipcode
posta kodunu içeren bir sınıf olması ve veri doğrulama gibi iş mantığını yönetmesi gibi:
public class Address {
private String street1;
//...
private Zipcode zipcode;
// easy to extend
public bool isValid() {
return zipcode.isValid();
}
}
public class Zipcode {
private string zipcode;
public bool isValid() {
// return regex match that zipcode contains numbers
}
}
Bu şey blog post olmasını sağlamanın yanı sıra "Asla, asla, (en az sık ya) Java Dize kullanmak asla" . Alt nesneleri oluşturmayı kolaylaştırmak için yapıcılar veya statik yöntemler kullanmanın bir alternatifi olarak, bir sıvı oluşturucu paterni kullanabilirsiniz .