Agile veya XP gibi evrimsel yöntemlerde bir tasarım çıkmazına ulaşırsanız ne yaparsınız?


11

Martin Fowler'in ünlü blog yazısı okurken Design Dead mi? Çevik Metodoloji ve Aşırı Programlama'da tasarımın yanı sıra programlamanın da evrimsel olduğu göz önüne alındığında, çarpıcı izlenimlerden biri, her şeyin yeniden düzenlenmesi gereken noktalar olduğu gerçeğidir.

Bir programcı düzeyi iyi olduğunda ve tasarım sonuçlarını anladıklarında ve kritik hatalar yapmadığında, kod gelişmeye devam edebilir. Ancak, normal bir bağlamda, bu bağlamda temel gerçeklik nedir?

Normal bir günde, bazı önemli gelişmeler ürüne girdiğinde ve kritik değişiklik gerektiğinde, ne kadar istersek, temel tasarım unsurlarının değiştirilemeyeceği bir kısıtlama değil mi? (kodun büyük bir kısmını atmadan). Tasarım ve gereksinimlerle ilgili herhangi bir olası iyileştirmenin çıkmaza girmesi pek olası değil mi?

Burada Agile olmayan herhangi bir uygulamayı savunmuyorum , ama gerçek deneyimleri için olduğu gibi çevik veya yinelemeli veya evrimsel gelişim yöntemleri uygulayan insanlardan bilmek istiyorum.

Hiç böyle çıkmaz noktalara ulaştın mı? Bundan kaçınmayı veya kaçmayı nasıl başardınız? Yoksa tasarımın geliştikçe temiz ve esnek kalmasını sağlayacak önlemler var mı?

Yanıtlar:


17

Az önce yayınladığınız makaleyi okudum, Fowler'ın çok iyi noktalar ve söylediği birçok şey yaptığını söylemeliyim, ekibimizle yıllardır savunuyorum.

IMO, eğer iyi bir tasarım yaparsanız, çıkmaz bir durum olarak kabul edilecek şeylere girmemelisiniz. Yazılımı her zaman yapı taşlarından oluşmuş olarak gördüm . Hala bazı ön tasarıma inanıyorum, ancak asıl amaç tüm ürünü tasarlamak değil, genel mimari / yön sağlamaktır, böylece ekibiniz hepimizin üzerinde çalıştığımız ortak bir resmi görselleştirebilir. Bir sürü küp ve üçgen parçanız varsa, parçaları birbirine tokatlamaya başlamadan önce bir kalenin nasıl bir araya getirileceğini çizmek yardımcı olur.

OO topraklarından geldiğim için, bana göre her blok bir sınıftır ve bu bloğun yüzey alanı genel arayüzdür (dışsal veya türetici sınıflar tarafından görülebilir). İyi SOLID ilkelerini izlerseniz, her bloğun son derece basit ve sezgisel bir genel arayüze sahip olduğundan emin olursunuz. Benzetmeme geri dönersek, kodunuzun yalnızca basit şekiller oluşturduğundan emin olmak istersiniz. Ne zaman çok karmaşık (birçok işlev, birçok değişken) sınıflar oluşturduğunuzda, gereksinimler değiştiğinde yeniden kullanılması zor şekiller oluşturursunuz.

Fowler ile hemfikirim; evrimsel tasarım için en büyük risk / zorluk, tasarım kararlarını kodlama zamanına bırakmanız ve her bir geliştiricinin bu kararları almasını beklemenizdir. Uygun geri bildirim mekanizmalarınız yoksa sistem arızalanabilir. Yeni bir özellik istendiğinde, genişletilmesi gereken işlevi bulmak, içine bir tür koşul koymak ve sadece bu işlevin içine bir sürü kod eklemek son derece caziptir. Ve bazen, tüm ihtiyaç duyulan bu olabilir, ancak bu aynı zamanda çıkmaz bileşenlere yol açan en yaygın tek uygulamadır. Bunun evrimsel tasarımla bir ilgisi yok. Buna "tasarım yok" denir.

Geri adım atmaya ve diyelim ki, bir dakika bekle, bu sınıfın zaten 15 üye değişkeni var, bunlardan 6'sını çıkarmama ve kendi müstakil sınıflarına koymama izin verdiğinizde, yazılımınız çok hafif olacak -ağır, esnek ve tekrar kullanılabilir yapı taşları. Eğer PM'ler gelir ve ürün gereksinimlerinizin yarısını değiştirirse, bazı bloklarınızı çıkarmanız, rafa geri koymanız ve yeni olanlar çizmeniz gerekebilir (tıpkı bir kale inşa ederken olduğu gibi, hepsini kullanamayabilirsiniz) silindirleriniz). Ama bu noktada, bu sadece iş yapmanın bir parçası. Gereksinimler değişti ve kodunuzu esnek ve modüler tutarak, ürününüzü yeni iş yönünüze uyacak şekilde değiştirebilmelisiniz.

Tasarımdaki bu evrimsel yaklaşımın her seviyede mühendisin becerisiyle çalıştığına inanıyorum. Şahsen, çok uzun bir süre yazılım yaptım ve ekibimiz çevik bir metodolojiye geçmeden önce, dev PC'mden birkaç ana bileşeni neredeyse hiç KG ile neredeyse doğrudan müşteriye göndermekten sorumluydum. Aynı zamanda bu bileşenler her zaman esnek ve bakım yapılabilir kalmıştır.

Sadece yazılım tasarlarken kendimi nispeten iyi göreceğimi söylemeye çalışıyorum. Aynı zamanda, 100 sayfalık bir tasarım belgesi yazmamı, bir kodlayıcıya vermesini ve çalışmasını beklemenizi istediyseniz, muhtemelen kendimi bir kağıt torbadan tasarlayamadım. Çalışmaya başlarken, bazen birkaç UML benzeri (çok basitleştirilmiş, tam dil değil) diyagramları çizerdim, ancak kodlamaya başladığımda, gerektiğinde yeniden düzenlerim ve son kodum asla çizdiğim gibi görünmezdi. Her küçük ayrıntıyı düşünmek için bir iki ay geçirsem bile, başka birisinin diyagramlarımı alabildiğini ve tasarımı kodlarken tasarımını değiştirmeden sağlam bir yazılım parçası bulabildiğini hayal edemiyorum.

Spektrumun diğer ucunda, şu anda ekibimde (şimdi çevik ve bunu tam olarak destekliyorum), son 15 yıldır sadece C yaptıkları gömülü topraklardan bize katılan birkaç adamımız var. Açıkçası bazı başlangıç ​​planlama ve ders verme konusunda yardımcı oldum, ancak aynı zamanda SOLID ve tasarım ilkelerinin uygulamalarını tartıştığımız düzenli kod incelemeleri ve beyin fırtınası oturumlarını takip etmeyi de sağladım. Biraz kandırmak için bazı spagetti kodları ürettiler, ama benden sadece hafif bir dürtme ile, zaten üretilenleri yeniden düzenlemeye başladılar ve komik kısım bunlardan birinin bana birkaç gün sonra geri gelip diyor ki, nefret ediyorum ancak bu kodu çıkardıktan sonra çok daha okunabilir ve anlaşılır görünüyor. Çıkmaz önlendi. Nokta I ' Yapmaya çalışıyorum, OO için tamamen yeni olan birisinin bile, daha fazla deneyime sahip bir akıl hocası olduğu sürece, ona "evrimsel tasarım" ın "tasarım" ile aynı şey olmadığını hatırlatmak için iyi bir kod üretebileceğidir. Ve hatta bazı "daha karmaşık" sınıfları bile o kadar korkutucu değil çünkü her sınıfın o kadar fazla sorumluluğu yok (yani o kadar fazla kod değil), o kadar kötüsü daha da kötüleşiyor, eğer o sınıf "çıkmaz sokaklar" ise, chuck ve aynı ortak arayüze sahip bir yedek sınıf yazmak (şimdiye kadar yazdım bir şeyde bu beklenmedik bir ihtiyaç görmedim ve haftada iki kez kod değerlendirmeleri yapıyorum).

Son bir not olarak, aynı zamanda tasarım belgelerine de inanıyorum (en azından mevcut ekibimin iş koşulları için), ancak tasarım dokümanlarımızın temel amacı Organizasyonel Bellek , bu yüzden kod üretildikten sonra gerçek belgeler yazılıyor ve refactored. Kodlamadan önce, genellikle peçeteler / mspaint / visio üzerine sınıflar çizdiğimiz hızlı (bazen çok hızlı olmayan) bir tasarım aşamasına sahibiz ve insanlara her zaman bu aşamanın bir plan değil, takip edecek bir yol ürettiğini ve kodlamaya başladıklarını hatırlatırım, mantıklı olmayan herhangi bir şey değiştirilmelidir. Bu hatırlatıcılarla bile, yeni çocuklar, kendileri için bile ne kadar doğal hissettirse de, kodu orijinal tasarıma geri koyma eğilimindedir. Bu genellikle kod incelemelerinde ortaya çıkar.

Dang, çok yazdım. Bunun için üzgünüm.


1
+1 Her kelimeye değdi. Tarif ettiğiniz gibi bu durumlarla karşılaşıyorum ve son tarih karşılandıktan sonra, tasarımın sağduyulu olduğunu düşündüğümden daha fazla temizlemelerini (refactor'u okuyun) isteyin. Ama çoğu zaman insanlar aynı soruyu tekrar tekrar bulurlar - Neden aynı şeyi tekrar yapıyorum ? Sanırım şimdi cevabım var - pazarlamak için daha hızlı zamana ihtiyacınız varsa ve tasarımın gelişmesine izin verirseniz, yeniden düzenleme eski günahlarınız için bir tazminat değil, aslında meşru bir şeydir.
Dipan Mehta

Evet, çok yazdın, ama bu iyi bir şeydi. Gerçekten okumaktan zevk :).
Radu Murzea

11

"Tasarım çıkmaz sokak" fenomeninin çevik yöntemlerle dik olduğunu söyleyebilirim. Demek istediğim şelale yapmak, (kötü) bir tasarıma çok fazla zaman harcamak mümkün. O zaman sadece kendinizi çıkmazda bulmak için uygulamak için çok zaman harcayın.

Bir şey varsa, çevik yöntemler daha önce kötü tasarım seçimleri yaptığınızı keşfetmenize yardımcı olmalıdır . Bunun nedeni, biriktirme planınızın önce en yüksek müşteri değeri öğelerine sahip olması ve yazılımın yararlı artışlarını sağlamaya odaklanmanızdır. Tasarımınız yüksek değer ve kullanışlılık sunmanıza izin veriyorsa, zaten bir şey için iyidir :-) Buna karşılık, bu tasarımın sağlayamayacağı uzun yıllar bulamayacağınız bir şelale-ish durumunda kötü bir tasarıma sahip olabilirsiniz. herhangi bir değer ve herhangi bir kullanışlılık - sahip olduğunuz tek şey onun iyi bir tasarım olduğu yanılsamasıdır. Dedikleri gibi, kanıt pudingdedir.

Flip tarafı, çevik yöntemlerde bile, sistemin tasarımı için kararları yinelemeden yinelemeye sürükleyen uygun bir vizyona sahip olmanın önemli olduğudur. Sanırım Ken Schwabber, korkunç geliştiricilerden oluşan bir ekibiniz varsa, kötü yazılımları sürekli olarak yineleme ile yineleyecek gibi bir şey söyledi. Çevik basitçe çok fazla zaman harcamak anlamına gelmez, çünkü uygulamaya başlamadan önce öğrenebileceğiniz veya hayal edebileceğiniz şeylerle sınırlısınız ( ve gereksinimler de değişir). Bununla birlikte, önceden iş yapmanız (örneğin araştırma) yapmanız gereken bazı durumlar vardır ve bunu yapmanız gerekir.

Çıkmaz sokaklardan nasıl kaçınırsınız?

Çoğunlukla gelecekteki gereksinimleri öngörerek söyleyebilirim. Bu, benzer projeler / ürünlerle deneyim ve aşina olduğunuz bir şeydir. Bu beklenti kısmen iyi bir tasarım oluşturmanıza yardımcı olan şeydir, çünkü mevcut sisteminiz hakkında kendinize bir çok "ya" sorusu soruyorsunuz. Bana göre bu kritik bileşen. OO gibi teknikler, ne yaptığınızı zaten bildiğinizde size yardımcı olur.

Çıkmaz sokak varsa ne yaparsın?

Bir "çıkmaz" Başka teknik blokta farklı değildir olacaktır roman şey gelişimi sırasında çarptı. Farkına varmanız gereken ilk şey, sizi tamamen geri adım atmaya zorlayan hiçbir gerçek "çıkmaz sokak" olmadığıdır. En azından bu noktaya kadar öğrendikleriniz, çaba sarf edilmemesi için ilerlemenizi sağlayan şeydir. Çıkmazlığa çarptığında bir sorunun var . Sorun, bazı yeni (veya eski) gereksinimleri karşılamak için neyin değişmesi gerektiği ve bu değişikliğin nasıl optimize edileceği. Şimdi tek yapmanız gereken bu sorunu çözmek. Bunun bir yazılım tasarımı değil, yazılım olduğu için şükredin, çünkü değişim çok daha kolaydır. Sorunları belirleyin, düzeltin == refactor == yazılım mühendisliği. Bazen çok fazla iş vardır ...

Scrum kullanıyorsanız, bu değişiklik doğal olarak kullanıcı hikayelerinden kaynaklanmalıdır (kullanıcı bu değişiklikten ne elde eder?). Süreç, mevcut tasarım (ayy) tarafından kolayca karşılanamayan bir hikayeden başlayacak ve ürün sahibiyle bu hikayenin nasıl parçalanacağı hakkında bir tartışma olacaktır. Bu değişiklik sayesinde çevik prensipleri uygulamaya devam ediyorsunuz.

Aklıma gelen OS dünyasından birkaç ünlü büyük gereksinim değişikliği:

Bunlara hangi şekilde bakarsanız bakın, çok fazla iş var. Orijinal tasarım neredeyse kesinlikle bu olma olasılığını hesaba katmadı (yani taşınabilirlik büyük bir gereklilik değildi). Tasarımın OO olup olmadığı da büyük bir faktör değildir. İyi bir tasarımda platforma özgü kısımlar bir şekilde izole edilecek ve iş daha kolay olacaktır.


Aslında Windows NT'nin ilk sürümlerinde "Donanım Ayıklama Katmanı" uygulanmış ve DEC Apha ile x86 desteklenmiştir. Hiç kimse DEC alfa tabanlı makineler satın almadığı için bu sessizce düştü. Bu "makine bağımsızlığının" mevcut sürümde hala körel bir formatta var olduğunu hayal ediyorum, bu yüzden bir ARM portu o kadar zor olmayabilir.
James Anderson

3

Projelerimi kalıcı olarak yeniden düzenliyorum ve ayrıca UML sınıf diyagramları kullanıyorum. Demek istediğim, paketlerle bir veya daha fazla sınıf diyagramı oluşturuyorum. Her diyagram paketin kök dizinine kaydedilir. Her UML sınıflandırıcısının, ilgili Java Kimliğiyle eşlenen kendi kimliği vardır. Bu, diyagramımı açtığımda otomatik olarak en son kod yeniden düzenleme değişikliklerine güncelleneceği anlamına geliyor. Sınıf diyagramlarımı grafiksel olarak doğrudan değiştirebilirim ve tüm projem hemen yeniden düzenlenir. Oldukça iyi çalışıyor ama asla insanın yerini almayacak. UML sınıf diyagramım aynı zamanda kodumun yalnızca grafiksel bir görünümüdür. EMF tutulması gibi karma kod ve modelin yapılmaması çok önemlidir, çünkü yeniden düzenleme yapılır yapılmaz model bilgileri de kaybolur. Asla Model Driven Development kod üretecini kullanmam çünkü bu işe yaramaz. Yapmıyorum

Proje yapımın tüm detaylarını ve her yerde notlarla dolu 100'den fazla sınıf diyagramına sahip olmanın gerçekten yararlı olduğunu söyledikten sonra. Projeler için sadece sınıf diyagramları oluşturuyorum çünkü genellikle geliştiricilerin başka diyagramları öğrenmek veya kullanmak için zamanları yok. Sınıf diyagramları da çok iyi çünkü otomatik olarak güncellendi. Sınıf diyagramları koddan sonra sadece bir paketi ters çevirip notlar ekleyerek oluşturulabilir. Hızlı ve her zaman doğru ve% 100 yinelemelidir.

Lütfen kod üreten bir model olan model güdümlü geliştirme ile genellikle UML koddan güncellenmiş UML sınıf diyagramları ile grafik sunum olarak kullanmayın. Birden fazla yineleme varsa, yalnızca UML senkronize kodunun gerçek bir değeri vardır.

Çok uzun olduğum için üzgünüm ama bence sadece projemizin grafiksel görünümü olarak kullanılıyorsa UML sınıf diyagramlarına ikinci bir şans vermeliyiz. Bu, UML'nin tüm projeyi kapsadığı ve tüm projeyi temsil eden büyük sınıf diyagramlarından oluşan tek bir modele sahip olduğu anlamına gelir. Yüzlerce görüşe sahip bir projedeki her bir görünüm için yüzlerce küçük görüşe ve bir modele sahip olmak saçma olurdu :-)


1
+1 posta kodu UML fikrini göstermek için! İlginçtir , koddan sonra diyagram belgelerine asla geri dönmeyiz !
Dipan Mehta

Evet, bu UML ile ilişkili model odaklı geliştirme ile ilgili tam olarak bir sorundur. Belgeleri oluşturursunuz ve daha sonra herhangi bir proje değişikliği varsa asla kullanmazsınız. Model ve kod birleştirme, UML kullanmamıza ve ihtiyacımız olduğu kadar çok değiştirmemize olanak tanır.
UML_GURU

3

Kötü tasarım, yön değişikliği, vb nedeniyle kodumu ve diğerleri kod çıkmaz ulaştı Ayrıca birçok başkaları bu sorunla karşılaştım gördüm. Büyük hata (en azından benim için bir hata gibi görünüyor), çalışma kodunu atma ve her şeyi baştan sona yeniden uygulama arzusudur.

Her davaya iyi işleyen bir şekilde yaklaştım:

  • mevcut tasarımın neden çalışmadığını belirleme
  • yeni bir tasarım ve bir geçiş planı hazırlayın
  • kullanımdan kaldırılmış olarak kullanılmayacak kodu etiketleyin
  • acil ihtiyacın karşılanması için sadece yeni tasarım için ihtiyacım olanı uygula
  • yeni kodun kullanım dışı kaldığı kodu kaldır

Maliyetler:

  • aynı anda kod tabanındaki 2 uygulama sayesinde daha karmaşık
  • iyi kullanım senaryoları ve testleri varsayarak tam bir yeniden tasarım / yeniden uygulama yapmaktan daha fazla özellik / hata düzeltmesi başına daha fazla maliyet

Yararları:

  • en azından daha az risk büyüklüğünde bir sipariş, çünkü hala eski çalışma tasarımına / koduna sahipsiniz
  • tam yeniden tasarım gerektirmeyen 1 ila n-1 özellikleri için daha hızlı pazarlama
  • tam yeniden tasarımı tamamlamadan önce ürün / kod ölmeye başlarsa, geliştirme zaman farkından tasarruf etmiş olursunuz
  • yinelemeli yaklaşım ve tüm faydaları

2

Yaklaşık bir ay önce, mevcut projemiz SCRUM geliştirme tarzı ile bazı kötü tasarım kararları (ve bir yerde çok fazla tasarım eksikliği) nedeniyle biraz sıkıştı.

Çözümümüz (ve SCRUM için standart olduğuna inandığım şey), tüm sprint (~ 2 hafta) yeniden düzenleme dışında bir şeye adamaktı. Bu süre zarfında yeni bir işlevsellik eklenmedi, ancak mevcut kod tabanını düşünebildik ve yaptığımız şey için çok daha iyi bir sistem tasarlayabildik.

Şimdi bu engeli aştık ve tekrar yeni özellikler ekliyoruz.


Bu, bulunacak bir başka büyük sürtünmedir. İlk sürüm teslim edildikten sonra müşteriye - şimdi aynı şeyi inşa ettiğimizi - yeni bir şey olmayan özellikler söylemek zorundayız! Bunu müşteriye ne sıklıkla ve sık sık (eğer varsa) söylemeyi göze alabilirsin? ya da nasıl açıklarsın?
Dipan Mehta

İki temel seçeneğiniz var, ya ilk önce basit gerçeği söylüyorsunuz - sahip olduğunuz şey bir karışıklık olsa da ve devam eden gelişimi desteklemek için altyapı oluşturduğunuzu söylediğiniz ileri ya da ikinci hareket için toplanması gerekiyor ( ki bu daha az doğru değildir, ancak biraz daha olumlu olacak şekilde döndürülür). Bunların her ikisini de, işlevselliği sağlamak için, şimdi geri ödenmesi gereken bir teknik borca ​​maruz kaldığımızı söyleyerek tamamlayabilirsiniz.
Murph

@Dipan Mehta: Diyelim ki bir müşteri iki katlı bir ev istiyor. Siz tasarlar ve sunarsınız. Sonra dört kat daha istiyorlar. Diyorsunuz ki, şu anki binayı daha sağlam hale getirmek için bu zamanı harcamak zorundayım, böylece dört ek kat daha tutacak. Orijinal plan sadece iki kat içeriyorsa, bunun müşteri için bir sorun olması gerektiğini düşünmüyorum. En başından itibaren altı katlı planlanmışsa, evet, müşteriye bunu söylemek sorun olabilir.
Giorgio

@DipanMehta Müşterilerin bu proje hakkında bilgi sahibi olmaları nedeniyle biraz şanslıyız. Şu anda kullandıkları bir ürüne yükseltme ve bu yıl sonuna kadar yarı belirsiz bir tamamlanma tarihi var. Bu yüzden, yeniden düzenleme için bir gecikme hakkında bile bilgi sahibi olmak zorunda değiller;) (Tasarım kararlarının
çoğunu yürüten

2

Tasarım değişikliklerinin maliyetini sınırlamanın anahtarı, kodu mümkün olduğunca KURU tutmaktır. Bu, uygulama kodunun çoğunu çok yüksek bir seviyeye getirecektir, burada kodun çoğu doğrudan niyetini ifade eder ve nispeten azı mekanizmayı belirtir. Bunu yaparsanız, tasarım kararları kodda mümkün olan en küçük ifadeye sahip olacak ve tasarım değişiklikleri mümkün olan en düşük maliyete sahip olacaktır.


2

Tasarım çıkmaz noktalarından kaçınmanın anahtarı, tasarımınızın ne zaman değişmesi gerektiğini tanımak ve daha sonra değiştirmek. En büyük problemler tasarımınızı sürekli geliştirerek değil, tasarımınızı büyük bir sorun olana kadar geliştirmeyi reddederek ortaya çıkar.

Örnek olarak, Netflix, farklı aile üyelerinin aynı plana fatura verebileceği ancak ayrı kuyruklara sahip olabileceği bir profil özelliğine sahiptir. Birkaç yıl önce, bu özelliği iptal etmek zorunda kalacaklarını açıkladılar, çünkü kullanıcılarının sadece% 10'u bunu kullandı, ancak uygulamadaki saldırı nedeniyle, aşırı miktarda bakım işi yiyordu. Bir kargaşadan sonra mermiyi ısırdılar ve bu müşterileri tutmak için pahalı bir yeniden tasarım yaptılar.

Eminim ki bu özelliği ilk kez eklediklerinde en düşük tasarımı tanıyan mühendisler vardı. Eğer o zamanlar bunu değiştirmiş olsaydı, neredeyse bir anlaşma kadar büyük olmazdı.


1

"İlkini atmayı planla" gibi bir şey söyleyen Fred Brooks değil miydi? Bu konuda çok fazla düşünmeyin, çıkmaz tasarımlar da tüm tasarımı ön planda yapmaya çalışan projelerde ortaya çıkar. Yeniden tasarımlar, başlangıçtan itibaren işlenemez bir tasarım olduğu için (son şey% 20- "şeytan ayrıntıdadır") veya bir müşteri odağını değiştirse de, her tür gelişimde gerçekleşir. Alarm zillerine gerçek bir ihtiyaç yoktur, çok endişelenmeyin.

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.