bir kurucu ne kadar karmaşık olmalı


18

İş arkadaşımla bir kurucunun ne kadar iş yapabileceği hakkında bir tartışma yaşıyorum. Dahili başka bir nesne A gerektiren bir sınıf, B var. Nesne A, B sınıfı işini yapmak için gereken birkaç üyelerinden biridir. Tüm genel yöntemleri iç nesneye A bağlıdır. A nesnesi hakkında bilgi DB saklanır, bu yüzden doğrulamak ve yapıcı içinde DB bakarak bakarak olsun. İş arkadaşım, kurucunun kurucu parametrelerini yakalamak dışında çok fazla iş yapmaması gerektiğini belirtti. Yapıcıya girişler kullanılarak A nesnesi bulunmazsa, tüm genel yöntemler yine de başarısız olacağından, bir örneğin oluşturulmasına izin vermek ve daha sonra başarısız olmak yerine, yapıcıya erken atmanın daha iyi olduğunu savundum.

Başkaları ne düşünüyor? Herhangi bir fark yaratıyorsa C # kullanıyorum.

Okuma Bir nesnenin tüm yapıcısını yapıcıda yapmak için bir sebep var mı? i DB giderek giderek A nesnesinin getirilmesi "Kullanıcının hazır hale getirmek için gerekli herhangi bir başka başlatma" bir parçasıdır çünkü kullanıcı yapıcı için yanlış değerlerde geçti, ben onun genel yöntemlerini kullanmak mümkün olmaz.

Yapıcılar, bir nesnenin alanlarını başlatmalı ve nesneyi kullanıma hazır hale getirmek için gerekli diğer başlatma işlemlerini yapmalıdır. Bu genellikle kurucuların küçük olduğu anlamına gelir, ancak bunun önemli miktarda çalışma olacağı senaryolar vardır.


8
Katılmıyorum. Bağımlılık tersine çevirme ilkesine bir göz atın, A nesnesinin yapıcısında geçerli bir durumda B nesnesine verilmesi daha iyi olur.
Jimmy Hoffa

5
Ne kadar soruyorsun olabilir yapılabilir? Ne kadar olmalıdır yapılabilir? Veya özel durumunuzun ne kadarı yapılmalıdır? Bu çok farklı üç soru.
Bobson

1
Jimmy Hoffa'nın bağımlılık enjeksiyonuna (veya "bağımlılık tersine çevirme") bakma önerisine katılıyorum. Açıklamayı okumak hakkındaki ilk düşüncem buydu, çünkü zaten orada yarı yolda gibisiniz; A sınıfına ayrılmış, B sınıfının kullandığı işlevsellik zaten var. Sizin durumunuzla konuşamıyorum, ancak genellikle bağımlılık enjeksiyon modelini kullanmak için yeniden düzenleme kodunun sınıfları daha basit / daha az iç içe yaptığını görüyorum.
Dr.Wily's Apprentice

1
Bobson, başlığı 'gerekir' olarak değiştirdim. Burada en iyi uygulamaları istiyorum.
Taein Kim

1
@JimmyHoffa: belki yorumunuzu bir cevaba genişletmelisiniz.
kevin cline

Yanıtlar:


22

Sorunuz tamamen ayrı iki bölümden oluşuyor:

Yapıcıdan istisna atmalı mıyım yoksa yöntem başarısız mı olmalı?

Bu, Başarısız hızlı ilkesinin açıkça uygulanmasıdır . Yapıcıyı başarısız kılmak, yöntemin neden başarısız olduğunu bulmaya kıyasla hata ayıklamak için çok daha kolaydır. Örneğin, kodun başka bir bölümünden oluşturulmuş örneği alabilir ve yöntemleri çağırırken hata alabilirsiniz. Nesnenin yanlış yaratıldığı açık mı? Hayır.

"Çağrıyı dene / yakala" sorununa gelince. İstisnalar olmak içindir olağanüstü . Bazı kodların bir istisna atacağını biliyorsanız, kodu try / catch içinde sarmazsınız, ancak istisna atabilecek kodu çalıştırmadan önce bu kodun parametrelerini doğrularsınız. İstisnalar, yalnızca sistemin geçersiz duruma geçmemesini sağlamanın bir yolu olarak ifade edilir. Bazı giriş parametrelerinin geçersiz duruma yol açabileceğini biliyorsanız, bu parametrelerin hiçbir zaman gerçekleşmediğinden emin olursunuz. Bu şekilde, genellikle sistemin sınırında olan istisnayı mantıksal olarak ele alabileceğiniz yerlerde yalnızca deneme / yakalama yapmanız gerekir.

Yapıcıdan "sistemin DB gibi diğer kısımlarına" erişebilir miyim.

Bunun en az şaşkınlık ilkesine aykırı olduğunu düşünüyorum . Pek çok kişi kurucunun bir DB'ye erişmesini beklemez. Yani hayır, bunu yapmamalısın.


2
Buna daha uygun bir çözüm genellikle inşaatın ücretsiz olduğu bir "açık" tip yöntemi eklemektir, ancak tüm gerçek başlatmanın gerçekleştiği "aç" / "bağlan" / vb. Gelecekte başarısız olan yapıcılar, yararlı bir yetenek olan nesnelerin kısmi yapımını yapmak istediğinizde her türlü soruna neden olabilir.
Jimmy Hoffa

@JimmyHoffa Yapıcı yöntemi ile özel yapım yöntemi arasında hiçbir fark görmüyorum.
Euphoric

4
Yapamazsınız, ama birçoğunuz yapar. Bir bağlantı nesnesi oluşturduğunuzda düşünün, yapıcı onu bağlar mı? Nesne bağlı değilse kullanılabilir mi? Her iki soruda da cevap hayırdır, çünkü bağlantıyı açmadan önce ayarları ve şeyleri değiştirebilmeniz için bağlantı nesnelerinin kısmen yapılandırılması yararlıdır. Bu, bu senaryoya ortak bir yaklaşımdır. Hala yapıcı enjeksiyonunun, A nesnesinin kaynak bağımlılığına sahip olduğu senaryolar için doğru yaklaşım olduğunu düşünüyorum, ancak açık bir yöntem, yapıcıyı tehlikeli işi yapmaktan daha iyidir.
Jimmy Hoffa

@JimmyHoffa Ancak bu, bağlantı sınıfının özel bir gereksinimidir, OOP tasarımının genel kuralı değildir. Aslında buna kuraldan ziyade istisnai bir durum diyebilirim. Temelde inşaatçı deseninden bahsediyorsunuz.
Euphoric

2
Bu bir gereklilik değil, bir tasarım kararıydı. Kurucunun bir bağlantı dizesi almasını ve kurulduğunda hemen bağlanmasını sağlayabilirlerdi. Nesneyi oluşturmanın faydalı olduğuna da karar vermediler, daha sonra bağlantı dizesini veya diğer bitleri ve bobble'ları anlayın ve daha sonra bağlayın ,
Jimmy Hoffa

19

Ugh.

Bir kurucu mümkün olduğunca az yapmalıdır - sorun kuruculardaki istisna davranışının garip olmasıdır. Çok az programcı uygun davranışın ne olduğunu (kalıtım senaryoları dahil) bilir ve kullanıcılarınızı her bir somutlaştırmayı denemeye / yakalamaya zorlar ... en iyi ihtimalle acı vericidir.

Orada bu iki bölümü var içinde yapıcı ve kullanma yapıcı. Yapıcıda gariptir, çünkü bir istisna oluştuğunda orada fazla bir şey yapamazsınız. Farklı bir tür döndüremezsiniz. Boş döndüremezsiniz. Temel olarak istisnayı yeniden düşünebilir, bozuk bir nesneyi geri döndürebilirsiniz (kötü yapı) veya (en iyi durum) bir iç parçayı akıllı bir varsayılanla değiştirebilirsiniz. Yapıcıyı kullanmak gariptir, çünkü o zaman örnekleriniz (ve türetilmiş tüm türlerin örneklemeleri!) O zaman onları üye başlatıcılarında kullanamazsınız. Sonunda her yerde dene / yakala tarafından okunabilirliğin (ve kırılganlığın) ötesinde, "yaratımım başarılı oldu mu?"

Yapımcınız önemsiz olmayan şeyler veya başarısız olması makul olarak beklenebilecek şeyler yapıyorsa, Createbunun yerine statik bir yöntemi (halka açık olmayan bir kurucu ile) düşünün . Çok daha kullanışlı, hata ayıklaması daha kolay ve başarılı olduğunuzda size tamamen yapılandırılmış bir örnek sunuyor.


2
Karmaşık inşaat senaryoları, tam da burada bahsettiğiniz yaratıcı desenlerin neden var olduğudur. Bu sorunlu yapılara iyi bir yaklaşımdır. Komutun uygun şekilde bağlandığını bilmeniz için .NET'te bir Connectionnesnenin CreateCommandsizin için nasıl yapabileceğini düşünmem gerekiyor .
Jimmy Hoffa

2
Buna, bir Veritabanının ağır bir dış bağımlılık olduğunu, bu tür kodları bir Fabrika sınıfına (veya bir IService gibi bir şeye) taşıyarak ileride bir noktada veritabanlarını değiştirmek (veya test etmek için bir nesneyle alay etmek) istediğinizi varsayalım. ) daha temiz bir yaklaşım gibi görünüyor
Jason Sperske

4
"yapıcılarda istisna davranışı garip" hakkında ayrıntı verebilir misiniz? Create'i kullanacak olsaydınız, tıpkı yapıcıya çağrı sararmışsınız gibi catch'i denemeniz gerekmez mi? Create'in kurucu için farklı bir isim olduğunu hissediyorum. Belki cevabını doğru alamıyorum?
Taein Kim

1
Yapıcılardan köpüren istisnaları yakalamayı denemek zorunda kaldıktan sonra, buna karşı argümanları + 1'leyin. Yine de "Yapıcıda çalışma yok" diyen insanlarla çalıştıktan sonra, bu da bazı garip desenler yaratabilir. Her nesne sadece bir yapıcı değil, aynı zamanda bir Initialize () bir tür nerede kodu gördüm nerede, tahmin ne? Nesne de denilene kadar gerçekten geçerli değil. Ve sonra iki şey var: ctor ve Initialize (). Bir nesneyi ayarlamak için çalışma yapma sorunu ortadan kalkmaz - C #, C ++ dediklerinden farklı çözümler verebilir. Fabrikalar iyidir!
J Trana

1
@jtrana - evet, başlat iyi değil. Yapıcı, bir aklı başında varsayılana veya bir fabrikaya başlar veya create yöntemi bunu oluşturur ve kullanılabilir bir örnek döndürür.
Telastyn

1

Yapıcı - yöntem karmaşıklık dengesi aslında iyi stile hakkında bir tartışma konusudur. Daha karmaşık şeyler için Class() {}bir yöntemle çoğu zaman boş yapıcı kullanılır Init(..) {..}. Dikkate alınması gereken argümanlar arasında:

  • Sınıf serileştirme olasılığı
  • Init yöntemini yapıcıdan ayırma ile, çoğu zaman aynı diziyi Class x = new Class(); x.Init(..);kısmen Birim Testlerde tekrarlamanız gerekir . Ancak o kadar iyi değil, okumak için kristal berraklığında. Bazen, sadece bir kod satırına koydum.
  • Birim Testi amacı sadece Sınıf başlatma testi olduğunda, kendi Init'e sahip olmak daha iyidir, ara Ekler ile tek tek yerine getirilen daha karmaşık eylemleri yapmak.

bence inityöntemin avantajı, başarısızlığın ele alınmasının çok daha kolay olmasıdır. Özellikle, inityöntemin dönüş değeri başlatmanın başarılı olup olmadığını gösterebilir ve yöntem nesnenin her zaman iyi durumda olmasını sağlayabilir.
pqnet
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.