DRY'yi kuplajı arttırmadan uygulamak mümkün müdür?


14

Bir F fonksiyonunu uygulayan bir yazılım modülümüz A olduğunu varsayalım. Başka bir B modülü F 'ile aynı fonksiyonu uygular.

Yinelenen koddan kurtulmanın birkaç yolu vardır:

  1. A'nın B'den F 'kullanmasına izin verin.
  2. B'nin A'dan F'yi kullanmasına izin verin.
  3. F'yi kendi modül C'sine yerleştirin ve hem A hem de B'yi kullanmasına izin verin.

Bu seçeneklerin tümü modüller arasında ek bağımlılıklar oluşturur. DRY prensibini artan bağlantı maliyetine uygularlar.

Görebildiğim kadarıyla DRY uygulanırken kuplaj daima artar veya kiralanır. Yazılım tasarımının en temel iki ilkesi arasında bir çelişki var gibi görünüyor.

(Aslında böyle çatışmaların olması şaşırtıcı değil. Bu muhtemelen iyi yazılım tasarımını zorlaştıran şeydir. Bu çatışmaların normalde tanıtım metinlerinde ele alınmamasını şaşırtıcı buluyorum.)

Edit (açıklama için): F ve F 'eşitliğinin sadece bir tesadüf olmadığını varsayıyorum. F 'nin değiştirilmesi gerekiyorsa, F' muhtemelen aynı şekilde değiştirilmelidir.


2
... DRY'nin çok faydalı bir strateji olabileceğini düşünüyorum, ancak bu soru DRY ile verimsizliği gösteriyor. Bazıları (örneğin, OOP meraklıları), sadece A ve B'nin kavramsal özerkliğini korumak için F'yi B'ye kopyalayıp yapıştırmanız gerektiğini iddia edebilir, ancak bunu yapacağım bir senaryoya girmedim. Ben kopya / yapıştırma kodu sadece en kötü seçenek hakkında olduğunu düşünüyorum, ben zaten bir şey yapmak için bir yöntem / işlev yazdım eminim nerede "kısa süreli bellek kaybı" duygu duramaz; bir işlevdeki bir hatayı düzeltmek ve bir diğerini güncellemeyi unutmak başka bir önemli sorun olabilir.
jrh

3
Birbiriyle çelişen bu OO prensipleri vardır. Çoğu durumda makul bir değiş tokuş bulmanız gerekir. Ancak IMHO KURU prensibi en değerlidir. @Jrh'in yazdığı gibi: birden fazla yerde aynı davranışı uygulamak, ne pahasına olursa olsun kaçınılması gereken bir bakım kabusu. Üretimdeki gereksiz kopyalardan birini güncellemeyi unuttuğunuzu öğrenmek işinizi durdurabilir.
Timothy Truckle

2
@TimothyTruckle: Onlara OO ilkeleri dememeliyiz çünkü diğer programlama paradigmaları için de geçerlidir. Ve evet, KURU değerlidir, ancak aşırıya kaçarsa da tehlikelidir. Sadece bağımlılıklar ve dolayısıyla karmaşıklık yaratma eğiliminde olduğu için değil. Aynı zamanda, değişmenin farklı nedenleri olan tesadüflerin neden olduğu kopyalara da sıklıkla uygulanır.
Frank Puffer

1
... ayrıca bazen bu senaryoya girdiğimde F'yi, A'nın ihtiyacı olan ve B'nin ihtiyacı olan parçalar için ayırabiliyordum.
jrh

1
Kuplaj doğal olarak kötü bir şey değildir ve hataları azaltmak ve verimliliği arttırmak için sıklıkla gereklidir. İşleviniz içinde dilinizin standart kitaplığından bir parseInt işlevi kullanırsanız, işlevinizi standart kitaplığa bağlarsınız. Yıllardır bunu yapmayan bir program görmedim. Anahtar, gereksiz kuplajlar oluşturmamaktır. Çoğu zaman, böyle bir bağlantıyı önlemek / kaldırmak için bir arayüz kullanılır. Örneğin, işlevim bir parseInt uygulamasını bağımsız değişken olarak kabul edebilir. Ancak, bu her zaman gerekli değildir ve her zaman akıllıca değildir.
Joshua Jones

Yanıtlar:


14

Bu seçeneklerin tümü modüller arasında ek bağımlılıklar oluşturur. DRY prensibini artan bağlantı maliyetine uygularlar.

Neden evet yapıyorlar. Ancak hatlar arasındaki bağlantıyı azaltırlar. Elde ettiğiniz, kuplajı değiştirme gücüdür. Kuplaj birçok şekilde gelir. Kodun çıkarılması dolaylı aktarımı ve soyutlamayı artırır. Artan iyi ya da kötü olabilir. Hangisini alacağınıza karar veren bir numaralı şey, bunun için kullandığınız addır. Eğer isme baktığımda içeriye baktığımda beni şaşırtıyorsa, hiç kimseye bir iyilik yapmadın.

Ayrıca, DRY'yi vakumda takip etmeyin. Çoğaltmayı öldürürseniz, bu kodun bu iki kullanımının birlikte değişeceğini tahmin etmek sizin sorumluluğunuzdadır. Bağımsız olarak değişme ihtimalleri varsa, karmaşaya ve az fayda için ekstra çalışmaya neden oldunuz. Ama gerçekten iyi bir isim bunu daha lezzetli hale getirebilir. Eğer aklınıza gelebilecek tek şey kötü bir isimse, lütfen şimdi durun.

Sisteminiz o kadar izole değilse, kuplaj her zaman var olacaktır, kimse çalışıp çalışmadığını asla bilemez. Yani yeniden düzenleme kuponu zehirinizi seçme oyunudur. DRY'nin ardından, aynı tasarım kararını değiştirmek çok zor olana kadar birçok yerde defalarca ifade edilerek oluşturulan bağlantıyı en aza indirerek ödeme yapabilirsiniz. Ancak DRY kodunuzu anlamayı imkansız kılabilir. Bu durumu kurtarmanın en iyi yolu gerçekten iyi bir isim bulmaktır. İyi bir isim düşünemiyorsanız, umarım anlamsız isimlerden kaçınmak için yeteneklisiniz


Sadece noktanızı doğru anladığımdan emin olmak için, biraz farklı bir şekilde ifade edeyim: Çıkarılan koda iyi bir ad atarsanız, çıkarılan kod artık yazılımı anlamakla ilgili değildir, çünkü isim her şeyi söylüyor (ideal olarak). Kuplaj hala teknik düzeyde mevcuttur, fakat bilişsel düzeyde yoktur. Bu nedenle nispeten zararsız, değil mi?
Frank Puffer

1
Nevermind, kötüm
Basilevs

@FrankPuffer daha iyi mi?
candied_orange

3

Açık bağımlılıkları kırmanın yolları vardır. Popüler bir çalışma zamanı bağımlılıkları enjekte etmektir. Bu şekilde, KURU elde edersiniz, statik güvenlik maliyetiyle kuplajı çıkarın. Günümüzde o kadar popüler ki, insanlar anlayamıyorlar bile, bu bir ödünleşim. Örneğin, uygulama kapları, karmaşıklığı gizleyerek yazılımları son derece karmaşık hale getiren bağımlılık yönetimini rutin olarak sağlar. Düz eski yapıcı enjeksiyonu bile eksik tip sistem nedeniyle bazı sözleşmeleri garanti edemez.

Başlığı cevaplamak için - evet, mümkündür, ancak çalışma zamanı gönderiminin sonuçları için hazır olun.

  • F'nin işlevselliğini sağlayarak A'da A arayüzünü tanımlayın
  • F arayüzü tanımla B B
  • F'yi C'ye koy
  • Tüm bağımlılıkları yönetmek için D modülü oluşturun (A, B ve C'ye bağlıdır)
  • D'de F'yi F A ve F B'ye uyarlayın
  • Ambalajları A ve B'ye enjekte edin (geçirin)

Bu şekilde, sahip olacağınız tek bağımlılık türü, diğer modüle bağlı olarak D'dir.

Veya yerleşik bağımlılık enjeksiyonu ile uygulama kapsayıcısında C'yi kaydedin ve yavaşça büyüyen çalışma zamanı sınıf yükleme döngüleri ve kilitlenmeleri otomatik kablolama servetinin tadını çıkarın.


1
+1, ancak açık uyarıyla bunun genellikle kötü bir ödünleşmedir. Statik güvenlik sizin korumanız için oradadır ve uzaktan bir sürü ürkütücü eylemle atlamak, proje karmaşıklığınız biraz arttığında çizginin ilerisinde izlenmesi zor hatalar istiyor ...
Mason Wheeler

1
DI'nin gerçekten bağımlılığı bozduğu söylenebilir mi? Resmi olarak bile, onu uygulamak için F imzalı bir arayüze ihtiyacınız var. Ancak yine de, A modülü C'den R'yi kullanıyorsa, çalışma zamanında C enjekte edildiğinden veya doğrudan bağlandığından bağımsız olarak üzerine boğulur.Di bağımlılığı bozmaz, hata sadece bağımlılık sağlanmadığında başarısızlığı
erteler

@ max630, uygulama bağımlılığını daha zayıf olan sözleşmeli olanla değiştirir.
Basilevs

@ max630 Doğru. DI'nin bağımlılığı bozduğu söylenemez. DI, aslında, bağımlılıkları tanıtmak için bir yöntemdir ve birleştirme ile ilgili sorulan soruya gerçekten diktir. F'de (veya onu çevreleyen arayüzde) bir değişiklik hala hem A hem de B'de bir değişiklik gerektirecektir
king-side slide

1

Daha fazla bağlamı olmayan bir cevabın mantıklı olduğundan emin değilim.

AZaten bağımlı mı Byoksa tam tersi mi? - bu durumda bariz bir ev seçimimiz olabilir F.

İyi bir ev olabilecek ortak bağımlılıkları paylaşıyor Ave Bpaylaşıyor musunuz F?

Ne kadar büyük / karmaşık F? Başka nelere Fbağlı?

Modüller Ave Baynı projede kullanılıyor mu?

Will Ave Bbazı ortak bağımlılık Neyse paylaşımı sonunda?

Hangi dil / modül sistemi kullanılıyor: Yeni bir modül, programcı ağrısında, performans yükünde ne kadar acı veriyor? Örneğin, modül kodu COM olan, kaynak koduna acı veren, alternatif takımlar gerektiren, hata ayıklama üzerinde etkileri olan ve (modüller arası çağrılar için) performans etkisi olan C / C ++ ile yazıyorsanız, biraz durun.

Öte yandan, tek bir yürütme ortamında sorunsuz bir şekilde bir araya gelen Java veya C # DLL'lerden bahsediyorsanız, bu başka bir konudur.


Bir işlev bir soyutlamadır ve DRY'yi destekler.

Bununla birlikte, iyi soyutlamaların tam olması gerekir - eksik soyutlamalar, tüketen istemcinin (programcı) temel uygulama bilgisini kullanarak açığı telafi etmesine neden olabilir: bu, soyutlamanın daha eksiksiz olarak sunulmasına göre daha sıkı bağlantıya neden olur.

Bu yüzden, tek bir işlevi yeni bir modüle taşımaktan daha iyi bir soyutlama yaratmaya Ave Bona bağımlı olmaya bakmayı savunacağım C

Yeni bir soyutlama alay işlevler kümesi arıyor olurdu, yani, bir temel yerine yapmak için daha dolgun / daha eksiksiz bir soyutlama yeniden düzenleme tanımlamak için kod tabanı daha fazla kadar bekleyebilir tek bir fonksiyon kodunda söyle.


2
Soyutlama ve bağımlılık grafiğini birleştirmek tehlikeli değil mi?
Basilevs

Does A already depend on B or vice versa? — in which case we might have an obvious choice of home for F.Bu, A'nın her zaman B'ye (veya tam tersi) güveneceğini varsayar ki bu çok tehlikeli bir varsayımdır. OP'nin F'yi doğal olarak A'nın (veya B'nin) bir parçası olarak görmemesi, F'nin her iki kütüphaneye de özgü olmadan var olduğunu gösterir. F bir kitaplığa aitse (örneğin bir DbContext uzantı yöntemi (F) ve Entity Framework sarmalayıcı kitaplığı (A veya B)), OP'nin sorusu tartışmalıdır.
Flater

0

Burada bu sorunu “en aza indirgeme” yollarına odaklanan cevaplar size bir kötülük yapıyor. Ve basitçe kuplaj oluşturmak için farklı yollar sunan “çözümler” gerçekten de çözüm değildir.

Gerçek şu ki, yarattığınız problemi anlayamıyorlar. Örneğinizle ilgili sorunun DRY ile bir ilgisi yoktur, daha ziyade (daha geniş) uygulama tasarımıyla ilgilidir.

Her ikisi de aynı F işlevine bağlıysa A ve B modüllerinin neden ayrı olduğunu kendinize sorun. Elbette, zayıf bir tasarıma bağlı kalırsanız bağımlılık yönetimi / soyutlama / kuplaj / siz-ismiyle ilgili sorunlarınız olacaktır.

Uygun uygulama modellemesi davranışa göre yapılır. Bu nedenle, F'ye bağımlı olan A ve B parçalarının kendi bağımsız modüllerine çıkarılması gerekir. Bu mümkün değilse, A ve B'nin birleştirilmesi gerekir. Her iki durumda da, A ve B artık sistem için yararlı değildir ve mevcut olmaması gerekir.

KURU, kötü tasarımı ortaya çıkarmak için kullanılabilen, neden olmayan bir prensiptir. Uygulamanızın yapısı nedeniyle DRY'yi ( gerçekten geçerli olduğunda - düzenlemenizi not ederek) elde edemezseniz , yapının bir yükümlülük haline geldiğinin açık bir işaretidir. Bu yüzden “sürekli yeniden düzenleme” de takip edilmesi gereken bir prensiptir.

ABC'nin orada dışarı, diğer tasarım ilkeleri (KATI, KURU, vs) tüm yapmak için kullanılan değişen (üstlenmeden dahil) daha ağrısız bir uygulama. Odaklanın o ve diğer tüm sorunların kaybolmaya başlarlar.


Her uygulamada tam olarak bir modül olmasını önerir misiniz?
Basilevs

@Basilevs Kesinlikle hayır (garanti edilmedikçe). Mümkün olduğunca çok tamamen ayrılmış modüllere sahip olmanızı öneririm. Sonuçta, bir modülün amacı budur.
king-side-slide

Soru, A ve B modüllerinin ilişkisiz işlevleri içerdiğini ve buna göre zaten çıkarıldığını, neden ve nasıl var olmalarını gerektirdiğini ima ediyor? Belirtildiği gibi soruna çözümünüz nedir?
Basilevs

@Basilevs Soru A ve B'nin düzgün bir şekilde modellenmediğini gösterir. İlk etapta soruna neden olan bu doğal eksikliktir . Mutlaka bunu basit bir gerçek yapmak var onlar kanıt değildir gerektiğini mevcuttur. Yukarıda bahsettiğim nokta bu. Açıkçası, KURU'nun kırılmasını önlemek için alternatif bir tasarım gereklidir. Tüm bu “tasarım ilkelerinin” amacının bir uygulamanın değiştirilmesini kolaylaştırmak olduğunu anlamak önemlidir.
king-side-slide

Tamamen farklı bağımlılıklara sahip bir ton başka yöntem kötü müydü ve bu tek tesadüfi olmayan yöntem yüzünden yeniden yapılması gerekiyor mu? Yoksa A ve B modüllerinin her birinin tek bir yöntem içerdiğini mi düşünüyorsunuz?
Basilevs

0

Bu seçeneklerin tümü modüller arasında ek bağımlılıklar oluşturur. DRY prensibini artan bağlantı maliyetine uygularlar.

En azından üçüncü seçenek için farklı bir fikrim var:

Açıklamanızdan:

  • A ihtiyacı F
  • B'nin F'ye ihtiyacı var
  • Ne A ne de B'nin birbirine ihtiyacı yoktur.

F'yi bir C modülüne koymak, hem A hem de B'nin zaten C özelliğine ihtiyacı olduğundan bağlantıyı arttırmaz.

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.