Nesne yönelimli kod yazarken daima bir tasarım deseni izlemeli miyim?


37

Herhangi bir nesne yönelimli program için akla gelebilecek bir tasarım deseni var mı? Bunu sordum çünkü son zamanlarda a Doorile bir sınıfın bir uygulamasını gördüm Lock. Testin bir parçasıydı ve cevap, kodun Boş Nesne desenini takip ettiğini söyledi:

class Lock
{
public:
    virtual void close() = 0;
    virtual void open() = 0;
    virtual bool is_open() const = 0;
    virtual ~Lock() { }
};

class DummyLock
    : public Lock
{
private:
    DummyLock();
    DummyLock(const DummyLock&) = delete;
    DummyLock& operator=(const DummyLock&) = delete;

private:
    void close() { }
    void open() { }
    bool is_open() const { return true; }

public:
    static DummyLock m_instance;
};

class Door
{
public:
    Door() : m_lock(DummyLock::m_instance) { }
    Door(Lock &lock) : m_lock(lock) { }

public:
    Lock& get_lock() const { return m_lock; }

private:
    Lock &m_lock;
};

Bu bana şunu düşündürdü: Bu kod, açıklama çok basit olsa da (bu sınıf kilitli bir kapı sınıfı tasarlıyor) iyi bir tasarım deseni izler, bu yüzden daha karmaşık bir kod yazıyorsam, her zaman benim takip ediyorum



51
Tamamen deyimlerle konuşabileceğinizi düşünüyor musunuz? Hayır? Öyleyse, programlarınızı tasarım desenlerini birleştirerek oluşturmamalısınız.
Kilian Foth

4
Örneğinizde, Null nesne kalıbı yalnızca akademik amaçlar için eklenmiştir, bu koda "iyi bir tasarım" sunmaz.
Doc Brown

4
@djechlin: Başka bir deyişle, "iki kelimeli" tasarım desenini kullanın :)
Michael Shaw

11
Sorun, çok fazla insanın, tasarım modellerinin düşünce için bir ikame ve deneyim için bir ikame olduğuna (belirli bir deneme ve yanılma anlamına geldiğine) inanıyor olmasıdır. Önemsiz boyut ve karmaşıklık ve iyi kalitede bir uygulama üretmek için tasarım desenleriyle dolu bir kitabı alamaz ve bunları Tinker Toys gibi bir araya getiremezsiniz. Deneyimli programcıların bile, işe yarayan bir tane bulana kadar genellikle iki veya üç tasarım denemesi gerekir.
Daniel R Hicks,

Yanıtlar:


143

her zaman takip ettiğim bir tasarım deseni olmalı mı?

Sevgili Tanrım, hayır!

Yani, devam edebilir ve herhangi bir rastgele kodun bazı rastgele XYZ düzenini takip ettiğini söyleyebilirsin, ama bu bilgisayar sandalyemin kralı olduğumu iddia etmekten daha kullanışlı değil. Başka kimse gerçekten ne bildiğini o vasıta ve hatta tam olarak benim iddia saygı duymayacaktır yapmak olanlar.

Tasarım kalıpları bir iletişim aracıdır, böylece programcılar diğer programcılara ne yaptığını ya da kendilerini tekrar etmek için çok fazla zaman harcamaksızın ne yapılması gerektiğini söyleyebilirler. Ve bir çok kez gelen şeyler olduklarından, programcıların "hey, XYZ'i her zaman ortaya çıkmış gibi görünüyor çünkü iyi / yararlı" olarak öğrenmesi için yararlı kavramlar.

Onlar yok önünüzde eşsiz sorun için terziye, desenleri kendiniz için düşünmek ihtiyacını değiştirmek veya güzel kova sığmayan kaçınılmaz şeylerin hepsini işlemek için.


5
İlk paragrafınız buna nasıl cevap vereceğimin bir parçası. Bir şey tekrarlandığında bir kalıp haline gelir . İletişim gerektirecek kadar tekrar edilirsa, bir Kalıptır ve bir addan yararlanır. Hatta bazı soyutlamalar eksik olduğundan, sadece bir kalıbın geliştiğini bile iddia ediyor. Desenlerin peşinde koşmak, değerli Kargo Tarikatının bir üyesi olarak rezil olmaya giden yoldur.
Magus

11
@Cerad: Elbette, Tanrı sınıflarını da yazmayacağına söz verdiğin sürece!
yatima2975

9
John Doe - Teknik Mühendis, Genel Kod Maymun ve bilgisayar koltuğunun kralı
hjk

1
Muhtemelen, bir tasarım uygun yerlerde kalıpları kullanmalı ve sınıflar böyle adlandırılmalıdır. Onlar önemli bir araçtır. the_cult(Tm) 'den korkmak da aynı derecede tehlikeli.
Gusdor

25
Mükemmel cevap! Tek eleştirim "Sevgili Tanrım HAYIR!" yeterince büyük değil.
tobyink

37

Hayır.

Dörtlü Çetenin (aslında tasarım desenlerini popülerleştiren) kitaplarında söylediği şey buydu :

“Tasarım kalıplarının nasıl kullanılacağına dair hiçbir tartışma, onları nasıl kullanmayacağınıza dair birkaç söz olmadan tamamlanmış sayılmaz . Tasarım kalıpları ayrım gözetmeksizin uygulanmamalıdır. Genellikle, ek bir dolaylı seviyeler getirerek esneklik ve değişkenlik elde ederler ve bu da bir tasarımı karmaşıklaştırabilir. ve / veya size bazı performanslara mal oldu. Bir tasarım deseni, yalnızca sağladığı esnekliğe gerçekten ihtiyaç duyulduğunda uygulanmalıdır. ”

Gösterdiğiniz örnek aslında hiçbir şey yapmıyor (bence bunun bir örnek olması gerektiğini sanmıyorum). Kendi başına boş nesne kalıbına ihtiyaç duymaz. Daha büyük bir program bağlamında olabilir.

Yanlış yaklaşım, sadece bir "tasarım deseni" olarak etiketlendiği için iyi olması gerektiği ve ardından daha fazla kalıpları tıkamak için daha fazla yer arayacağı varsayımıdır. Programa uyduklarında bunları kullanın ve aslında sizin için bir problemi çözün.


7
Kitabın Tasarım Desenleri: Erich Gamma, Richard Helm, Ralph Johnson ve John Vlissides'in Yeniden Kullanılabilir Nesneye Yönelik Yazılımın Elemanları.
developerwjk

4
+1 Aslında tasarım modellerinin kaynağını alıntılamak için.
Pharap

29

daha karmaşık kod yazıyorsam, her zaman takip ettiğim bir tasarım deseni olmalı mı?

Hayır. Tasarım kalıpları tam olarak bu: nesneler arasındaki ilişkilerde kalıplar . Başka bir deyişle, birinin kullandığı sık sık kullanılan ve yeniden kullanılan ilişkiler "Hey, bunu çok yapıyor gibi görünüyoruz, bir isim verelim." Tasarım kalıplarının listesi OOP'nin başında bir kerede belirlenmedi ve ardından GOF ! Onlar keşfedildi ve sonunda belgelendi ve daha sonra kitap tarafından popülerleştirildi.

Bununla birlikte, tasarım modellerinin yararının büyük bir kısmı, yazılım tasarımı hakkında daha üst düzeyde düşünmeyi kolaylaştırmalarıdır. Uygulama detayları hakkında endişelenmeyi atlamanıza ve büyük resim hakkında daha fazla düşünmenize izin veriyorlar. Bu anlamda sizi minutiden kurtarırlar, ancak aynı zamanda sizi ifade etme biçiminizin bildiğiniz kelimelerle sınırlandırılabileceği gibi sizi de sınırlayabilirler. Bu nedenle, yaptığınız işlerin çoğu için bir tasarım deseni olduğu zamanlar gelebilir , çünkü bildiğiniz kalıplar sizin düşündüğünüz terimlerdir. Bir modeli kötüye kullandığınız ve bir şeyler yapmanın daha iyi yolları hakkında daha derin düşünmeniz gerekebilecek durumlar için gözlerinizi açık tutun.

Ayrıca, pratikte , belirli bir tasarım modelini, varolan bazı kodlardaki modeli, nesne çerçevesi gibi tanıyacak kadar uygulayamadığınızı fark edin. Yaygın tasarım kalıplarını bilmek, bir çerçevenin nasıl kullanılmasının amaçlandığını öğrenmeyi çok kolaylaştırır çünkü sınıflar arasındaki ilişkileri zaten anladığınız şekilde görebilirsiniz.


10

Tasarım desenlerinin iki avantajı var

  1. Diğer geliştiricilere tarif etmek kolaydır, çünkü insanlar genellikle kalıpların ne olduğu konusunda hemfikirdirler.
  2. Seleflerimiz tarafından oldukça düşünceli bir şekilde dövülmüş olma eğilimindedirler, bu yüzden güçlü ve zayıf yönleri iyi anlaşılır.

Her programın hedefleri olmalı

  1. İşe yarıyor. Nihai amaç ne olursa olsun yapmalı ya da kaç tasarım deseni kullandığınızın bir önemi yoktur. OO tasarım desenleri, problemi bitleri kolayca anlayabilmeyi kolaylaştırır, böylece çalışmasını kanıtlamak daha kolaydır.
  2. Okumak kolaydır. Tasarım desenlerinin güzel olduğu yer burasıdır. Çözdükleri OO sorunları karmaşıktır. Onları "standart" bir şekilde çözerseniz, bir sonraki geliştiricide daha kolay
  3. Büyümek kolaydır. Neredeyse 0 modern program herkesin planladığı yerde bitirir. Her program ilk sürümünden sonra büyür. OO kalıpları büyümede meraklı bir şekilde iyi olduğu bilinmektedir.

Bunların hepsi söyleniyor, OO tasarım modellerine yapılan her referansın "sadece iş başında iyiler" olduğunu unutmayın. Mükemmel değiller, ama bir nişi çok etkili dolduruyorlar. Çalışırken onları kullanın, çalışmadıklarında onlardan kaçının.

Örnek olarak, "karmaşık kod" ile ilgili sorunuzda belirttiğim gibi yazdığım bir betik dilini alın. Her yerde tasarım desenleri ile çoğu OO. Bununla birlikte, çöp toplayıcıyı yazmaya gelince, OO'nun tüm iddialarını usulsüzce düşürdüm, çünkü yapmam gereken belirli şeyler daha iyi moda bit bodur olarak modellendi. Finalistler yazmaya gelene kadar her şeyde bir OO modeli yoktur, bir kez daha OO tekrar faydalı bir model olmaya başladı. Herhangi bir pompa veya durum olmadan, kod tekrar OO tekniklerini tekrar kullanmaya başladı.

Ürün modelinizi daha iyi hale getirdiklerinde tasarım desenlerini kullanın; Ürününüzü daha kötü hale getirdiklerinde onlardan kaçının.


2
Bence son cümle en üste koyu veya özet olarak yazılmalıdır.
Pharap

5

Bu eğilimi biraz daha etkileyeceğim, çünkü cevap diğer cevapların izin verdiğinden daha ince. Yazdığınız her sınıf bir tasarım deseni kullanmamalı, ancak yazmanız en önemsiz olmayan programların kullanılması gerekir.

Herhangi bir tasarım deseni olmayan önemsiz bir program şunları gösterir:

  • Programınız o kadar benzersiz ki, bunun hiçbir bölümü programcılar tarafından daha önce karşılaşılan genel sorunlara benzemez. Veya
  • Programınız bu ortak sorunları içeriyor, ancak bunları daha önce hiç kimsenin düşünmediği şekilde daha iyi çözdünüz.

Her iki senaryo da pek olası değildir, alınma.

Bu, tasarım deseninin tasarımınızı sürmesi gerektiği veya ayırt etmeden bir tanesini yerleştirmeniz gerektiği anlamına gelmez, çünkü bunu yapmazsanız kötü görüneceğini düşünüyorsunuz. Yanlış tasarım deseni hiç yoktan daha kötü.

Bunun anlamı, genel programınızdaki bir tasarım deseni eksikliğine kod kokusu olarak bakmanız gerektiğidir. Tasarımınız daha temiz olamazsa, ikinci bir bakış atmanızı ve yeniden değerlendirmenizi sağlayan bir şey. Bu noktada tasarım modellerini bir programın dışında bırakmaya karar verirseniz, bu kasıtlı, bilinçli bir karar olmalı, gerçekleşmemeli.

Örneğin, "Bir kapı ve kilit modellemeliyim, hangi tasarım desenini kullanmalıyım?" Demezsiniz. Bununla birlikte, önce herhangi bir tasarım deseni kullanmadan tasarladıysanız, daha sonra "Bu kodda çok fazla boş kontrol var, merak etmeme yardımcı olacak bir tasarım deseni olup olmadığını" söyleyecektir.

Farkı gör? Bu ince ama önemli bir ayrım.


5
Tasarım kalıplarından çok daha yaygın sorunlar (ve ortak çözümleri) vardır. Tasarım desenleri, ortak tüm OO çözümlerinin bir kümesi değil, ortak OO çözümlerinin kataloglu bir alt kümesidir.
Michael Shaw,

1
'Önemsiz' ile ne demek istediğinizi tanımlayabilir misiniz? 'Önemsiz' teriminin öznel olduğu izlenimini edindim.
Pharap

1
Bu özneldir. Çalışmakta olan bir takımda yazacağınız ve sürekli olarak birden fazla bakıcı gerektiren bir program türü.
Karl Bielefeldt

Sorununuzu daha sonra görecek kadar şanslıysanız . Boş kontroller, elbette. Güvenlik açıkları? Programın bakımdan geçeceği diğer sinsi yollar? Sadece bir sonraki mühendisin ortaya çıkardığı problemler? Çok daha şanslı.
djechlin

"Bir kapı ve kilit modellemeliyim, arayüz ne olmalı? Performans sözleşmenin bir parçası mı olacak? Bir hizmet mi yoksa kütüphane mi kullanmalıyım? Kaynaklar nasıl geçilecek?" Hepsi sorulmalı ve temel olarak tasarım deseni olarak kabul edilen cevaplara sahip olmalısınız.
djechlin

4

Kırık soru Size GoF tarafından salınan çok fazla zararı ortadan kaldıracak yeni bir tasarım deseni tanımı vereyim: bir tasarım deseni iyi bir kodlama uygulamasıdır . Bu kadar.

Oldukça karmaşık herhangi bir modül, içinde birkaç tasarım modeline sahip olacaktır. Önbelleğe aldığınız her an muhtemelen hafif bir desendir, ancak bunu söylemezseniz programlama derecenizi iptal etmeyeceğim. Herhangi bir zamanda bir geri arama yaptığınızda, bir çeşit olay / yangın / geri arama düzenindesiniz. Eğer "statik" kelimesine sahipseniz, bir singletonunuz olur. Statik bir kurucunuz varsa, bir fabrika şablonuna sahipsiniz. Modülünüze bir kaynak geçerse, bağımlılık enjeksiyonunu kullanıyorsunuzdur.

"Tasarım deseni", GoF tarafından popüler olmayan, tüm kalıplar aynı seviyede olduğu gibi ses çıkaran ya da sınıf başına 3 ila 5 önerilen doktoru kullanmanız gerektiğini söyleyen, kesilmiş bir terimdir. Bir şeyi doğru yaptığınız bir şeyi doğru yaptığınız zaman, bu bir tasarım kalıbıdır . A for(;;), örneğin sonsuz bir döngüyü temsil etmek için kullanılan yaygın bir kalıptır.

Bir sürü tasarım deseni öğrenmeye çalışmamalısın. Programlama bilgisi tasarım desenleri tarafından indekslenmez! Aksine, iyi kod yazmayı kitap, blog okuyarak ve alanınızdaki konferanslara katılarak öğrenmelisiniz . Örneğin, zaten bağımlılık enjeksiyonunu kullanıyorsanız, ancak henüz etiketlemediyseniz, her zaman DI kullanarak veya bir IoC çerçevesi kullanmaktan faydalanabilirsiniz . Veya olayları ve geri aramaları doğrudan kodlamakta zorlanıyorsanız, gitmelisin Haskell'i öğrenin, böylece işlevsel tasarım modellerine aşina olursunuz ve kolaylaşır.

Ve eğer bütün sınıfınız başkasının doğru yaptığı büyük bir şey okuyorsa, neden tekerleği yeniden icat ediyorsunuz? Sadece eşyalarını kullan.


2
for(;;)Deyim hangi dilde ? Bu muhtemelen birinin "doğru" yaptığı bir şeyin en iyi örneği değildir.
Telastyn

1
@Telastyn C, C ++, Java, Javascript, C #.
djechlin

2
20 yılı aşkın programlamalarımda bunu C, C ++, Java veya C # yerine daha fazla (veya ) tercih eden birini görmedim . while(true)while(1)
Telastyn

1
@Telastyn stackoverflow.com/a/2611744/1339987 fwiw (gerçek) tercih etmeye başladım çünkü bana daha okunaklı görünüyor.
djechlin

1
Her zaman (;;) için kullanırım. Belli bir sebep yok, muhtemelen bir yerlerde okudum. Katılan hiçbir değişken ya da sabit olmadığı gerçeğini seviyorum. Her neyse, @Telastyn şimdi biriyle tanıştın .
Karınca

0

Her zaman OO tasarım ilkelerini izlemelisiniz (örneğin, modülerlik, bilgi gizleme, yüksek uyum, vb.). Tasarım kalıpları, özellikle KISS ilkesini göz önünde bulundurursanız, OO tasarım ilkelerinin nispeten rafine edilmiş bir hedefidir .

Desenler, ortak tasarım problemlerinin çözümleridir. Bu problemler iki yerden birinden (veya ikisinin bir karışımından) gelir: problem alanı (örneğin, bir şirkette İnsan Kaynaklarını yöneten yazılım) ve çözüm alanı . Bir OO programları çözüm alanı içindeki bir örnektir (örneğin, İK yönetimini kolaylaştırmak için bir OO programı tasarlayabilmenizin birçok yolundan biri).

Bir modelin ne zaman kullanılacağını bilmek çok kolay değil. Bazı modeller düşük seviyelidir, kodlamaya ve çözüm alanına daha yakındır (örneğin, Singleton, Null nesnesi, Yineleyici). Diğerleri problem alanındaki gereksinimler tarafından motive edilir (örneğin, geri al / yinelemeyi destekleyen komut deseni, çoklu giriş / çıkış dosyası türlerini destekleme stratejisi).

Gelecekte, yazılımın çeşitlemelerini destekleme gereksiniminden birçok model geliyor. Bu varyasyonları hiçbir zaman yapmanız gerekmiyorsa, bir desen aşırı tasarım olabilir. Bir örnek, mevcut harici İK veri tabanı ile çalışmak için Adaptör modelini kullanmak olabilir. Mevcut veritabanı Oracle ile çalıştığından ve gelecekte NoSQL'i desteklemek isteyebileceğinizden Adapter'i uygulamaya karar veriyorsunuz. NoSQL hiçbir zaman kurumunuza gelmezse, bu Adaptör kodu çok işe yaramaz olabilir. YAGNI'ye bakınız . Asla gelmeyen çeşitler için destek tasarım desenini yanlış kullanmaktır.


0

Desenler, yaygın sorunlara ortak çözümlerdir. Her zaman bazı kalıpları takip ediyoruz, GoF'un kalıpları en çok tekrar edenlere hitap ediyor. Bu, yazılım mühendisleri tarafından bilinen paylaşılan bir anlayışın ve paylaşılan bir yaklaşımın olması.

Bu, cevabım hayır, ama evet, her zaman kendi tarzını takip ediyorsun dedi. GoF'un haklı olarak söylediği gibi ...

Bir kişinin Deseni başka bir kişinin ilkel yapı taşıdır.

Harika bir teklif.


Bu, önceki 7
cevapta

İnce. Not: Genel bir noktaya değindim ... Tasarım Desenlerine teorik bir tartışma olarak uygulanabilir.
Syed Priom

"Bu site tamamen cevap almakla ilgili . Bu bir tartışma forumu değil ..." ( tur )
gnat

Ben soruyu cevapladım. Teşekkür ederim. Bu konuşma burada bitiyor.
Syed Priom

@gnat, yine de çok daha özlü bir halt.
djechlin

0

Kod yazarken, kasıtlı olarak elimden geldiğince fazla tasarım deseni kullanmayı düşünmüyorum. Ancak, bilinçaltı olarak, bir kodlama problemi olduğunda, tasarım modellerinden biri uygun gözüküyor ve sadece onu kullanıyorum. Ve bazen hiçbir şey uymaz. Benim için daha önemli olan, işi yapan ve bakımı ve büyütmesi kolay olan kod yazmak.

İşte tasarım modellerini kullanarak OOD prensiplerini uygulama üzerine bir makale ve ayrıca kod örnekleri de var (C ++ 'da). Bazı tasarım desenlerinin temiz kod yazmak için nasıl ve ne zaman uygulanacağını gösterir.


2
Bu makale daha dün yazıldı; Hiç blog ile bağlı mısın? Eğer öyleyse, lütfen o üyeliği açıklayın .
Martijn Pieters
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.