Çok sayıda argümana sahip yapıcılardan kaçınma


10

Bu yüzden farklı sınıflardan nesneler yaratan bir fabrikam var. Olası sınıfların tümü soyut bir atadan türetilir. Fabrikada bir yapılandırma dosyası (JSON sözdizimi) vardır ve kullanıcının yapılandırmasına bağlı olarak hangi sınıfın oluşturulacağına karar verilir.

Bunu başarmak için, fabrika JSON ayrıştırma işlemi için boost :: property_tree kullanır. Ptree'de yürür ve hangi somut nesneyi yaratacağına karar verir.

Ancak, ürün nesnelerinin birçok alanı (öznitelikleri) vardır. Somut sınıfa bağlı olarak, nesnenin yaklaşık 5-10 niteliği vardır, gelecekte belki daha da fazladır.

Bu yüzden nesnelerin kurucusunun nasıl olması gerektiğinden emin değilim. İki çözüm düşünebilirim:

1) Ürünün yapıcısı her özelliği bir parametre olarak bekler, böylece yapıcı 10'dan fazla parametre ile sonuçlanır. Bu çirkin olacak ve uzun, okunamayan kod satırlarına yol açacaktır. Bununla birlikte, avantaj, fabrikanın JSON'u ayrıştırabilmesi ve yapıcıyı doğru parametrelerle çağırabilmesidir. Ürün sınıfının, JSON yapılandırması nedeniyle oluşturulduğunu bilmesine gerek yoktur. İlgili JSON veya yapılandırma olduğunu bilmek gerekmez.

2) Ürünün yapıcısı yalnızca bir bağımsız değişken, property_tree nesnesi bekler. Sonra gerekli bilgileri ayrıştırabilir. Konfigürasyondaki am bilgisi eksik veya sınırların dışındaysa, her ürün sınıfı düzgün tepki verebilir. Fabrikanın, çeşitli ürünler için hangi argümanlara ihtiyaç duyduğunu bilmesine gerek yoktur. Fabrikanın ayrıca yanlış yapılandırma durumunda nasıl tepki vereceğini bilmesine gerek yoktur. Ve yapıcı arayüzü birleşik ve küçük. Ancak, bir dezavantaj olarak, ürünün gerekli bilgileri JSON'dan çıkarması gerekir, bu nedenle nasıl yapılandırıldığını bilir.

Çözelti tercih etme eğilimim 2). Ancak, bunun iyi bir fabrika modeli olup olmadığından emin değilim. Ürünün JSON yapılandırmasıyla oluşturulduğunu bildirmek bir şekilde yanlış geliyor. Öte yandan, yeni ürünler çok basit bir şekilde tanıtılabilir.

Bununla ilgili herhangi bir görüşünüz var mı?



1
Bağlantını takip ettim. Cırcır ucube'nin en yüksek puanlı cevabında bir örnek var. Peki bu "kurucu" yaklaşımı hangi sorunu çözüyor? DataClass kod satırı data = builder.createResult (); vardır. Ancak createResults () - yöntemi hala 10 parametreyi DataClass nesnesine almak zorundadır. Ama nasıl? Görünüşe göre sadece bir soyutlama katmanınız var, ancak DataClass'ın yapıcısı küçülmüyor.
lugge86

Oluşturucuya ve prototipe bir göz atın.
Silviu Burcea

Silviu Burcea, yaptım. Ancak, oluşturucu kullanırken, oluşturucu parametreleri ürüne nasıl alır? Bir yerlerde şişman bir arayüz OLMALIDIR. Oluşturucu sadece bir katman daha, ancak parametrelerin bir şekilde ürün sınıfına girmesi gerekiyor.
lugge86

1
Sınıfınız çok büyükse, yapıcı argümanlarını değiştirmek, onu çok büyük yapmaz .
Telastyn

Yanıtlar:


10

Seçenek 2 yapmazdım, çünkü o zaman sonsuza kadar nesnenizin yapımını boost özellik ağacı ayrıştırma ile kıvırdınız. Bu kadar çok parametreye ihtiyaç duyan bir sınıftan memnunsanız, o kadar çok parametreye ihtiyaç duyan bir kurucu ile rahat olmalısınız, hayat böyle!

Ana endişeniz kod okunabilirliği ise, oluşturucu desenini kullanabilirsiniz, temelde adlandırılmış argümanların olmaması için c ++ / java stopgap. Sonunda şöyle görünen şeylerle sonuçlanırsınız:

MyObject o = MyObject::Builder()
               .setParam1(val1)
               .setParam2(val2)
               .setParam3(val3)
             .build();

Şimdi MyObject, Builder :: build'de çağrılan özel bir kurucuya sahip olacak. Güzel olan şey, 10 parametreli bir kurucu çağırmanız gereken tek yer o olacak. Boost özellik ağacı fabrikası kurucuyu kullanır ve daha sonra doğrudan veya farklı bir kaynaktan bir MyObject oluşturmak istiyorsanız, kurucuyu kullanırsınız. Oluşturucu temel olarak, her parametreyi iletirken açıkça adlandırmanıza izin verir, böylece daha okunabilir. Bu açıkça bir kazan plakası eklediğinden, sadece dağınık kurucuyu çağırmaya veya mevcut parametrelerinizin bazılarını yapılara vb.

https://en.wikipedia.org/wiki/Builder_pattern#C.2B.2B_Example


5

İkinci yaklaşımı KULLANMAYIN.

Bu kesinlikle bir çözüm değildir ve uygulamanızın fabrikaların bulunduğu kısmı yerine, yalnızca iş mantığınızdaki sınıfları başlatır.

Ya:

  • benzer şeyleri temsil eden bazı parametreleri nesnelerde gruplandırmaya çalışın
  • geçerli sınıfı birkaç küçük sınıfa böl
  • sınıfınız aslında bir hizmet değil, bunun yerine bir değer nesnesi ise olduğu gibi bırakın

Oluşturduğunuz nesne aslında veri tutmaktan sorumlu bir sınıf olmadığı sürece, kodu yeniden düzenlemeye ve büyük sınıfı daha küçük sınıflara ayırmaya çalışmalısınız.


Eh, mantık mantığı ürünleri döndüren bir fabrika kullanıyor, bu nedenle iş mantığı JSON / ptree şeylerini görmüyor. Ama görüşünüzü görüyorum, ayrıştırıcıda Parser kodu olması yanlış geliyor.
lugge86

Sınıf, gömülü bir sistem için bir GUI'de bir widget temsil ediyor, bu nedenle, 5+ öznitelikler benim için iyi görünüyor: x_coord, y_coord, arka plan rengi, çerçeve boyutu, çerçeve rengi, metin ...
lugge86

1
@ lugge86 JSON'i ayrıştırmak için bir fabrika kullanıyor ve bu nedenle newiş mantığınızın içinde nesneleri çağırmaktan veya inşa etmekten kaçınmanıza rağmen, çok iyi bir tasarım değildir. Kontrol Do şeyler aramayın Miško Hevery tarafından konuşmak size ima fabrika yaklaşımı testi ve bakış okuma noktasında hem neden kötü olduğunu daha derinlemesine açıklıyor. Ayrıca, sınıfınız bir veri nesnesi gibi görünmektedir ve bunlar için normal hizmet sınıfından daha fazla parametreye sahip olmak genellikle iyidir. Çok rahatsız olmazdım.
Andy

Fabrika yaklaşımımla iyi hissediyorum, ancak bağlantınızı takip edeceğim ve düşüneceğim. Ancak fabrika bu konuda söz konusu değil. Soru hala ürünlerin nasıl kurulacağı ...
lugge86

"10 parametreli bir servis sınıfına sahip olmak, sınıfın çok fazla şey yaptığı gibi görünüyor" Makine öğreniminde değil. Herhangi bir ML algoritması tonlarca ayarlanabilir parametreye sahip olacaktır. ML'yi kodlarken bununla başa çıkmanın doğru yolunun ne olduğunu merak ediyorum.
Siyuan Ren

0

Seçenek 2 neredeyse doğru.

Geliştirilmiş bir seçenek 2

İşi o JSON-yapı nesnesini almak ve bitleri seçmek ve fabrika kurucularını çağırmak olan "önden bakan" bir sınıf oluşturun. Fabrikanın yaptıklarını alır ve müşteriye verir.

  • Fabrikada böyle bir JSON şeyin var olduğu konusunda hiçbir fikri yok.
  • Müşteri, fabrikanın hangi özel parçalara ihtiyacı olduğunu bilmek zorunda değildir.

Temel olarak "ön uç" 2 Bobs'a diyor ki : " Redaksiyonlu müşterilerle ilgileniyorum, böylece mühendislerin bunu yapmak zorunda kalmaması gerek! İnsan becerilerim var!" Zavallı Tom. "Müşteriyi konstrüksiyondan ayırdım. Bu sonuç son derece uyumlu bir fabrika" demiş olsaydı; işini sürdürmüş olabilir.

Çok fazla tartışma?

İstemci - ön uç iletişimi için değil.

Ön uç - fabrika? 10 parametre değilse, yapabileceğiniz en iyi şey, orijinal JSON şey değilse, o zaman bazı DTO paketten çıkarmaktır. Bu JSON'u fabrikaya aktarmaktan daha mı iyi? Aynı fark diyorum.

Bireysel parametreleri geçirmeyi şiddetle öneririm. Temiz, uyumlu bir fabrika hedefine sadık kalın. @DavidPacker yanıtı endişelerinden kaçının .

"Çok fazla argüman" azaltma

  • Fabrika veya Sınıf kurucuları

    • sadece belirli sınıf / nesne yapımı için argümanlar almak.
    • varsayılan parametreler
    • isteğe bağlı parametreler
    • adlandırılmış argümanlar
  • Kullanıcı arabirimi bağımsız değişken gruplaması

    • Yukarıdaki kurucu imzaları tarafından yönlendirilen argüman değerlerini inceler, değerlendirir, doğrular, ayarlar, vb.

"Fabrika böyle bir JSON şey bile var kesinlikle hiçbir fikrim yok" - Peki, o zaman fabrika ne için ?? Hem üründen hem de tüketiciden ürün yaratmanın ayrıntılarını gizler. Neden başka bir sınıf yardımcı olsun ki? Fabrikada konuşan JSON ile iyiyim. Bir XML ayrıştırmak için başka bir fabrika uygulamak ve gelecekte "Soyut Fabrika" uygulamak ...
lugge86

Bay Factory: "Hangi nesneyi istiyorsunuz? ... Bu nedir? Sadece hangi sınıf nesnesini inşa edeceğimi söyle." Yapılandırma dosyası JSON, Bob Amca'nın "bir uygulama detayı" dediği gibi bir veri kaynağıdır. Başka bir kaynaktan ve / veya başka bir biçimde olabilir. Genellikle belirli veri kaynağı ayrıntılarından ayrılmak istiyoruz. Kaynak veya form değişirse fabrika değişmez. Bir kaynak + ayrıştırıcı ve ayrıştırılmış modüller olarak bir fabrika verildiğinde her ikisi de yeniden kullanılabilir hale getirir.
radarbob
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.