Neye öncelik verilmelidir: YAGNI mı İyi Tasarım mı?


76

YAGNI hangi noktada iyi kodlama uygulamalarına karşı öncelik kazanmalı ve bunun tersi geçerli mi? İşyerinde bir proje üzerinde çalışıyorum ve meslektaşlarıma iyi kod standartları yavaşça tanıtmak istiyorum (şu anda hiçbiri yok ve her şey kafiye veya sebep olmadan birbirine bağlanıyor), ancak bir dizi sınıf oluşturduktan sonra (biz TDD yapmayın ya da ne yazık ki herhangi bir ünite testi yapmayın.) Bir adım geri atmıştım ve YAGNI’yı ihlal ettiğini düşündüm, çünkü kesinlikle bu sınıfların bazılarını genişletme gereği duymadığımızı kesinlikle biliyorum.

İşte ne demek istediğimin somut bir örneği: Temel CRUD işlevlerine sahip basit bir Depo tarzı modeli kullanan bir dizi saklı yordamı saran bir veri erişim katmanım var. Tüm depo sınıflarımın ihtiyaç duyduğu çok sayıda yöntem olduğu için, depolarım için adlandırılan genel bir arayüz oluşturdum IRepository. Ancak, daha sonra her bir havuz tipi (örneğin ICustomerRepository) için bir "işaretleyici" arayüz (yani yeni bir işlevsellik eklemeyen arayüz ) oluşturdum ve somut sınıf bunu uyguladı. İş nesnelerini Saklı Prosedürün döndürdüğü DataReaders / DataSets'ten oluşturmak için bir Fabrika uygulamasıyla aynı şeyi yaptım; depo sınıfımın imzası şunun gibi görünmeye meyillidir:

public class CustomerRepository : ICustomerRepository
{
    ICustomerFactory factory = null;

    public CustomerRepository() : this(new CustomerFactory() { }

    public CustomerRepository(ICustomerFactory factory) {
        this.factory = factory;
    }      

    public Customer Find(int customerID)
    {
        // data access stuff here
        return factory.Build(ds.Tables[0].Rows[0]);
    }
}

Buradaki kaygım, YAGNI'yi ihlal ettiğimden dolayı çünkü% 99 kesin CustomerFactoryolarak bu depoya somut bir şey vermek için hiçbir neden olmayacağının kesin olduğunu biliyorum ; Birim testlerimiz olmadığı için, MockCustomerFactorybenzer bir şeye ihtiyacım yok ve bu kadar çok arabirime sahip olmak iş arkadaşlarımı karıştırıyor olabilir. Öte yandan, fabrikanın somut bir uygulamasını kullanarak bir tasarım kokusu gibi görünüyor.

Uygun yazılım tasarımı arasında bir uzlaşmaya varmanın ve çözümü önemsememenin iyi bir yolu var mı? Tüm "tekli uygulama arayüzlerine" sahip olmama gerek varsa veya biraz iyi tasarımdan ödün verebilseydim ve sadece temel arayüze ve sonra da tek betona sahip olup olmadığımı ve sadece programlama için endişelenmediğimi sorguluyorum. Uygulama bu ise kullanılacaktır.


17
“Birim testler yapmadığımız için MockX'e ihtiyacım yok” diyorsunuz ki bu doğal olarak “IX'a ihtiyacım yok, sadece X'e ihtiyacım var”. Etrafa, sen birim testleri yok aslında bunlar size yardımcı olacaktır, çünkü IX ve MockX gerektiği gerçeğini vurgulayan çevirmek zorunda birim testleri. Test yaptırmama gerçeğini kabul etmeyin, bunu (muhtemelen iyi, uzun bir zaman) çözülecek geçici bir sorun olarak kabul edin.
Anthony Pegram 16:11


1
Bunun gibi yeni sınıflar yazıyor olsaydı, bazı testler eklemek istersin diye düşünmüştüm. İş arkadaşların onları çalıştırmazsa bile. En azından daha sonra “Bakın! Ünite testlerim kodumu kırdığınızda yakaladı! Ünite testlerinin ne kadar iyi olduğunu görün!” Diyebilirsiniz. Bu durumda, alay edilebilir hale getirmek burada faydalı olabilir. (Bununla birlikte, nesne bir arayüz tanımlanmadan alay edilebilseydi tercih ederim)
Winston Ewert

Birim testleri beni sahte bir çerçeve oluşturmaya (ya da kullanmaya) zorlamaz mı, böylece canlı saklı yordamlara çarpmam? Testler eklemememin ana nedeni budur - her birimiz, test ettiğimiz ve kod yazdığımız üretim veritabanının yerel bir kopyasına sahibiz.
Wayne Molina

3
@Anthony Ve alay etmek, içerdiği ekstra karmaşıklığı her zaman haklı kılıyor mu? Alay etmek iyi bir araçtır, ancak faydası da maliyetlere göre ağırlıklandırılmalı ve bazen ölçek aşırı bir dolaylı indirimle diğer yöne yatırılmalıdır. Elbette, ekstra karmaşıklığa yardımcı olacak araçlar var, ancak karmaşıklığı ortadan kaldırmayacaklar. “Her ne pahasına olursa olsun sınama” olarak verilen bir muamele artışı eğilimi var gibi görünüyor. Bunun yanlış olduğuna inanıyorum.
Konrad Rudolph

Yanıtlar:


75

Uygun yazılım tasarımı arasında bir uzlaşmaya varmanın ve çözümü önemsememenin iyi bir yolu var mı?

YAGNI.

Biraz iyi tasarım feda edebilirim

Yanlış varsayım.

ve taban arayüzü ve sonra tek beton,

Bu bir "fedakarlık" değil. Yani bir iyi bir tasarım.


72
Kusursuzluk, eklenecek başka bir şey olmadığında değil, alınacak bir şey kalmadığında da başarılır. Antoine De St-Exupery
Newtopian 16:11

5
@ Newtopian: insanlar Apple'ın en son ürünleri ile ilgili bu konuda karışık duygular var. :)
Roy Tinker

14
Bu tür cevaplarla ilgili büyük bir sorunum var. "X doğrudur, çünkü Y bunu söyler ve Y toplum tarafından iyi desteklenir" geçerli mi? Gerçek hayatta biri YAGNI'ye karşı saldırdıysa, ona bu cevabı argüman olarak gösterir misiniz?
vemv

2
@vemv. Buradaki hiç kimse YAGNI'ye karşı bağırmıyor. Tüm S.Lott, OP'nin 2 değerli hedef arasındaki algılanan çelişkilerin bir hata olduğunu söyledi. BTW, bugünün yazılım dünyasında YAGNI'ye karşı çürüyen etkin bir geliştirici tanıyor musunuz ? Gerçek projeler üzerinde çalışıyorsanız, gereksinimlerin sürekli değiştiğini ve kullanıcıların ve yöneticilerin genel olarak ne yaptıklarını bilmediklerini veya onların önüne geçene kadar istemediklerini biliyorsunuzdur. Gerekli olanı uygulamak ÇALIŞMA TÜRÜDÜR - geleceği tahmin etmeye çalışan bir kod yazarak neden zaman, enerji ve para harcıyorsunuz (veya işinizi riske atıyorsunuz)?
Vektör

6
Demek istediğim YAGNI ile ilgili değil - cevap kalitesiyle ilgili. Özellikle birinin bağırdığını söylemedim, aklımın bir parçasıydı. Lütfen tekrar oku.
vemv

74

Çoğu durumda, ihtiyacınız olmayacak kodlardan kaçınmak, daha iyi tasarıma yol açar . En sürdürülebilir ve geleceğe yönelik tasarım, gereklilikleri karşılayan en az miktarda iyi adlandırılmış basit kodu kullanan tasarımdır.

En basit tasarımlar, geliştirilmesi en kolay olanıdır. Hiçbir şey işe yaramaz, gereğinden fazla soyutlanmış soyutlama katmanları gibi sürdürülebilirliği öldüremez.


8
'YAGNI kodundan kaçınmayı' sinir bozucu derecede belirsiz buluyorum. Bu anlamına gelebilir ihtiyacın olacak değiliz kodu veya YAGNI ilkesine bağlıdır kodu . (Bkz 'KISS kodu')
sehe

2
@sehe: Belirsiz değil (“YAGNI ilkesine bağlı kalıyor” derken tamamen çelişkili olsa da): heceleyerek:: "Buna ihtiyaç duymayacak bir kod", muhtemelen ne demek ihtiyacın olmayacak mı?
Michael Borgwardt

1
Bu cevabı büyük bir yazı tipinde yazdıracağım ve tüm mimarlık astronotlarının okuyabileceği bir yere asacağım. 1!
kirk.burleson 16:11

1
+1. Bazı yeni özellikleri desteklemem ve eklemem için bana verilen ilk kurumsal projemi hala hatırlayabilirim. Yaptığım ilk şey, 40.000 satırlık bir programdaki 32.000 satırlık gereksiz kodu, hiçbir işlevsellik kaybetmeden kaldırmaktı . Orijinal programlayıcı bundan kısa bir süre sonra ateşlendi.
EJ Brennan

4
@vemv: "şu anda kullanılmayan, trivally hariç" kullanılmadığı, yani bir YAGNI durumu olarak "yararsız" ifadesini okuyun. Ve "fazla mühendislik", "kötü" den biraz daha belirgindir. Özellikle "teorik kavramların neden olduğu karmaşıklık veya somut, mevcut gereksinimler yerine hayal edilen olası gereksinimler" anlamına gelir.
Michael Borgwardt 17:11

62

YAGNI ve SOLID (veya başka bir tasarım metodolojisi) birbirini dışlamaz. Ancak, onlar kutuplara yakın karşıtlardır. Her ikisine de% 100 bağlı kalmak zorunda değilsiniz, ancak bir miktar alıp ver; Bir sınıfın tek bir yerde kullandığı son derece soyutlanmış bir desene ne kadar çok bakarsanız ve YAGNI'ye söyleyip sadeleştirirseniz, tasarım katılaşır. Tersi de doğru olabilir; geliştirme aşamasında birçok kez, bir tasarım "inanç üzerine" SOLIDly uygulanır; Nasıl ihtiyacın olacağını görmüyorsun, ama sadece bir önsün. Bu doğru olabilir (ve kazandıkça daha fazla tecrübe kazanmanız daha olasıdır), ancak sizi bir tokat-çizgi "hafif yap" yaklaşımı kadar teknik borca ​​da götürebilir; DIL "spagetti code" codebase yerine, "lazanya kodu" ile bitebilir, basitçe bir yöntem veya yeni bir veri alanı ekleyen çok sayıda katmana sahip olmak, yalnızca bir uygulama ile hizmet proxy'ler ve gevşek bir şekilde bağlı bağımlılıklar arasında bir gün süren dolaşma süreci haline gelir. Veya "mantı kodu" ile bitirdiniz, öyle küçük ısırık büyüklüğünde parçalar halinde gelir ki, mimaride yukarı, aşağı, sola veya sağa hareket etmeniz, sizi her biri 3 satırlık 50 yöntemden geçirir.

Başka cevaplarda söyledim, ama işte burada: İlk seferde, çalışmasını sağlayın. İkinci seferde, zarif olun. Üçüncü seferde, SOLID yapın.

Bunu yıkmak:

İlk önce bir kod satırı yazdığınızda, çalışması yeterlidir. Bu noktada, tüm bildiğiniz için, bir kereye mahsus. Böylece, 2 ve 2 eklemek için "fildişi kule" mimarisi inşa etmek için herhangi bir stil noktası elde edemezsiniz. Yapmanız gerekeni yapın ve bir daha asla göremeyeceğinizi farz edin.

İmleciniz bu kod satırına bir daha girdiğinde, ilk yazdığınız andan itibaren hipotezinizi ispatladınız. Uzatmak ya da başka bir yerde kullanmak için bu kodu tekrar gözden geçiriyorsunuz, bu bir kerelik değil. Şimdi, DRY gibi bazı temel ilkeler (kendinizi tekrar etmeyin) ve kod tasarımı için diğer basit kurallar uygulanmalıdır; tekrarlanan kod için metotları ve / veya form döngülerini çıkartın, ortak hazırlayıcılar veya ifadeler için değişkenleri çıkartın, bazı yorumlar ekleyin, fakat genel olarak kodunuz kendi kendini belgelemelidir. Şimdi, kodunuz düzenli bir şekilde düzenlenmiş, eğer hala sıkı sıkıya bağlıysanız ve ona bakan herhangi biri, satır satır izlemek yerine, kodu okuyarak ne yaptığınızı kolayca öğrenebilir.

İmleciniz bu koda üçüncü kez girdiğinde, büyük olasılıkla çok büyük bir şeydir; Ya bir kez daha genişletiyorsunuz ya da kod tabanında en az üç farklı yerde daha kullanışlı oluyor. Bu noktada, çekirdek olmasa da, sisteminizin bir öğesidir ve bu şekilde tasarlanmalıdır. Bu noktada, genellikle şu ana kadar nasıl kullanıldığının bilgisine de sahip olursunuz; bu, tasarımları bu kullanımları ve diğer yenilikleri düzene sokmak için nasıl tasarlayacağınıza dair iyi tasarım kararları vermenize olanak sağlar. Şimdi SOLID kuralları denklemi girmelidir; özel amaçlı kod içeren sınıfları çıkartın, benzer amaç ve fonksiyonlara sahip olan sınıflar için ortak arayüzler tanımlayın, sınıflar arasında gevşek bağlanmış bağımlılıklar kurun ve bağımlılıkları kolayca ekleyebileceğiniz, çıkarabileceğiniz veya değiştirebileceğiniz şekilde tasarlayın.

Bu noktadan sonra, bu kodu daha fazla genişletmeniz, yeniden uygulamanız veya yeniden kullanmanız gerekirse, hepsi güzel bir şekilde paketlenir ve hepimizin bildiği ve sevdiğimiz "kara kutu" biçiminde özetlenir; başka bir yere ihtiyaç duyduğunuz yere takın veya söz konusu arayüzün kullanımını değiştirmek zorunda kalmadan, arayüzün yeni bir uygulaması olarak tema üzerine yeni bir değişiklik ekleyin.


Ben awesomeness ikinci.
Filip Dupanović

2
Evet. Yeniden kullanım / genişletme tasarımını önceden tasarladığımda, yeniden kullanmak veya uzatmak istediğimde, beklediğimden farklı bir şekilde olacağını fark ettim. Tahmin, özellikle gelecekle ilgili zor. Bu yüzden 3 grev kuralınızı destekliyorum - o zamana kadar nasıl kullanılacağı / uzatılacağı konusunda makul bir fikriniz var . Not: Bunun bir istisnası, bunun nasıl olacağını zaten biliyorsanız (örneğin, önceki projelerden, alan bilgisinden veya önceden belirtilmişse).
13,

Dördüncü pasta, müthiş olun.
Richard Neil Ilagan 20:11

@KeithS: Görünüşe göre John Carmack benzer bir şey yaptı: "Quake II'nin kaynak kodu ... Quake 1, Quake World ve QuakeGL'i güzel bir kod mimarisinde birleştirin." fabiensanglard.net/quake2/index.php
13,

+1 Sanırım şu urun ismini vereceğim: "Practic refactoring" :)
Songo

31

Bunlardan herhangi biri yerine, WTSTWCDTUAWCROT?

(Kullanabileceğimiz en basit şey nedir ve perşembe günü serbest bırakabiliriz?)

Basit kısaltmalar yapılacak işler listemde var, ancak öncelik değiller.


8
Bu kısaltma YAGNI prensibini :) ihlal
riwalk

2
Tam ihtiyacım olan harfleri kullandım - daha fazla ve daha az değil. Bu şekilde, bir çeşit Mozart gibiyim. Evet. Ben kısaltmalar Mozart'ım.
Mike Sherrill 'Cat Recall'

4
Mozart'ın kısaltmalar yapmakta korkunç olduğunu asla bilmiyordum. Bir SE sitesinde her gün yeni bir şey öğreniyorum. : P
Cameron MacFarland

3
@Mike Sherrill 'CatRecall': Belki bunu WTSTWCDTUWCROTAWBOF = 'a genişletmeliyiz = "Bunu yapmak için yapabileceğimiz en basit şey nedir, perşembe günü yayınlayabiliriz ve cuma günü kırılmayacağız?" ;-)
Giorgio

1
@ Stargazer712 no :) POLA'yı ihlal ediyor.
v.oddou

25

YAGNI ve iyi tasarım çelişkili değil. YAGNI gelecekteki ihtiyaçları desteklemektir (değil). İyi tasarım, yazılımınızın şu anda ne yaptığını ve bunu nasıl yaptığını şeffaf hale getirmekle ilgilidir .

Bir fabrikaya giriş yapmak mevcut kodunuzu kolaylaştıracak mı? Değilse, eklemeyin. Varsa, örneğin testler eklerken (ki yapmanız gereken!), Ekleyin.

YAGNI gelecekteki işlevleri desteklemek için karmaşıklık eklememekle ilgilidir .
İyi Tasarım, tüm mevcut işlevleri desteklerken karmaşıklığı ortadan kaldırmakla ilgilidir .


15

Çatışma değil, hedeflerin yanlış.

Ne yapmaya çalışıyorsun?

Kaliteli bir yazılım yazmak istiyorsunuz ve bunu yapmak için kod tabanınızı küçük tutmak istiyorsunuz ve sorun yok.

Şimdi bir çatışmaya varıyoruz, kullanmayacağımız davaları yazmazsak tüm davaları nasıl kapatıyoruz?

İşte problemin neye benziyor.

görüntü tanımını buraya girin (ilgilenen herkes, buna buharlaşan bulutlar denir )

Peki, bunu ne sürüyor?

  1. Neye ihtiyacın olmayacağını bilmiyorsun
  2. Zaman kaybetmek ve kodunuzu şişirmek istemezsiniz

Bunlardan hangisini çözebiliriz? Eh, zaman kaybetmek istemiyor gibi görünüyor ve şişkinlik kodu harika bir amaç ve mantıklı. Peki ya bu ilki? Kodlamak için neye ihtiyacımız olacağını bulabilir miyiz?

İşyerinde bir proje üzerinde çalışıyorum ve iş arkadaşlarım için iyi kod standartları yavaşça tanıtmak istiyorum (şu anda hiçbiri yok ve her şey kafiye veya sebep olmadan birbirine bağlandı.) [...] Geri adım attım ve YAGNI’yı ihlal ettiğini düşündüm, çünkü kesinlikle bu sınıfların bazılarını genişletme gereği duymadığımızı kesinlikle biliyorum.

Hepsini tekrar ifade edelim

  • Kod standardı yok
  • Proje planlama devam etmiyor
  • Her yerde kovboylar kendi lanet şeylerini yapıyorlar (ve vahşi vahşi batıda şerif oynamaya çalışıyorsun), evet.

Uygun yazılım tasarımı arasında bir uzlaşmaya varmanın ve çözümü önemsememenin iyi bir yolu var mı?

Bir uzlaşmaya ihtiyacınız yok, yetkin ve tüm projenin vizyonuna sahip ekibi yönetmek için birine ihtiyacınız var. İhtiyacınız olanı planlayabilecek birine ihtiyacınız var, her biriniz ihtiyaç duymayacağınız şeyleri atmak yerine ihtiyaç duymayacağınız şeyler çünkü gelecekten çok emin değilsiniz çünkü ... neden? Nedenini size söyleyeyim, çünkü hiç birinizin hepinizin içinde bir planı yok. Tamamen ayrı bir sorunu çözmek için kod standartları getirmeye çalışıyorsunuz. Çözmeniz gereken PRIMARY probleminiz açık bir yol haritası ve proje. Bunu yaptıktan sonra, “kod standartları bu hedefe daha etkili bir şekilde takım olarak ulaşmamıza yardımcı oluyor” diyebilirsiniz, ki bu da asıl gerçek, ancak bu sorunun kapsamı dışında.

Bunları yapabilecek bir proje / ekip yöneticisi edinin. Eğer bir tane varsa, onlardan bir harita istemeniz ve YAGNI problemini bir haritanın bulunmadığını açıklamanız gerekir. Eğer son derece beceriksizlerse, planı kendiniz yazın ve "İhtiyacımız olan şeyler hakkında size raporum var, lütfen gözden geçirin ve kararınızı bize bildirin."


Ne yazık ki bir tane yok. Geliştirme Yöneticisi, standartların / kaliteden daha hızlı bir şekilde işlerin yapılmasından daha fazla endişe duyuyor ya da doğrudan doğrudan sınıflardan döndürülen her yerde ham DataSet'i kullanmak, VB6 stil kodlaması ve yinelenen mantıkla tüm kodların arkasındaki her şeyi kopyalamak ve yapıştırmak gibi standart uygulamaları yapacak bitmiş.
Wayne Molina

Sorun değil, biraz daha yavaş olacak, ama onların endişeleriyle konuşmalısın. Bu YAGNI / Yararsız kod sorununun zaman kaybettirdiğini açıklayın, yol haritasını önerin, ona bir yol haritası verin, çalışmayı daha hızlı hale getireceğini açıklayın. Satın alındığında, zayıf standartların gelişim hızına getirdiği sorunlara gelin, daha iyisini önerin. Projenin yapılmasını istiyorlar, sadece işin nasıl yönetileceğini bilmiyorlar, onun yerini almanız ya da ona bebek vermeniz ya da istifa etmeniz gerekiyor.
Gizli

Erm ..... Bence sürüş hedefi 'iyi ve değerli bir ürüne sahip olmak istersiniz' olur mu?
sehe

@sehe bu onun kararı değil: s.
Gizli

3
Mükemmel cevap. Yokuş yukarı bir savaşla karşı karşıya. Herhangi bir yönetim alımı yoksa, bunu yapmak zor olacaktır. Ve bu sorunun erken olduğu ve asıl sorunu çözmediği konusunda haklısınız.
Seth Spearman

10

Kodunuzun ünite testleriyle genişletilmesine izin vermek, YAGNI kapsamında asla ele alınmayacaktır, çünkü buna ihtiyacınız olacak. Bununla birlikte, tasarımınızın tek bir uygulama arayüzünde değiştiğine ikna olmadım, çünkü kodun test edilebilirliğini arttırıyor çünkü CustomerFactory zaten bir arayüzden miras alıyor ve herhangi bir zamanda bir MockCustomerFactory için değiştirilebiliyor.


1
İyi Tasarım ve YAGNI arasındaki kozmik savaş ve / veya aşk hakkında değil, gerçek sorun hakkında faydalı yorumlar için +1.
psr

10

Soru yanlış bir ikilem sunuyor. YAGNI prensibinin doğru uygulanması ilgisiz bir şey değildir. İyi tasarımın bir yönü . SOLID ilkelerinin her biri aynı zamanda iyi tasarım unsurlarıdır. Her prensibi herhangi bir disiplinde her zaman tam olarak uygulayamazsınız. Gerçek dünyadaki problemler kodunuza çok fazla kuvvet uygular ve bunlardan bazıları zıt yönlere zorlar. Tasarım ilkeleri bütün bunları hesaba katmak zorundadır, ancak hiçbir koşulda bütün durumlar için uygun bir prensip yoktur.

Şimdi, her bir ilkeye, bazen farklı yönlere yönelebildikleri halde, hiçbir şekilde içsel olarak çatışmaya girmeyecekleri anlayışı ile bir göz atalım.

YAGNI, geliştiricilerin belirli bir yeniden işleme türünden kaçınmasına yardımcı olmak için tasarlandı: ki bu yanlış olanı yapmaktan geliyor. Bunu, gelecekte neyin değişeceğini ya da neye ihtiyaç duyulacağını düşündüğümüz hakkındaki tahminlere dayanarak, kararların çok erken alınmamasını sağlayarak bize yol göstererek yapar. Toplu tecrübe bize bunu yaptığımızda genelde yanlış olduğumuzu söyler. Örneğin, YAGNI size şu anda birden fazla uygulayıcıya ihtiyaç duymadığınızı bilmiyorsanız , yeniden kullanılabilirlik amacıyla bir arayüz oluşturmamanızı söyleyecektir . Benzer şekilde, YAGNI, şu anda birden fazla ekrana sahip olacağınızı bilmiyorsanız, bir uygulamadaki tek formu yönetmek için bir "Ekran Yöneticisi" oluşturmadığını söyler .

Birçok kişi sandığının aksine, KATI olduğu değil kullanırlılık, genericity, hatta soyutlama hakkında. SOLID, belirli bir değişikliğin ne olabileceği hakkında hiçbir şey söylemeden, değişime hazır kod yazmanıza yardımcı olmak için tasarlanmıştır . SOLID'in beş prensibi, aşırı jenerik olmadan esnek ve saf olmadan basit olan kod oluşturma stratejisi oluşturur. SOLID kodunun doğru uygulanması, iyi tanımlanmış rol ve sınırlara sahip küçük, odaklanmış sınıflar oluşturur. Pratik sonuç, ihtiyaç duyulan herhangi bir değişiklik için asgari sayıda sınıfa dokunulması gerektiğidir. Benzer şekilde, herhangi bir kod değişikliği için, diğer sınıflara indirgenmiş bir miktar "dalgalanma" vardır.

Sahip olduğunuz örnek duruma baktığımızda, YAGNI ve SOLID'in ne söyleyebileceğini görelim. Tüm depoların dışardan aynı görünmesi nedeniyle ortak bir depo arayüzü düşünmektesiniz. Ancak ortak, genel bir ara yüzün değeri, uygulayıcılardan herhangi birini, özellikle hangisinin olduğunu bilmeye gerek kalmadan kullanma yeteneğidir. Uygulamanızda bunun gerekli veya yararlı olacağı bir yer olmadığı sürece, YAGNI yapmaz diyor.

Bakılacak 5 KATI ilke var. S, Tek Sorumluluktur. Bu arayüzle ilgili hiçbir şey söylemez, ancak somut sınıflarınız hakkında bir şeyler söyleyebilir. Veri erişiminin kendisinin en iyi şekilde bir veya daha fazla sınıfın sorumluluğunun üstlenebileceği, depoların sorumluluğunun örtük bir bağlamdan (CustomerRepository, Müşteri varlıkları için dolaylı olarak bir depo olduğu) açık çağrılara çevrilmesidir. Müşteri varlık türünü belirten genelleştirilmiş veri erişim API'si.

O Açık-Kapalı. Bu çoğunlukla miras ile ilgilidir. Eğer depolarınızı ortak işlevsellik uygulayan ortak bir tabandan türetmeye çalışıyorsanız ya da farklı depolardan daha fazla türetmeyi düşünüyorsanız, bu geçerli olacaktır. Ama sen değilsin, öyle değil.

L, Liskov Değiştirilebilirliktir. Bu, depoları ortak havuz arayüzü üzerinden kullanmayı amaçladıysanız geçerlidir. Tutarlılığı sağlamak ve farklı uygulayıcılar için özel işlemlerden kaçınmak için arayüze ve uygulamalara kısıtlamalar getirmektedir. Bunun nedeni, bu tür özel işlemlerin bir arayüzün amacını baltalamasıdır. Bu prensibi göz önünde bulundurmak faydalı olabilir, çünkü ortak depo arabirimini kullanmaktan sizi uyarabilir. Bu YAGNI'nin rehberliği ile çakışıyor.

Ben Arabirim Ayrımıyım. Bu, depolarınıza farklı sorgu işlemleri eklemeye başlarsanız geçerli olabilir. Arabirim ayrımı, bir sınıfın üyelerini belirli tüketiciler tarafından diğeri diğerlerinin kullanacağı iki alt gruba ayırabileceğiniz, ancak hiçbir tüketicinin her iki alt grubu kullanmayacağı durumlarda geçerlidir. Kılavuz, ortak bir taneden ziyade iki ayrı arayüz oluşturmaktır. Sizin durumunuzda, münferit örnekleri alma ve kaydetmenin, genel sorgulama yapan aynı kod tarafından tüketilmesi muhtemel değildir, bu yüzden bunları iki arayüze ayırmak faydalı olabilir.

D Bağımlılık Enjeksiyonu. Burada S ile aynı noktaya geri dönüyoruz. Veri erişim API'si tüketiminizi ayrı bir nesneye ayırırsanız, bu ilke, yalnızca o nesnenin bir örneğini yenileştirmek yerine, oluştururken bunu iletmeniz gerektiğini söyler. bir depo. Bu, veri erişim bileşeninin kullanım ömrünü kontrol etmeyi kolaylaştırır ve bu sayede tek bir oluşturma rotasına gitmenize gerek kalmadan, depolarınız arasında referanslar paylaşma olanağını açar.

SOLID ilkelerinin çoğunun mutlaka uygulamanızın geliştirilmesinin bu aşamasında uygulanmayacağını not etmek önemlidir. Örneğin, veri erişimini engellemeniz gerekip gerekmediğine ve veri tabanı mantığını veritabanına çarpmadan sınamak isteyip istemediğinize bağlıdır. Bu olası gibi görünmüyor (maalesef, bence), bu yüzden muhtemelen gerekli değildir.

Tüm bu düşüncelerden sonra, YAGNI ve SOLID'in aslında bir ortak sağlam, anında alakalı tavsiye sunduğunu görüyoruz: Muhtemelen ortak bir genel depo arayüzü oluşturmak gerekli değildir.

Tüm bu dikkatli düşünce bir öğrenme alıştırması olarak son derece faydalıdır. Öğrenirken zaman alıcıdır, ancak zamanla sezgiyi geliştirirsiniz ve çok hızlı olur. Yapmanız gereken doğru şeyi bileceksiniz, ancak birisi nedenini açıklamanızı istemediği sürece tüm bu kelimeleri düşünmenize gerek yok.


Bu sayfadaki tartışmaların çoğunun GRASPrinciples'in 2 büyük yarışmacısına "düşük bağlanma" ve "yüksek uyum" bıraktığını düşünüyorum. Müşteri tasarım kararları “düşük bağlantı” prensibinden kaynaklanmaktadır. Düşük kavrama uğruna SRP + ISP + DIP'yi "ne zaman" etkinleştirme gibi. Örnek: bir sınıf -> 3 sınıf MVC düzeninde. Veya daha da pahalı: .dll / .so modüllerinde / meclislerde bölünme. Bu, yapı etkileri, projeler, makelistler, sunucu oluşturma, kaynak sürümlü dosyalar eklemeleri nedeniyle çok maliyetlidir ...
v.oddou

6

'İyi tasarımın', bir işe yaramadığı zaman bile, her zaman uygulanması gereken bir tür fikirbilim ve resmi kurallar dizisini takip etmek anlamına geldiğine inanıyor gibisiniz.

IMO bu kötü tasarım. YAGNI iyi bir tasarım bileşenidir, asla bir çelişki değildir.


2

Örneğinizde YAGNI’nin üstün olması gerektiğini söyleyebilirim. Daha sonra arayüz eklemeniz gerekirse, size bu kadar pahalıya mal olmaz. Bu arada, eğer hiç bir amaca hizmet etmiyorsa, sınıfa göre bir arayüze sahip olmak gerçekten iyi bir tasarım mı?

Bir kez daha düşündüm, belki bazen ihtiyacın olan şey İyi Tasarım değil, Yeterli Tasarım. İşte konuyla ilgili mesajların çok ilginç bir dizi:


İlk ve üçüncü bağlantılarınız aynı yere gidiyor.
David Thornley

2

Bazı insanlar, arayüz isimlerinin I ile başlamaması gerektiğini iddia ediyor. Özellikle bir sebep, verilen tipin bir sınıf mı yoksa bir arayüz mü olduğuna bağlı olarak aslında bağımlılığı sızdırıyor olmanızdır.

Ne sizi yasaklar CustomerFactoryya tarafından uygulanan olacağını, ilk başta sınıf olmak ve daha sonra bir arayüze değişen DefaultCustormerFactoryya UberMegaHappyCustomerPowerFactory3000? Değiştirmeniz gereken tek şey, uygulamanın somutlaştığı yerdir. Ve eğer daha az iyi bir tasarıma sahipseniz, o zaman bu en fazla bir avuç yer.

Yeniden düzenleme, gelişimin bir parçası. En iyisi küçük kodlara sahip olmak, kolayca kırılması kolay, bir arabirim ve her bir sınıf için ilan edilmiş bir sınıf olması, sizi aynı anda en az iki yerde her yöntem adını değiştirmeye zorluyor.

Arabirimleri kullanmanın asıl amacı, muhtemelen iyi tasarımın en önemli ayağı olan modülerliği sağlamaktır. Bununla birlikte, bir modülün sadece dış dünyadan ayrılmasıyla değil (dış perspektiften nasıl algıladığımızla ilgili olsa da) değil, aynı zamanda içsel çalışma tarafından da tanımlandığını unutmayın.
Demek istediğim, doğası gereği birbirine ait olan şeyleri birbirinden ayırmanın pek mantıklı gelmediği. Bir bakıma bardak başına ayrı bir rafa sahip bir dolaba sahip olmak gibidir.

Önem, büyük ve karmaşık bir problemin daha küçük, daha basit alt problemlere dönüştürülmesinde yatmaktadır. Ve başka alt bölümler olmadan yeterince basit hale geldikleri noktada durmalısınız, yoksa gerçekte daha karmaşık hale gelecektir. Bu YAGNI'nin bir sonucu olarak görülebilir. Ve kesinlikle iyi tasarım demektir.

Amaç, bir şekilde tek bir depo ve tek bir fabrika ile yerel bir sorunu çözmemek. Amaç, bu kararın başvurunuzun geri kalanında herhangi bir etkisi olmamasıdır. Modülerliğin konusu budur.
İş arkadaşlarınızın modülünüze bakmasını, kendiliğinden açıklamalı çağrıları olan bir cepheyi görmesini ve tüm potansiyel olarak gelişmiş iç tesisatlar için endişelenmenize gerek kalmadan bunları kullanabileceklerinden emin olmalarını istiyorsunuz.


0

interfaceGelecekte beklenen bir çok uygulama oluşturuyorsunuz . I<class>Kod tabanınızdaki her sınıf için de olabilir . Yapma.

YAGNI'ye göre sadece tek beton sınıfını kullanın. Test amacıyla "sahte" bir nesneye sahip olmanız gerektiğini düşünüyorsanız, orijinal sınıfı biri orijinal beton sınıfı, diğeri ise sahte uygulama ile birlikte iki uygulamalı soyut sınıfa dönüştürün .

Yeni somut sınıfı somutlaştırmak için, orjinal sınıfın bütün örneklerini güncellemeniz gerekecektir. Ön tarafta statik bir kurucu kullanarak bunun üstesinden gelebilirsiniz.

YAGNI yazılmadan önce kod yazmamayı söylüyor.

İyi tasarım soyutlama kullanmak diyor.

İkisine de sahip olabilirsin. Bir sınıf bir soyutlamadır.


0

İşaretçi neden arayüzlenir? Bana "etiketleme" den başka bir şey yapmadığını vurur. Her fabrika tipi için farklı bir "etiket" ile ne anlamı var?

Bir arayüzün amacı, bir sınıfa "davranış gibi" davranışı vermek, onlara "depo yeteneği" kazandırmaktır. Öyleyse, tüm somut havuz türleriniz aynı IRepository gibi davranırsa (hepsi de IRepository uygular) o zaman hepsi aynı kodla başka bir kodla ele alınabilir. Bu noktada tasarımınız genişletilebilir. Daha fazla somut depo türü eklemek, tümü genel IRepository (ler) olarak işlenir - aynı kod tüm somut türleri "genel" depolar olarak işler.

Arayüzler ortak noktalara dayanan şeyleri ele almak içindir. Ancak özel marker arayüzleri a) davranış eklemiyor. ve b) benzersiz olmaları için sizi zorlar.

Yararlı arayüzler tasarladığınız ölçüde, OO'nun özel sınıfları, türleri veya somut sınıflarla 1: 1 korelasyonu olan özel işaretleme arayüzlerini işlemek için özel kod yazmak zorunda kalmama durumu konusunda iyiliğe sahip olursunuz. Bu anlamsız fazlalık.

Kapalı durumdayken, örneğin, çok sayıda farklı sınıfın kuvvetle yazılmış bir koleksiyonuna ihtiyacınız varsa, bir işaretleyici arayüzü görebiliyorum. Koleksiyonda hepsi "ImarkerInterface" ler. Ama onları çıkardıkça onları uygun tiplerine atmanız gerekiyor.


0

Şu anda, belli belirsiz makul bir ICO Müşteri Deposu yazabilir misiniz? Örneğin, müşterilerinizin her zaman PayPal'ı kullandıkları geçmişte (gerçekten buraya, muhtemelen kötü bir örnek) Ya da şirketteki herkes Alibaba ile bağlantı kurmaktan vazgeçmiyor mu? Öyleyse, şimdi daha karmaşık tasarımı kullanmak isteyebilir ve patronlarınız için çok uzaklara bakabilirsiniz. :-)

Aksi halde bekleyin. Bir veya iki gerçek uygulamanız olmadan bir arabirimde tahmin etmek genellikle başarısız olur. Başka bir deyişle, genelleştirilecek birkaç örnek bulana kadar süslü bir tasarım desenini genelleştirmeyin / soyutlamayın / kullanmayın.

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.