Sürekli değişen projelerde tasarım kalıplarını kullanmaktan kaçınmalı mıyız?


32

Bir arkadaşım, her geliştiriciden nefret edeceği bir projede küçük bir şirket için çalışıyor: mümkün olduğu kadar çabuk serbest bırakılması için baskı yapıyor, teknik borcu önemseyen görünüyor, müşterinin teknik geçmişi yok.

Bana bunun gibi projelerde tasarım kalıplarının uygunluğunu düşündürten bir hikaye anlattı. İşte hikaye.

Ürünleri web sitesinde farklı yerlerde göstermek zorunda kaldık. Örneğin, içerik yöneticileri ürünleri, aynı zamanda son kullanıcıları veya ortakları API üzerinden görüntüleyebilir.

Bazen, ürünlerden bilgiler eksikti: örneğin, bir ürünün henüz yaratıldığı sırada hiçbir grubun fiyatı yoktu, ancak fiyat henüz belirlenmedi. Bazılarının tanımı yoktu (açıklama, değişiklik geçmişi, yerelleştirilmiş içerik vb. İçeren karmaşık bir nesnedir). Bazılarında gönderi bilgisi yoktu.

Tasarım kalıpları hakkındaki son okumalarımdan esinlenerek, bunun sihirli Null Nesne desenini kullanmak için mükemmel bir fırsat olduğunu düşündüm . Ben de yaptım ve her şey düzgün ve temizdi. Birinin product.Price.ToString("c")fiyatı görüntülemek veya product.Description.Currentaçıklamayı göstermek için araması gerekiyordu ; şartlı şeyler gerekli değildir. Bir güne kadar, bir paydaş, JSON'dayken API'de farklı şekilde gösterilmesini istedi null. Ayrıca içerik yöneticileri için "Fiyat belirtilmemiş [Değiştir]" i göstererek de farklıdır. Ve sevgili Null Nesne kalıbımı öldürmek zorunda kaldım, çünkü artık buna gerek yoktu.

Aynı şekilde, birkaç soyut fabrika ve birkaç inşaatçıyı çıkarmak zorunda kaldım, güzel Cephe desenimi doğrudan ve çirkin çağrılarla değiştirdim, çünkü temel arayüzler üç ay boyunca günde iki kez değişti ve hatta Singleton beni terk etti. Gereksinimler ilgili nesnenin içeriğe bağlı olarak farklı olması gerektiğini söylediğinde.

Üç haftadan fazla süren çalışma, tasarım kalıpları eklemek, ardından bir ay sonra parçalamaktan ibaretti ve kodum nihayet, kendim de dahil olmak üzere herkes tarafından bakımı imkansız olacak şekilde spagetti oldu. Bu kalıpları asla ilk başta kullanmamak daha iyi olmaz mıydı?

Aslında, gereksinimlerin sürekli değiştiği bu tür projeler üzerinde kendim çalışmak zorunda kaldım ve aklımda olmayan veya ürünün tutarlılığını gerçekten düşünmeyen insanlar tarafından dikte edildi. Bu bağlamda, ne kadar çevik olduğunuz önemli değildir, bir soruna zarif bir çözüm getireceksiniz ve sonunda uyguladığınızda, gereksinimlerin çok sert bir şekilde değiştiğini, zarif çözümünüzün uymayacağını öğreneceksiniz. artık.

Bu durumda çözüm ne olurdu?

  • Tasarım desenleri kullanmamak, düşünmekten vazgeçmek ve doğrudan kod yazmak mı?

    Bir takımın doğrudan kod yazdığı, bir diğeri yazmadan önce iki kez düşündüğü, orijinal tasarımını birkaç gün sonra atmak zorunda olma riskini aldığı bir deneyim yapmak ilginç olurdu: kim bilir, belki de her iki takımın da aynı teknik borç. Bu verilerin bulunmadığı durumlarda, 20 aylık bir proje üzerinde çalışırken önceden düşünmeden kod yazmanın doğru olmadığını iddia ediyorum .

  • Artık anlamlı olmayan tasarım desenini koru ve yeni oluşturulan durum için daha fazla desen eklemeye çalış.

    Bu da doğru görünmüyor. Desenler, kodun anlaşılmasını basitleştirmek için kullanılır; çok fazla desen koymak ve kod karışıklık haline gelecektir.

  • Yeni gereksinimleri kapsayan yeni bir tasarım düşünmeye başlayın, sonra eski tasarımı yavaşça yenisine yeniden yansıtın.

    Bir teorisyen ve Çevik’i tercih eden biri olarak, kesinlikle bu konuyla ilgileniyorum. Uygulamada, her hafta beyaz tahtaya geri dönmeniz ve önceki tasarımın büyük bölümünü yinelemeniz gerektiğini bildiğiniz ve müşterinin bunun için size ödeme yapacak kadar parası olmadığı ya da beklemek için yeterli zamanınız olmadığını bildiğiniz zaman , bu muhtemelen işe yaramaz.

Peki, herhangi bir öneriniz var mı?


43
Bunun yanlış bir ikilem olduğunu düşünüyorum. Arkadaşınızın kendi kabulüne göre, kod artık erişilemez bir spagetti tabağı. Bu, yazılım modellerinin hatası değil; Arkadaşınızın bu kalıpları düzgün bir şekilde kullanamaması, korunabilirliği artıracak şekilde azaltması değil. Belirli örnekler bulabildiğimde uygun bir cevap göndereceğim.
Robert Harvey,

5
Ayrıca, FWIW, sürüklenme maliyetlerine karşı toleransı olmayan herhangi bir müşteri, değiştirme gereksinimleri için maliyetler içine yerleştirilmiş ödenekler olmadıkça, muhtemelen Agile yapmamalıdır.
Robert Harvey,

5
tasarım desenleri olmadan, kodun daha önce erişilemez bir duruma ulaşacağından şüpheleniyorum
Steven A. Lowe,

28
Bu soru bir anlam ifade etmiyor. “Tasarım kalıplarından kaçınmanın” tek yolu hiçbir yazılımı yazmamaktır. "XYZ Paterni" gibi şeyler, programcıların kod yapımız ve seçeneklerimiz hakkında birbirimize daha rahat bilgi ve tavsiyeler iletmemize olanak tanıyan ortak kodlama stratejilerine verilen adlardır. Kodunuzdaki herhangi bir tasarım seçeneğine, her ne kadar yaygın olarak bilinmese de, bir isim verilebilir ve "tasarım deseni" olarak adlandırılabilir (benzersiz bir tasarımınızla gurur duyduğunuz ve bir isim ve blog hakkında yeterince bilgi verdiğiniz için motive olmadığınız sürece) o ya da bir şey).
Jason C,

9
Yani, ayağınıza "ayak" demekten kaçınabilirsiniz ama yine de o ayağınız var, "ayak" demiyorsanız, birisiyle konuşmanız daha zordur. “Tasarım kalıplarından kaçındığınızı” düşünebilirsiniz, ancak işe yarayan iyi bir tasarımla karşılaşırsanız, geri adım atın ve bakın, muhtemelen tasarımınızın zaten bilinen ortak kalıplardan birine uyduğunu görürsünüz, sen onu ara ya da ara.
Jason C

Yanıtlar:


86

Bu soruda bazı yanlış varsayımlar görüyorum:

  • Tasarım desenleri ile kod, doğru uygulanmasına rağmen, bu desenlerin olmadığı kodlardan ziyade uygulanması daha fazla zaman gerektirir.

Tasarım kalıpları kendi içinde bir amaç değildir, tam tersi değil, size hizmet etmelidirler. Bir tasarım deseni, kodun uygulanmasını kolaylaştırmazsa veya en azından geliştirilebiliyorsa (bu, değişen gereksinimlere uyarlanması daha kolay demektir), o zaman desen amacını özlüyor. Takım için "yaşamı" kolaylaştırmazlarsa kalıpları uygulamayın. Yeni Null nesne kalıbı, kullandığı süre boyunca arkadaşına hizmet ediyorsa, her şey yolundaydı. Daha sonra ortadan kaldırılacak olsaydı, bu da iyi olabilirdi. Boş nesne deseni (doğru) uygulamayı yavaşlattığında kullanımı yanlıştı. Unutmayın, öykünün bu bölümünden "spagetti kodu" na kadar herhangi bir sebep sonuçlanamaz.

  • Müşteri suçludur, çünkü teknik bir geçmişi yoktur ve ürünün uyumu veya tutarlılığı ile ilgilenmez

Bu ne onun işi ne de onun suçu! İşiniz uyum ve tutarlılığı önemsemek. Gereksinimler günde iki kez değiştiğinde, çözümünüz kod kalitesini feda etmek olmamalıdır. Sadece müşteriye ne kadar süreceğini söyleyin ve "doğru" tasarımı almak için daha fazla zamana ihtiyacınız olduğunu düşünüyorsanız, o zaman herhangi bir tahminde yeterince büyük bir güvenlik payı ekleyin. Özellikle sizi baskı altına almaya çalışan bir müşteriniz varsa, "Scotty Principle" kullanın . Teknik olmayan bir müşteriyle çaba hakkında tartışırken, "yeniden yapılandırma", "birim testleri", "tasarım desenleri" veya "kod dokümantasyonu" gibi terimlerden kaçının; saçma "çünkü hiçbir değeri görmez. veya en azından müşteri tarafından anlaşılabilir (özellikler, alt özellikler, davranış değişiklikleri, kullanıcı dokümanları, hata düzeltmeleri, performans optimizasyonu vb.).

  • hızlı değişim gereksinimleri için çözüm, kodu hızlı bir şekilde değiştirmektir.

Dürüst olmak gerekirse, "temeldeki arayüzler üç ay boyunca günde iki kez değişirse", çözümün kodu günde iki kez değiştirerek tepki vermemesi gerekir. Asıl çözüm, gereksinimlerin neden bu kadar sık ​​değiştiğini ve sürecin bu kısmında bir değişiklik yapmanın mümkün olup olmadığını sormaktır . Belki biraz daha net analiz yardımcı olabilir. Belki de arabirim çok geniştir çünkü bileşenler arasındaki sınır yanlış seçilmiştir. Bazen, gereksinimlerin hangi kısmının sabit olduğu ve hangilerinin hala tartışılmakta olduğu hakkında daha fazla bilgi istemek için yardımcı olur (ve tartışılan şeyler için uygulamayı erteler). Ve bazen bazı insanlar zihinlerini günde iki kez değiştiremedikleri için "kıçlarına tekmelemek" zorunda kalırlar.


30
+1 - İnsanların sorunlarını teknik çözümlerle çözemezsiniz.
Telastyn

1
+1, ancak "veya en azından daha iyi geliştirilebilir (bu: değişen gereksinimlere adapte olmak daha kolay)" - Bunu makul ölçüde değişen gereksinimlerle nitelendirebilirim , değil mi?
Fuhrmanator

1
@Fuhrmanator: Bunun genel anlamda tartışmanın zor olduğunu düşünüyorum. IMHO, ilk gereksiniminizin "bir kelime işlemcisine ihtiyacımız" olduğu ve hiçbirinin "bir uçuş simülatörüne ihtiyacımız" olduğu zaman hiçbir tasarım modelinin size yardımcı olamayacağı açıktır. Daha az sert gereksinim değişiklikleri için, yazılımınızı geliştirilebilir kılmak için neyin yardımcı olacağına karar vermek her zaman kolay değildir. En iyisi IMHO'nun çok fazla desen uygulamaması, ancak bazı prensiplerin - özellikle de SOLID prensipleri ve YAGNI'nin uygulanmasıdır. Ve Telastyn ile% 100 aynı fikirdeyim - gereksinimler çok sık değiştiğinde, muhtemelen teknik bir sorun değildir.
Doktor Brown,

4
+1 - "Dürüst olmak gerekirse, 'altta yatan arayüzler üç ay boyunca günde iki kez değişirse', o zaman çözüm, kodu günde iki kez değiştirerek tepki vermemelidir. Gerçek çözüm gereksinimlerin neden bu kadar sık ​​değiştiğini sormaktır. Sürecin bu kısmında bir değişiklik yapmak mümkündür. ”Eğer sürekli yeni talimatlar alıyorsanız, tüm paydaşlarla oturup en iyisi beklentilerin ne olduğunu ortaya koymaktır. Farklılıklarınızı giderin ve umarım projeye daha net bir hedef vererek herkesin zamanını ve parasını boşa harcamayın.
krillgar

1
@Cornelius Doc Brown, beton olmadan zor olduğunu söyledi. Bir kelime işlemcisinden bir uçuş simülatörüne gitmek için gerekenler makul olmaz; hiçbir tasarım deseni yardımcı olmaz. Örneği arasında bir çok gri alan var, yani bir kelime işlemcisinin Kaydet işlevine (çok makul olan) yeni bir dosya formatı ekleniyor. Spesifikasyonlar olmadan tartışması zor. Ayrıca, biri değişmek istemez . Zaten bir gereksinime dayanarak bir tasarım seçimi yaptıysanız, bu tür değişikliklerin zor olması. Flight sim kelimesine göre işlemci sim, erken seçim için mükemmel bir örnektir.
Fuhrmanator

43

Benim düşünceme göre tasarım kalıplarını kullanmaktan kaçınmamanız veya kaçınmamalısınız.

Tasarım kalıpları, basitçe bilinen ve isimleri verilen genel sorunların güvenilir çözümleridir. Teknik olarak, aklınıza gelebilecek herhangi bir çözüm veya tasarımdan farklı değildir.

Sorunun kökeninin, “kalıpları da dahil ancak bunlarla sınırlı olmamak üzere“ aklıma gelen en iyi çözüm nedir? Biliyorum".

Belki bu yaklaşım, desenleri, kısmen yapay veya zorla, ait olmadıkları yerlerde kullanmaya zorlar. Ve bu bir karmaşa ile sonuçlanan budur.


13
+1 "Tasarım kalıpları, genel sorunların isimleri verilen basitçe iyi bilinen ve güvenilir çözümlerdir. Teknik olarak, aklınıza gelebilecek herhangi bir çözüm veya tasarımdan farklı değildir." Kesinlikle. İnsanlar, adlandırılmış tasarım modellerine o kadar kapılıyorlar ki, programcıların kodumuz ve tasarım seçimlerimiz hakkında birbirimizle iletişim kurmasını kolaylaştırmak için çeşitli stratejilere verilen adlardan başka bir şey olmadığını unutuyorlar. Bu tutum çok sık , mutlaka yararlanmayan problemlere uygunsuz "kalıpları" zorlama girişimi ile ilişkilidir - büyük karışıklık.
Jason C

14

Null Object kalıbını kullanma örneğinizde, programcının müşterinin ihtiyaçlarını değil, programcının ihtiyaçlarını karşıladığı için sonuçta başarısız olduğuna inanıyorum. Müşterinin fiyatı, içeriğe uygun bir biçimde görüntülemesi gerekiyordu. Programcının bazı ekran kodunu basitleştirmesi gerekiyordu.

Öyleyse, bir tasarım deseni gereksinimleri karşılamadığında, tüm tasarım kalıplarının zaman kaybı olduğunu mu söylüyoruz yoksa farklı bir tasarım modeline ihtiyacımız olduğunu mu söylüyoruz?


9

Desen nesnelerini kaldırmak, onları kullanmaktan daha çok yanlıştı. İlk tasarımda, Null Nesnesi bir soruna bir çözüm sağlamıştır. Bu en iyi çözüm olmayabilir.

Bir proje üzerinde çalışan tek kişi olmak size tüm gelişim sürecini deneyimleme şansı verir. En büyük dezavantaj, akıl hocanız olacak birinin olmamasıdır. En iyi veya daha iyi uygulamaları öğrenmek ve uygulamak için zaman ayırmanın hızlı bir şekilde gerçekleşmesi muhtemeldir. İşin püf noktası, hangi uygulamanın ne zaman öğrenileceğini tespit etmektir.

Product.Price.toString ('c') formundaki zincir referansları Demeter Yasasını ihlal ediyor . Bu uygulamada birçoğu null ile ilgili her türlü sorunu gördüm. Product.displayPrice ('c') gibi bir yöntem dahili olarak null fiyatları kaldırabilir. Aynı şekilde, ürün. veya product.diplay ('Geçerli').

Yöneticiler ve içerik sağlayıcılar için yeni gereksinimin ele alınması, içeriğe cevap vererek ele alınmalıdır. Kullanılabilecek çeşitli yaklaşımlar vardır. Fabrika yöntemleri, görüntülenecekleri kullanıcı sınıfına bağlı olarak farklı ürün sınıfları kullanabilir. Başka bir yaklaşım, farklı kullanıcılar için farklı veriler oluşturmak için ürün sınıfı görüntüleme yöntemleri için olacaktır.

İyi haber şu ki, arkadaşın işlerin elinden geldiğini fark ediyorsun. Umarım, revizyon kontrolünde kodu vardır. Bu onun her zaman alacağı kötü kararları geri almasına izin verecektir. Öğrenmenin bir kısmı, bazıları başarısız olacak olan farklı yaklaşımları denemektir. Önümüzdeki birkaç ay boyunca başa çıkabilirse, hayatını kolaylaştıran ve spagetti'yi temizleyen yaklaşımlar bulabilir. Her hafta bir şeyi düzeltmek için çalışmayı deneyebilirdi.


2
Ayrıca, Demeter'in yasasını çiğnemek zorunda kaldığınızı, yüzeyde kullanılan modelin uygun olmadığını da gösterebilir. "Görüntüle modeli" (gevşek anlamda kullanılan) neden sadece gösterilecek açıklamaya sahip değil? (Yani, neden UI seviyesindeki mevcut düşüşten daha fazlası var?) İş katmanı, yönetici olup olmamasına bağlı olarak zaten farklı içeriğe sahip olan UI katmanına uygun şekilde doldurulmuş bir nesne hazırlayabilir.
Cornelius

7

Soru pek çok noktada yanlış gibi görünüyor. Ancak en bariz olanlar:

  • Bahsettiğiniz Null Object Pattern için, gereksinimler değiştikten sonra, kodun bir kısmını değiştirirsiniz. Bu iyi, ancak Boş Nesne Örüntüsünü 'öldürdüğünüz' anlamına gelmez (btw, ifadelerinize dikkat edin, bu çok aşırı geliyor, bazı insanlar paranoyak bunu hiç komik görmeyecek).

Birçok insan doğru demiştir, tasarım kalıpları çok yaygın bir uygulamayı etiketlemek ve adlandırmakla ilgilidir. Bir gömleği düşünün, bir gömleğin yakası vardır, bir nedenden dolayı yakayı veya yakanın bir kısmını çıkarırsınız. Adlandırma ve etiketleme değişir, ama yine de özünde bir tişört. Bu tam olarak buradaki durum, ayrıntılı olarak bu değişiklikler 'sizin de öldürdüğünüz' anlamına gelmeyen küçük değişiklikler. (yine aşırı ifadelere dikkat edin)

  • Bahsettiğiniz tasarım kötü, çünkü gereksinim değişiklikleri küçük şeyler olarak ortaya çıktığında, her yerde büyük stratejik tasarım değişiklikleri yapıyorsunuz. Üst düzey işletme sorunu değişmezse, büyük tasarım değişikliği yapmayı haklı çıkaramazsınız.

Tecrübelerime göre, küçük gereksinimler ortaya çıktığında, kod tabanının yalnızca küçük bir kısmını değiştirmeniz gerekir. Bazıları biraz kırılgan olabilir, ancak sürdürülebilirliği veya okunabilirliği önemli ölçüde etkileyemeyecek kadar ciddi hiçbir şey yoktur ve hack kısmını açıklamak için genellikle birkaç yorum satırı yeterli olacaktır. Bu da çok yaygın bir uygulamadır.


7

Bir an için duralım ve buradaki temel konuya bakalım - Mimari modelin sistemdeki düşük seviyeli özelliklere çok fazla bağlı olduğu bir sistemi inşa etmek, mimarlığın geliştirme sürecinde sık sık kırılmasına neden olmak.

Bununla ilgili mimari ve tasarım kalıplarının kullanımının uygun bir seviyede atılması gerektiğini ve doğru seviyenin ne olduğunun analizinin önemsiz olmadığını hatırlatmamız gerektiğini düşünüyorum. Bir yandan, "MVC" veya benzeri gibi çok temel kısıtlamalarla mimariyi sisteminizi çok yüksek bir seviyede kolayca tutabilirsiniz; bu, net kurallar ve kod kaldıracında olduğu gibi kaçırılmış fırsatlara neden olabilir ve spagetti kodunun kolayca Tüm bu boş alanda gelişmek.

Öte yandan, kısıtlamaları ayrıntılı bir düzeye koyarken olduğu gibi, gerçekte beklediğinizden daha değişken olan kısıtlamalara dayanabileceğinizi varsayarak, kısıtlamalara sürekli olarak dayandığınızı varsayarsanız, sisteminizi aşırı mimara getirebilirsiniz. sizi ümitsizliğe başlayana kadar sürekli olarak yeniden şekillenmeye ve yeniden inşa etmeye zorlamak.

Bir sistem için gereksinimlerdeki değişiklikler her zaman orada olacak, daha az veya daha büyük ölçüde. Ve mimari ve tasarım kalıplarını kullanmanın potansiyel yararları her zaman orada olacak, bu yüzden tasarım kalıplarını kullanmanın ya da kullanmamanın bir sorumu yok, ama onları hangi seviyede kullanmanız gerektiği.

Bu, yalnızca önerilen sistemin mevcut gerekliliklerini anlamanızı değil, aynı zamanda sistemin hangi yönlerini sistemin istikrarlı temel özellikleri olarak görebileceğini ve geliştirme sürecinde hangi özelliklerin değişebileceğini tanımlamanızı gerektirir.

Organize olmayan spagetti koduyla sürekli mücadele etmek zorunda kaldığınızı tespit ederseniz, muhtemelen yeterince mimarlık yapmıyorsunuzdur ya da yüksek seviyede. Mimarinizin sık sık kırıldığını tespit ederseniz, muhtemelen çok ayrıntılı bir mimari yapıyorsunuzdur.

Mimari ve tasarım kalıplarının kullanımı, bir masayı boyar gibi bir sistemi “kaplayabileceğiniz” bir şey değildir. Onlar, güvenmeniz gereken kısıtlamaların istikrarlı olma olasılığının yüksek olduğu ve bu tekniklerin gerçekte mimarlığı modelleme ve gerçek kısıtlamaları / mimarlık / kalıpları uygulama zorluğuna değer olduğu bir seviyede, dikkatlice uygulanması gereken tekniklerdir. kod olarak.

Çok detaylı bir mimarinin konusu ile ilgili olarak, çok fazla değer vermediği mimarlıkta çok fazla çaba gösterebilirsiniz. Referans olarak risk odaklı mimariyi görün, bu kitabı beğendim - Yeterince Yazılım Mimarisi , belki siz de.

Düzenle

Cevabımı netleştim, çünkü kendimi sık sık aynı olmayan "çok detaylı mimari" anlamına geldiğim "çok fazla mimari" olarak sık sık ifade ettiğimi farkettim. Çok ayrıntılı mimari, genellikle "çok fazla" mimari olarak görülebilir, ancak mimariyi iyi bir seviyede tutsanız ve insanlığın gördüğü en güzel sistemi oluştursanız bile, bu öncelikler ise, mimarlık için çok fazla çaba olabilir. özellikleri ve pazara zaman.


+1 Bunlar çok yüksek seviyeler hakkında çok iyi düşünceler. Bir sisteme bakmanız gerektiğini düşünüyorum ama dediğiniz gibi yazılım tasarımında çok fazla deneyim gerektirir.
Samuel,

4

Arkadaşınız fıkralarına dayanarak çok sayıda kafa çarpmasıyla karşı karşıya görünüyor. Bu talihsiz bir durumdur ve çalışmak için çok zor bir ortam olabilir. Zorluğa rağmen, hayatını kolaylaştırmak için kalıpları kullanmak için doğru yoldaydı ve bu yolu terk etmesi çok utanç verici. Spagetti kodu nihai sonucudur.

İki farklı problem alanı olduğu için, teknik ve kişilerarası, her birini ayrı ayrı ele alacağım.

kişilerarası

Arkadaşınızın yaşadığı mücadele hızla değişen gereksinimlerle ve bunun sürdürülebilir bir kod yazma yeteneğini nasıl etkilediğiyle ilgilidir. Öncelikle, günde iki kez değişen gereksinimlerin, her gün bu kadar uzun bir süre boyunca daha büyük bir sorun olduğunu ve gerçekçi olmayan örtük bir beklentisi olduğunu söyleyebilirim. Gereksinimler , kodun değiştirebildiğinden daha hızlı değişiyor . Kodun veya programcının yetişmesini bekleyemeyiz. Bu hızlı değişim hızı, istenen ürünün daha yüksek bir düzeyde eksik bir anlayışına işaret ediyor. Bu bir problem. Gerçekten ne istediklerini bilmiyorlarsa, asla alamamak için çok zaman ve para harcıyorlar.

Değişikliklerin sınırlarını belirlemek iyi olabilir. Her iki haftada bir set halinde grup halinde değişiklik yapın, ardından uygulandıkları sırada iki hafta boyunca onları dondurun. Gelecek iki haftalık dönem için yeni bir liste oluşturun. Bu değişikliklerin bazılarının örtüşme veya çelişki hissi yaşadım (örneğin, iki seçenek arasında gidip geliyor). Değişiklikler hızlı ve öfkeli olduğunda, hepsinin önceliği vardır. Listede birikmelerine izin verirseniz, çabaları ve üretkenliği en üst düzeye çıkarmak için en önemli olanı düzenlemek ve öncelik sırasına koymak için onlarla birlikte çalışabilirsiniz. Bazı değişikliklerinin aptalca ya da daha az önemli olduğunu görebilir, arkadaşınıza biraz soluk odası verebilir.

Bu sorunların olsa iyi kod yazmanızı engellememesi gerekir. Kötü kod daha kötü sorunlara yol açar. Yeniden çözümlemek bir çözümden diğerine zaman alabilir, ancak bunun mümkün olduğu gerçeği , iyi kodlama uygulamalarının kalıplar ve ilkeler yoluyla faydalarını göstermektedir.

Sık sık değişiklik yapılan bir ortamda teknik borç bir noktada ortaya çıkacaktır . Havluya atmak yerine ödemeleri yapmak ve üstesinden gelemeyecek kadar büyüyene kadar beklemek daha iyidir. Bir örüntü artık kullanışlı değilse, yeniden ayırın, ancak kovboy kodlama yöntemlerine geri dönmeyin.

Teknik

Arkadaşınız temel tasarım kalıplarını iyi kavramış gibi görünüyor. Boş nesne, karşılaştığı soruna iyi bir yaklaşımdır. Aslında, hala iyi bir yaklaşım. O zorlukları var gibi görünüyor durumlarda, desen arkasında ilkelerini anlamaktır neden bunların neler olduğu. Aksi takdirde, yaklaşımını bırakacağına inanmıyorum.

(Aşağıda, asıl soruda istenmemiş, ancak açıklama amaçlı desenlere nasıl yapabileceğimizi gösteren bir dizi teknik çözüm var.)

Boş nesnenin arkasındaki ilke, değişken olanı içine alma fikridir . Nelerin değiştiğini saklıyoruz, böylece başka hiçbir yerde uğraşmak zorunda kalmayacağız. Burada, null nesnesi product.Priceörnekte varyansı kapsıyordu (ben ona bir Pricenesne diyeceğim ve null nesne fiyatı olacaktır NullPrice). Pricebir etki alanı nesnesidir, işletme kavramıdır. Bazen, iş mantığımızda, henüz fiyatı bilmiyoruz. Bu olur. Boş nesne için mükemmel kullanım çantası. fiyatını veren Pricebir ToStringyöntem var veya bilinmiyorsa NullPrice#ToStringboş dize (veya boş bir dize döndürür). Bu makul bir davranış. Sonra gereksinimler değişir.

Biz çıkış a zorunda nullAPI görünümü veya yöneticilerinin görünümüne farklı bir dizeye. Bu iş mantığımızı nasıl etkiler? Öyle değil. Yukarıdaki ifadede, 'görünüm' kelimesini iki kere kullandım. Bu kelime muhtemelen açıkça söylenmedi, ancak gereksinimlerdeki gizli kelimeleri duymak için kendimizi eğitmeliyiz. Öyleyse 'görüş' neden bu kadar önemli? Çünkü bize değişimin gerçekten nerede olması gerektiğini söyler: bize göre.

Bir yana : MVC çerçevesi kullanıp kullanmamamız burada önemsiz. MVC'nin “Görünüm” için çok özel bir anlamı olsa da, bir sunum kodu parçasının daha genel (ve belki de daha uygulanabilir) anlamında kullanıyorum.

Bu yüzden bunu gerçekten düzeltmemiz gerekiyor. Bunu nasıl yapabiliriz? Bunu yapmanın en kolay yolu bir ififadedir. Null nesnesinin tüm ifs'lerden kurtulmak istediğini biliyorum, ama pragmatik olmak zorundayız. Boş olup olmadığını görmek için dizeyi kontrol edebiliriz ve şunu değiştirebiliriz:

if(product.Price.ToString("c").Length == 0) { // one way of many
    writer.write("Price unspecified [Change]");
} else {
    writer.write(product.Price.ToString("c"));
}

Bu, kapsüllemeyi nasıl etkiler? Buradaki en önemli kısım, görünüm mantığının görünümde kapsüllenmesidir . İş mantığımızı / etki alanı nesnelerimizi görünüm mantığındaki değişikliklerden bu şekilde tamamen izole edebiliriz. Çirkin, ama işe yarıyor. Ancak bu tek seçenek değil.

Herhangi bir fiyat belirlenmemişse, varsayılan mantıkları çıkarmak istediğimiz için iş mantığımızın biraz değiştiğini söyleyebiliriz. Metodumuzda küçük bir ince ayar yapabiliriz Price#ToString(aslında aşırı yüklenmiş bir yöntem oluşturur). Varsayılan bir getiri değeri kabul edebilir ve eğer fiyat belirlenmediyse geri dönebiliriz:

class Price {
    ...
    // A new ToString method
    public string ToString(string c, string default) {
        return ToString(c);
    }
    ...
}

class NullPrice {
    ...
    // A new ToString method
    public string ToString(string c, string default) {
        return default;
    }
    ...
}

Ve şimdi bizim bakış kodumuz:

writer.write(product.Price.ToString("c", "Price unspecified [Change]"));

Koşullu gitti. Ancak, bunu çok fazla yapmak, etki alanı nesnelerinizde özel durum yöntemlerini çoğaltabilir; bu nedenle, yalnızca bunun birkaç örneği olacaksa, bu mantıklı olur.

Bunun yerine bir boole döndüren bir IsSetyöntem oluşturabiliriz Price:

class Price {
    ...
    public bool IsSet() {
        return return true;
    }
    ...
}

class NullPrice {
    ...
    public bool IsSet() {
        return false;
    }
    ...
}

Mantığı görüntüle:

if(product.Price.IsSet()) {
    writer.write(product.Price.ToString("c"));
} else {
    writer.write("Price unspecified [Change]");
}

Koşullu maddenin iadesini görünümde görüyoruz, ancak iş mantığında fiyatın ayarlanmış olup olmadığını söylemek için durum daha güçlü. Artık Price#IsSetbaşka bir yerde kullanabiliriz.

Son olarak, görüş için tamamen bir yardımcının fiyatını sunma fikrini özetleyebiliriz. Bu, koşullu nesneyi, etki alanı nesnesini istediğimiz kadar koruyarak gizler:

class PriceStringHelper {
    public PriceStringHelper() {}

    public string PriceToString(Price price, string default) {
        if(price.IsSet()) { // or use string length to not change the Price class at all
           return price.ToString("c");
        } else {
            return default;
        }
    }
}

Mantığı görüntüle:

writer.write(new PriceStringHelper().PriceToString(product.Price, "Price unspecified [Change]"));

Değişiklik yapmak için daha birçok yolu vardır (biz genelleme olabilir PriceStringHelperbir nesne içine döner bir dize boş ise varsayılan), ancak bunlar (çoğunlukla) korumak birkaç hızlı olanlar desenleri hem ve ilkeleri, olarak sıra böyle bir değişiklik yapma pragmatik açıdan.


3

Bir tasarım modelinin karmaşıklığı, sorunu aniden çözmesi gerekiyorsa sizi ısırdırabilir. Ne yazık ki, tasarım kalıplarının coşkusu ve popülaritesi nedeniyle, bu risk nadiren açıkça ortaya çıkmaktadır. Arkadaşınızın anekdotu, kalıpların nasıl para kazanmadığını göstermek için çok yardımcı olur. Jeff Atwood'un konuyla ilgili bazı sözcükleri var.

Gereksinimlerde doküman varyasyon noktaları (risktir)

Daha karmaşık tasarım modellerinin birçoğu (Null Object çok fazla değil) “Öngörülen değişkenlik veya dengesizliklerin noktalarını belirleyin; çevrelerinde sabit bir arayüz oluşturmak için sorumluluklar verin” olan Korumalı varyasyonlar kavramını içerir . Adaptör, Ziyaretçi, Cephe, Katmanlar, Gözlemci, Strateji, Dekoratör vb. Hepsi bu prensibi kullanır. Yazılımın beklenen değişkenlik boyutunda genişletilmesi gerektiğinde "öderler" ve "kararlı" varsayımlar sabit kalır.

Gereksinimleriniz “öngörülen varyasyonlarınız” her zaman yanlış olacak şekilde kararsızsa, uyguladığınız desenler acı verir veya gereksiz karmaşıklığa en iyi şekilde neden olur.

Craig Larman, Korumalı varyasyonları uygulamak için iki fırsattan bahseder:

  • varyasyon noktaları - mevcut, mevcut sistemde veya desteklenmesi gereken çoklu arayüzler gibi gereksinimlerde ve
  • evrim noktaları - mevcut gereksinimlerde bulunmayan spekülatif varyasyon noktaları.

Her ikisinin de geliştiriciler tarafından belgelenmesi gerekiyor, ancak muhtemelen varyasyon noktalarına bağlılığınız olmalıdır.

Riski yönetmek için, PV uygulayan herhangi bir tasarım modelinin, müşteri tarafından imzalanan gereksinimlerdeki bir varyasyon noktasına kadar izlenmesi gerektiğini söyleyebilirsiniz. Bir müşteri gereksinimlerde bir değişim noktası değiştirirse, tasarımınızın kökten değişmesi gerekebilir (çünkü bu çeşitliliği desteklemek için tasarıma [desen] yatırım yaptınız). Uyum, eşleşme, vb. Açıklamaya gerek yok

Örneğin, müşteriniz yazılımın üç farklı eski envanter sistemiyle çalışmasını istiyor. Tasarladığınız nokta budur. Müşteri bu şartı yerine getirirse, elbette bir sürü işe yaramaz tasarım altyapınız var. Müşterinin, varyasyon noktalarının bir maliyete mal olduğunu bilmesi gerekir.

CONSTANTS kaynak kodunda basit bir PV şekli vardır

Sorunuza bir başka benzetme CONSTANTS, kaynak kodda kullanmanın iyi bir fikir olup olmadığını sormak olacaktır . Değinen Bu örnekte , müşteri şifreleri ihtiyacını düştü diyelim. Böylece MAX_PASSWORD_SIZEkodunuz boyunca sabit bir şekilde yayılması, işe yaramaz hale gelir ve hatta bakım ve okunaklılığa engel olur. CONSTANTSSebep olarak kullanımını suçlar mısın?


2

En azından kısmen durumunuzun doğasına bağlı olduğunu düşünüyorum.

Sürekli değişen gereksinimlerden bahsettiniz. Eğer müşteri "Bu arı tutma uygulamasının eşekarısı ile de çalışmasını istiyorum" diyorsa, bu, dikkatli bir tasarımın ilerlemeye yardımcı olacağı bir durum gibi görünüyor, bunu engellemeyecek gibi görünüyor (özellikle gelecekte bunu isteyeceğini düşündüğünüzde meyve sineğini de koru.)

Öte yandan, değişimin niteliği “Bu arıcılık başvurusunun çamaşırhanenin konglomera bordrosunu yönetmesini istiyorum” gibi bir şeyse, hiçbir kod sizi deliğinizden çıkaramaz.

Tasarım kalıplarında doğal olarak iyi bir şey yok. Onlar da diğerleri gibi araçlardır - sadece orta-uzun vadede işlerimizi kolaylaştırmak için onları kullanırız. Farklı bir araç ( iletişim veya araştırma gibi ) daha yararlıysa, onu kullanırız.

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.