En iyi nasıl biri şişirilmiş GUI kodu yazmaktan kaçınabilir?


48

GUI kodu ile ne zaman çalışsam, kodun diğer kod türlerinden daha hızlı şişirme eğiliminde olduğunu biliyorum. Ayrıca refactor için zor görünüyor. Diğer kod türlerinde oldukça kolay bir şekilde refaktör olabilirim - daha büyük bir sınıfı daha küçük işlevsellik parçalarına ayırabilirim - çoğu GUI çerçeveli, genellikle widget'ımı / kontrolümü / sınıfını gerektiren bir çerçeveye bağlarım widget / control / whatever öğesinde daha birçok şeyi daha doğrudan uygulayın. Bazen bu, (a) bazı temel widget'ların / kontrol / şeyin devraldığı ya da (b) korunan yöntemlere erişmesi gerektiğinden kaynaklanmaktadır.

Tipik olarak, örneğin, kullanıcıyla etkileşime giren tüm modları uygulamak için çerçeveden ne olursa olsun, sinyaller / olaylar / çerçeveler vasıtasıyla çok çeşitli girişlere cevap vermek zorundayım. Aşağıdakileri içerebilecek çok çeşitli giriş / çıkışları işlemek için bir GUI widget'ına / denetimine ihtiyacım olabilir:

  1. sağ tıklama / içerik menüsü
  2. içerik menüsünden seçimlere tepki verme - çok fazla olabilir
  3. GUI'yi boyamanın özel bir yolu
  4. klavye girişine tepki
  5. düğmeler, onay kutuları,
  6. vs vs

... tüm bunlar GUI altındaki iş mantığını temsil eden sınıfları yönetir.

Basit bir düz ileri GUI, iş mantığını ayırırken ve MVC kullanırken bile kodunun oldukça hızlı bir şekilde büyümesini sağlayabilir, GUI kodunun değişim için büyük bir mıknatıs olduğunu düşünüyorum.

GUI kodunu aklı başında bir şekilde yönetmenin ve bozuk bir pencere olmasına izin vermekten kaçınmanın bir yolu var mı? Yoksa GUI kodu için yapabileceğimiz en iyi şey, rastgele olay işleyicileri / geçersiz kılınan yöntem kitlesi midir?


4
"Şişirme" tanımınız tam olarak nedir?

Yanıtlar:


36

GUI koduyla ilgili hatırlanması gereken şey, olay odaklı olması ve olay odaklı kodun, her zaman rastgele organize edilmiş olay işleyicileri kütlesinin görünümüne sahip olmasıdır. Gerçekten dağınık olan şey, olayla ilgili olmayan kodları sınıfa atmaya çalıştığınız zamandır. Elbette, olay işleyicileri için destek sağlama görünümüne sahiptir ve olay işleyicilerinizi küçük ve küçük tutabilirsiniz, ancak etrafta dolaşan tüm bu ekstra destek kodu GUI kaynağınızın şişirilmiş ve dağınık görünmesini sağlar.

Öyleyse bu konuda ne yapabilirsiniz ve işleri nasıl refactor için kolaylaştırırsınız? İlk önce yeniden yapılanma tanımımı, zaman zaman yaptığım bir şeyden, sürekli olarak yaptığım kodla değiştireceğim. Neden? Çünkü yeniden yönlendirme yapmak, kodunuzu daha kolay bir şekilde değiştirmek yerine kodunuzu daha kolay bir şekilde değiştirebilmenizi sağlar. Sizden sadece burada anlambilimi değiştirmenizi istemiyorum, bunun yerine kodunuzu farklı görebilmek için biraz zihinsel calisthenics yapmanızı istiyorum.

En sık kullandığım bulduğum üç yeniden düzenleme tekniği, Rename , Extract Method ve Extract Class . Başka bir yeniden düzenleme yapmayı asla öğrenmeseydim, bu üçü hala kodumu temiz ve iyi yapılandırılmış tutmamı sağlayacaktı ve sorunuzun içeriğinden, muhtemelen neredeyse sürekli olarak aynı üç yeniden yapılandırmayı kullanırken kendinizi bulacağınız gibi geliyor. GUI kodunuzu ince ve temiz tutmak için.

Dünyadaki GUI ve Business mantığının mümkün olan en iyi şekilde ayrılmasına sahip olabilirsiniz ve yine de GUI kodu, ortasında bir kod mayınının patlatıldığı gibi görünebilir. Benim tavsiyem bu düzgün GUI yönetmek için yardımcı olmak için ekstra bir sınıf veya iki olması zarar olmamasıdır ve bu mutlaka olmak zorunda değildir Görüntüle MVC deseni uygulayarak eğer sınıfları - sık bulacaksınız rağmen ara sınıflar görüşünüze o kadar benzerdir ki, çoğu zaman rahatlık için onları birleştirme dürtüsünü hissedeceksiniz. Bunu kabul ediyorum, tüm görsel mantığı yönetmek için GUI'ye özel bir katman eklemenin gerçekten zarar vermemesidir, ancak muhtemelen bunu yapmanın yararlarını ve maliyetlerini ölçmek istersiniz.

Bu yüzden benim tavsiyem:

  • GUI'nin Görünüm'e (veya bir ara katmana) nasıl bağlanacağını çağırmak ve tanımlamak dışında doğrudan GUI'nizin arkasında hiçbir şey yapmayın.
  • Her görüşte ilgili şeyi tek bir sınıfa, hatta GUI penceresi başına tek bir sınıfa bağlamayı denemeyin, bunu sizin için mantıklı gelmiyorsa. Alternatifiniz, GUI mantığınızı yönetmek için sınıfları yönetmek için çok sayıda küçük ve kolay oluşturmaktır.
  • Yöntemleriniz 4-5 kod satırından biraz daha büyük görünmeye başladığında, bunun gerekli olup olmadığını ve bir veya iki yöntemi çıkarmak mümkün olup olmadığını inceleyin, böylece bir sınıf anlamına gelse bile yöntemlerinizi yalın tutabilirsiniz daha birçok yöntemle.
  • Sınıflarınız gerçekten büyük görünmeye başlıyorsa, çoğaltılmış işlevlerin TÜMÜNÜ kaldırarak başlayın ve ardından yöntemlerinizi mantıksal olarak gruplandırabilir veya başka bir sınıfı ya da iki sınıfı çıkarabileceksiniz.
  • Her satır kod yazdığınızda yeniden düzenlemeyi düşünün. Çalışmak için bir kod satırı alırsanız, işlevselliği çoğaltmaktan kaçınmak veya davranışını değiştirmeden biraz daha yalın hale getirmek için yeniden aktarabileceğinizi görün.
  • Kaçınılmaz olanı kabul edin, sisteminizdeki bir parçanın ya da diğerinin biraz şişkinlik hissetmeye başlayacağını, özellikle de gittiğinizde yeniden yapılanmayı ihmal ederseniz hissedeceğinizi kabul edin. Hatta iyi faktörlü kod tabanı ile, yine Okumanın daha yokmuş gibi hissedebilirsiniz olabilir yapmak. Bu, yazma yazılımı gerçeğidir, kendinizi her zaman "daha iyi" bir şeyler yapılabileceğini hissediyorsunuzdur, bu yüzden profesyonel bir iş yapmak ile altın kaplama arasında bir denge kurmanız gerekir.
  • Çalıştığınız ve kodunuzu sakladığınız temizleyicinin kodunuz ne kadar az şişirilmiş gibi göründüğünü kabul edin.

3
+1 Beğenin ya da beğenmeyin, bir GUI, ayrıntılı bir işlem olan zillion ile ilgilenir ve bu kod anlamına gelir.
Patrick Hughes,

Geliştiriciler GUI için olaya dayalı kodlamayı kullanmayı öğrenmelidir.
David Gao

23

Bence, yaşadığınız sorunların çoğunun basit bir nedene dayanabileceğini düşünüyorum. Çoğu geliştirici GUI koduna 'gerçek' kod gibi davranmaz. Burada kanıt veya istatistik yok, sadece içimde bir his var.

Belki de ' sadece sunum ' olduğunu ve önemli olmadığını düşünüyorlar . ' Orada iş mantığı yok ' diyorlar, ' neden ünite test ediyor '? Nesne yönelimi ve temiz kod yazarken bahsettiler. İşleri daha iyi hale getirmek için bile YTL kullanmıyorlar. Başlamak için hiçbir yapı yoktur, sadece bazı kodları tokatlarlar ve diğerleri zaman içerisinde kendi dokunuşlarını eklerken çürümesine izin verirler. Güzel bir karışıklık, grafiti kodu.

GUI kodunun kendine özgü zorlukları vardır, bu nedenle farklı ve saygılı bir şekilde ele alınmalıdır. Yazmak isteyen aşka ve geliştiricilere ihtiyacı var. Onu ince tutan ve iyi yapı ve doğru kalıp verenler.


2
GUI kodunun algılanması için +1, gui koduna göre farklı muamele görür. Birisinin "GUI'yi sınamak için canınızı sıkma çünkü maliyet etkin değil ve yapması o kadar zor" dediğini duyma sayımı kaybettim. Genellikle "Zor ve nasıl yapılacağını öğrenmek için çok tembelim!" Diline çeviriyorum.
S.Robins

1
+1 Çalıştığım yerde sık sık GUI kodunu gözden geçirmiyoruz - "sadece GUI, atla". Ve ben de herkes kadar suçluyum. Garip olan şey, kişisel projelerimde zamanın temiz GUI kodu almayı denemek için çok zaman harcaması. Sanırım sadece bir kültür meselesi.
HappyCat

8

Bazı nedenlerden dolayı, GUI kodu geliştiricilerde endişelerin ayrılması konusunda kör bir nokta oluşturur. Belki de, çünkü tüm öğreticiler her şeyi bir sınıfa toplar. Belki de fiziksel temsili, olayların onlardan daha yakın görünmesini sağlamasıdır. Belki de sınıflar yavaş bir şekilde inşa edildiğinden, insanların ısınmaya neden olacak şekilde yavaş yavaş kaynaması gibi kaynaştırılmaya ihtiyaç duyduklarını fark etmemeleri nedeniyle.

Sebep ne olursa olsun, çözüm, sınıflarınızı çok daha küçük hale getirmektir. Bunu sürekli olarak kendime, yazdıklarımı ayrı bir sınıfa koymanın mümkün olup olmadığını sorarak yapıyorum. Başka bir sınıfa koymak mümkün ise ve o sınıf için makul ve basit bir isim düşünebilirsem, o zaman yaparım.


6

Model Görünümü Presenter / Passive View modeline bakmak isteyebilirsiniz. Ray Ryan, GWT için en iyi mimarlık uygulamaları hakkında bir Google IO’da güzel bir konuşma yaptı.

http://www.google.com/events/io/2009/sessions/GoogleWebToolkitBestPractices.html

Fikirleri diğer çerçevelere ve dillere soyutlamak kolaydır. MVP'nin ana faydası (bence) birim test edilebilirliğidir. Ve bunu sadece, eğer şişmemiş ve spagetti olmayan kodunuz (sorunuza bakılırsa, istediğiniz budur) elde edersiniz. Sunucu adı verilen bir görünüm mantığı katmanı getirerek çalışır. Gerçek görünüm bundan bir ara yüz vasıtasıyla ayrıştırılır (ve böylece birim testlerinde kolayca takılabilir). Artık, görünüm mantık katmanınız (sunucu) somut GUI çerçevesinin iç kısımlarından kurtarıldığı için, normal kod gibi düzenleyebilirsiniz ve örneğin Swing devralma hiyerarşisine bağlı değilsiniz. İdeal olarak, GUI uygulamalarını aynı arayüze uygun oldukları sürece farklı çerçevelerde değiştirebilirsiniz.


1
+1. MVP, GUI mantığını, insanların MVC hakkında konuştuklarında anladıklarından oldukça farklı olan ayrı sınıflara nasıl çıkaracağına odaklanır.
Doktor Brown

5

Cevabım dört bölümden oluşuyor: yapı, basitlik, test etme ve sözdizimi.

İlk üçünü yapmak gerçekten zor!

Yapı , en az miktarda kod ve en fazla sayıda çerçeve, kütüphane vb. Kullanmaya çok dikkat etmek anlamına gelir.

Sadelik , ilk tasarımdan gerçek uygulamaya kadar işleri basit tutmak anlamına gelir. Gezintiyi basit tutmak, basit eklentileri kullanmak, yerleşimi oldukça 'düz' tutmak burada yardımcı olacaktır. Artık bilgisayar, ipad, mobil ve diğer cihazlarda çalışan sayfaların avantajlarını hızla görebilen müşterilere / kullanıcılara 'satılabilir'.

Test sık kodunun 'yama' karşıt olarak daha iyi kod başında onlarla uğraşmak dizayn edilebilir olduğunda tarayıcı test araçları (webrat ve benim raylar çalışma ile akla gelen Capybara) ön yakalamak farklı tarayıcılarda sorun da dahil olmak üzere araçlar farklı geliştiriciler tarafından farklı tarayıcıların kullanıcıları tarafından 'keşfedildiği gibi'.

Sözdizimi. HTML, CSS, Javascript vb. İçin bir kod denetleyici / IDE / düzenleyici eklentisi vb. Kullanmak gerçekten yararlıdır. Farklı tarayıcılar farklı performans gösterdiğinde, farklı biçimlerde farklı performans gösterdiğinde, hatalı biçimlendirilmiş HTML'leri işleyebilmek yoluyla tarayıcıların elde ettiği avantaj bu yüzden, HTML biçiminizi kontrol eden bir araç esastır. İyi biçimlendirilmiş HTML'ye sahip olmak, HTML kodunun kaldırılmasında çok yardımcıdır, çünkü kötü kod daha fazla görünürlüğe sahip olmalıdır.


4

Bulduğum çözüm bildirim kodu. Sadece prosedür kodunu kullanmak spagetti GUI kodu için bir reçetedir. Elbette, "widget'ı boyamanın özel bir yolu" muhtemelen kod kalacak. Fakat bu bir sınıfta izole edilen koddur. Olay işleyicileri, klavye kısayolları, pencere boyutları - tüm bu karışık şeyler en iyi şekilde ilan edilir.


4

Burada bir sürü harika cevap var.

GUI kodunu basitleştirmeme yardımcı olan bir şey, GUI'nin kendi veri modeline sahip olduğundan emin olmaktır.

Basit bir örnek olarak, 4 metin giriş alanına sahip bir GUI'ye sahipsem, o zaman bu 4 metin giriş alanının içeriğini tutan ayrı bir veri sınıfım var. Daha karmaşık GUI'ler daha fazla veri sınıfı gerektirir.

Bir model olarak GUI tasarlarım. GUI modeli, uygulama modeli görünüm denetleyicisi tarafından kontrol edilir. Uygulama görünümü, GUI kodunun kendisinden ziyade GUI modelidir.


2

Kelime İşleme, Grafik editörleri vb. Uygulamalar karmaşık arayüzlere sahiptir ve kodları basit olamaz. Bununla birlikte, işletme uygulamaları için, GUI'nin çok karmaşık olması gerekmekle kalmamakta, bir kısmı da hala böyle olmaktadır.

GUI'yi basitleştirmenin anahtarlarından bazıları (çoğu .NET için geçerlidir):

  1. Mümkün oldukça basit tasarım için çaba gösterin. İşletme tarafından aranmazsa, süslü davranışlardan kaçının.

  2. İyi bir kontrol sağlayıcı kullanın.

  3. İstemci kodunun kendisinde özel kontrol işlevselliği oluşturmayın. Bunun yerine, özgün denetimi genişleten kullanıcı denetimleri oluşturun; böylece form / sayfanın kodunu kullanmak yerine, belirli davranışlarınızı denetimlere yansıtabilirsiniz.

  4. Uluslararasılaştırma, kaynak yönetimi, stiller vb. İşlemlerini yürütmek için bir çerçeve (hatta bir ev yetiştirilen) kullanın, böylece bu kodu her kullanıcı arayüzünde tekrar etmemeniz için.

  5. Gezinme için bir bileşen (veya çerçeve) kullanın.

  6. Hatalar, uyarılar, onay vb. İçin standart diyaloglar oluşturun.


1

Nesneye Yönelik Tasarım'ı kodunuza ve kullanıcı arabirimi geliştirmeye uygulayın:

  1. Ayrı sunum ve model Görüntüle / denetleyici mantığını veri modelinden ayırmak için bir MV-kitaplığı / çerçevesi kullanın ya da kendiniz yazın. Arka uçla tüm iletişim, model içinde yapılmalı ve model durumu her zaman arka uç ile aynı olmalıdır.
  2. Dekuplaj A nesnesi B nesnesini biliyorsa, A B yöntemlerini çağırabilir, ancak B A'yı bilmemelidir. Bunun yerine A B olaylarını dinleyebilir. Bunun dairesel bir bağımlılık olmadığından emin olunur. Uygulamanızın bileşenler arasında pek çok etkinlik varsa, bir EventBus oluşturun veya Twitter Flight gibi olaya dayalı bir çerçeveden yararlanın.
  3. Kısmi vs tam oluşturma Görünümünüz bir öğe veya tablo ise, koleksiyona bir öğe eklemek / silmek için "ekle", "kaldır" gibi yöntemler oluşturmak için cazip olabilirsiniz. Sıralama ve sayfalama işlemlerini desteklemeniz gerektiğinde kodunuz kolayca şişebilir. Bu yüzden benim tavsiyem: kısmi bir değişiklik olsa bile sadece bütün görüşü yeniden düzenlemek. Peki ya performans? koleksiyonunuz büyükse, yine de sayfalandırma yapmanız gerekir. Web geliştiricisi: etkinlik işleyicilerinizin, görünümün değişmeyen kök öğesine atandığından emin olun.
  4. Görünüm modeli Görünümünüzün durumu, örneğin bir Tablo görünümünün satır verilerini, sütun verilerini, sıralama düzenini, şu anda kontrol edilen satırları (çoklu kontrolü destekliyorsa) vb. bu durumlar için bir ViewModel nesnesi oluşturun. UI'de bir şey değiştiğinde View nesnesinin ViewModel'deki ayarlayıcıları çağırması gerekir (örn. Kullanıcı bir satırı kontrol eder); ve kullanıcı arayüzünü güncelleyerek ViewModel'in değişiklik olayına yanıt vermelidir. Change olayı UI tarafından tetiklenirse, genellikle UI'yi güncellemekten kaçınmanız gerekir.

İşte benim puanlarımı göstermek için küçük ama önemsiz olmayan bir uygulama. Kod ve görünüm / model etkileşim şemasını burada bulabilirsiniz: https://github.com/vanfrankie/pushpopbox


0

"Veri bağlama" kavramına bir göz atmak istersiniz . Bu, UI öğelerini soyut model öğelerine bildirimsel bir şekilde bağlamanın bir yoludur, böylece model öğeleri UI'nin içeriğiyle otomatik olarak eşitlenir. Bu yaklaşımın birçok faydası vardır; örneğin, verileri senkronize etmek için olay işleyicileri kendiniz yazmak zorunda değilsiniz.

.NET ve Eclipse / JFace gibi birçok UI çerçevesi için veri tabanı desteği vardır .

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.