Winform'da bir proje nasıl düzgün bir şekilde yapılandırılır?


26

Bir süre önce bir winform uygulaması oluşturmaya başladım ve o zaman küçüktü ve projeyi nasıl yapılandıracağımı hiç düşünmedim.

O zamandan beri ihtiyacım olan ek özellikleri ekledim ve proje klasörü gittikçe daha da büyüyor ve şimdi projeyi bir şekilde yapılandırmanın zamanı geldiğini düşünüyorum ancak doğru yolun ne olduğundan emin değilim, bu yüzden birkaç sorum var.

Proje klasörü düzgün bir şekilde nasıl yeniden yapılandırılır?

Şu anda böyle bir şey düşünüyorum:

  • Formlar İçin Klasör Oluştur
  • Utility sınıfları için Klasör Yaratın
  • Yalnızca veri içeren Sınıflar İçin Klasör Oluştur

Sınıf eklerken adlandırma kuralı nedir?

Sınıfları yeniden adlandırmalı mıyım ki işlevsellik sadece isimlerine bakarak tanımlanabilir mi? Örneğin, tüm form sınıflarını yeniden adlandırma, böylece adları Form ile bitecek . Veya onlar için özel klasörler oluşturulmuşsa bu gerekli midir?

Yapılması gereken, böylece ana formun tüm kodu Form1.cs'de bitmez.

Karşılaştığım bir başka sorun da, ana form eklediğim her özellikle daha büyük hale geldiği için, kod dosyasının (Form1.cs) gerçekten büyük olması. Örneğin bir TabControl'üm var ve her sekmede bir sürü kontrol var ve tüm kod Form1.cs'de bitiyor. Bu nasıl önlenir?

Ayrıca, bu problemlerle ilgilenen herhangi bir makale veya kitap biliyor musunuz?

Yanıtlar:


24

Ortak tuzaklardan bazılarına düşmüşsünüz gibi görünüyor, ama endişelenmeyin, düzeltilebilirler :)

Öncelikle uygulamanıza biraz farklı bakmanız ve onu parçalara ayırmaya başlamanız gerekir. Parçaları iki yöne bölebiliriz. Öncelikle kontrol mantığını (iş kuralları, veri erişim kodu, kullanıcı hakları kodu, her türlü şey) kullanıcı arayüzünden ayırabiliriz. İkinci olarak, UI kodunu parçalara ayırabiliriz.

Bu yüzden ilk önce UI'yi parçalara ayırarak ilk kısmı yapacağız. Bunu yapmanın en kolay yolu, kullanıcı arabiriminizi usercontrols ile oluşturduğunuz tek bir ana bilgisayar formuna sahip olmaktır. Her kullanıcı kontrolü formun bir bölgesinden sorumlu olacak. Uygulamanızın bir kullanıcı listesi olduğunu hayal edin ve bir kullanıcıya tıkladığınızda aşağıdaki metin kutusunu doldurun. Kullanıcı listesinin görüntüsünü yöneten bir kullanıcı kontrolüne, ikincisini ise kullanıcı ayrıntılarının görüntüsünü yöneten bir kullanıcı kontrolüne sahip olabilirsiniz.

Buradaki asıl püf nokta, kontroller arasındaki iletişimi nasıl yönettiğinizdir. Formdaki 30 kullanıcı kontrolünün tüm rasgele tutulan birbirlerine referanslar almasını ve bunlara çağrı yöntemlerini istemiyorsunuz.

Böylece her kontrol için bir arayüz yaratıyorsunuz. Arayüz kontrolün kabul edeceği işlemleri ve meydana getirdiği olayları içerir. Bu uygulamayı düşündüğünüzde, liste kutusu liste seçiminin değişip değişmemesi umrunda değil, yeni bir kullanıcının değişmiş olmasıyla ilgileniyorsunuz.

Bu nedenle, örnek uygulamamızı kullanarak, kullanıcıların liste kutusunu barındıran kontrol için ilk arayüz, bir kullanıcı nesnesini ileten UserChanged adlı bir olayı içerecektir.

Bu harika, çünkü artık liste kutusundan sıkılıyorsanız ve 3 boyutlu zoomlu sihirli göz kontrolü istiyorsanız, aynı arayüze kodlamanız ve takmanız yeterli :)

Tamam, bu yüzden ikinci kısım, UI mantığını etki alanı mantığından ayırarak. Bu iyi giyilmiş bir yol ve burada MVP şablonuna bakmanızı tavsiye ederim. Bu gerçekten basit.

Her kontrol şimdi bir Görünüm (MVP'de V) olarak adlandırılıyor ve yukarıda ihtiyaç duyulanın çoğunu zaten ele aldık. Bu durumda, kontrol ve bunun için bir arayüz.

Tek eklediğimiz model ve sunucu.

Model, uygulama durumunuzu yöneten mantığı içerir. Bunları biliyorsunuz, kullanıcıları almak, veritabanına gitmek, bir kullanıcı eklediğinizde veritabanına yazmak vb. Buradaki fikir, tüm bunları, her şeyden tamamen yalıtılmış bir şekilde test edebilmenizdir.

Sunucu açıklamak için biraz daha zor. Model ve Görünüm arasında oturan bir sınıftır. Bu görünüm tarafından yaratılır ve daha önce tartıştığımız arayüzü kullanarak görünüm kendisini sunucuya aktarır.

Sunucu kendi arayüzüne sahip olmak zorunda değildir, ancak yine de bir tane oluşturmayı seviyorum. Sunucunun açıkça ne yapmasını istediğinizi yapar.

Böylece sunum yapan kişi, View'ın kullanıcı listesini almak için kullanacağı ListOfAllUsers gibi metodları ortaya koyar, alternatif olarak, bir AddUser metodu olarak da bir Görünüm koyabilir ve sunum yapandan bunu çağırabilirsiniz. Ben ikincisini tercih ederim. Bu şekilde sunum yapan kişi istediği zaman listeye bir kullanıcı ekleyebilir.

Presenter, seçilen kullanıcı düzenlenebilirse true değerini döndürecek CanEditUser gibi özelliklere de sahiptir. Görünüm daha sonra bilmesi gereken her şeyi sorgulayacaktır. Düzenlenebilir olanları siyah olarak isteyebilir ve yalnızca Gri olanları okuyabilirsiniz. Teknik olarak, UI odaklı olduğu için, Görünüm için bir karar, kullanıcının ilk etapta düzenlenebilir olup olmadığı Presenter içindir. Sunucu, Modelle konuştuğu için biliyor.

Yani özet olarak, MVP'yi kullanın. Microsoft, tanımladığım şekilde MVP kullanan SCSF (Smart Client Software Factory) adlı bir şey sağlar. Başka birçok şey yapıyor. Oldukça karmaşık ve her şeyi yapma şeklini beğenmedim, ancak yardımcı olabilir.


8

Ben şahsen her şeyi tek bir yürütülebilir dosyada bir araya getirmek yerine, farklı ilgi alanlarını birkaç meclis arasında ayırmayı tercih ediyorum.

Genellikle, uygulamanın giriş noktasında mutlak minimum miktarda kod tutmayı tercih ederim - İş mantığı yok, GUI kodu yok ve veri erişimi yok (veritabanları / dosya erişimi / ağ bağlantıları / vb); Genelde giriş noktası kodunu (yani çalıştırılabilir) satırları boyunca bir şeyle sınırlarım

  • Tüm bağımlı meclislerden çeşitli uygulama bileşenlerini oluşturma ve başlatma
  • Tüm uygulamanın bağlı olduğu herhangi bir 3. taraf bileşenini yapılandırma (örn. Tanılama için Log4Net)
  • Ayrıca, muhtemelen, beklenmeyen kritik / ölümcül arızaların durumlarını kaydetmeye yardımcı olacak ana işlevde "tüm istisnaları yakala ve yığın izini kaydet" türünü de ekleyeceğim.

Uygulama bileşenlerine gelince, genellikle küçük bir uygulamada en az üçünü hedeflerim.

  • Veri Erişim Katmanı (veritabanı bağlantıları, dosya erişimi, vb.) - uygulama tarafından kullanılan herhangi bir kalıcı / depolanmış verinin karmaşıklığına bağlı olarak, bu derlemelerin birkaçı olabilir - Muhtemelen veritabanı işleme için ayrı bir derleme oluşturabilirim (Muhtemelen birden fazla bile veritabanıyla etkileşime girme durumunda karmaşık bir şey varsa, örneğin, kötü tasarlanmış bir veritabanına sahip olmanız durumunda, DB ilişkilerini kodla ele almanız gerekebilir, bu nedenle ekleme ve alma için birden çok modül yazmak mantıklı olabilir)

  • Mantık Katmanı - uygulamanızı çalıştıran tüm kararları ve algoritmaları içeren ana "et". Bu kararlar GUI hakkında kesinlikle hiçbir şey bilmemeli (kim GUI olduğunu söylüyor?) Ve veritabanı hakkında kesinlikle hiçbir şey bilmemeli (Huh? Bir veritabanı var? Neden bir dosya değil?). İyi tasarlanmış bir mantık katmanı umarım yeniden derlenmeye gerek kalmadan "sökülür" ve başka bir uygulamaya bırakılabilir. Karmaşık bir uygulamada, bu mantık düzeneklerinin bir sürü grubu olabilir (çünkü uygulamanın geri kalanını sürüklemeden sadece 'parçaları' sökmek isteyebilirsiniz)

  • Sunum katmanı (yani GUI); Küçük bir uygulamada, hepsi tek bir düzene girebilen birkaç iletişim kutusu içeren tek bir "ana form" olabilir - daha büyük bir uygulamada, GUI'nin tüm işlevsel parçaları için ayrı montajlar olabilir. Buradaki sınıflar, kullanıcı etkileşiminin çalışmasını sağlamaktan biraz daha fazlasını yapacaktır - bazı temel giriş onaylamaları, herhangi bir animasyonu ele alma, vb. Gibi bir kabuktan biraz daha fazlası olacaktır. mantık katmanı (bu nedenle sunum katmanım kesinlikle hiçbir uygulama mantığı içermeyecek, ancak mantık katmanına herhangi bir GUI kodunun yükünü de yerleştirmeyecektir - bu nedenle herhangi bir ilerleme çubuğu veya diğer süslü şeyler de sunum derlemesine oturtulacaktır / ler)

Sunum, Mantık ve Veri katmanlarını ayrı montajlara bölmek için temel mantığım şudur: Ana uygulama mantığını veritabanınız veya GUI'niz olmadan çalıştırabilmenin tercih edildiğini düşünüyorum.

Başka bir deyişle; Uygulamanızla aynı şekilde çalışan, ancak bir komut satırı arayüzü veya bir web arayüzü kullanan başka bir yürütülebilir dosya yazmak istersem; ve veritabanı depolamasını dosya depolaması için değiştirir (veya belki de farklı bir veritabanı türü), o zaman bunu ana uygulama mantığına dokunmaya gerek kalmadan yapabilirim - tek yapmam gereken küçük bir komut satırı aracı yazmak. ve başka bir veri modeli, sonra "hepsini bir araya takın", ve ben hazırım.

"Eh, hiçbir zaman hiçbir zaman bunu yapmak istemeyeceğim , bu yüzden bunları değiştiremezsem önemli değil" - asıl mesele, modüler bir uygulamanın işaretlerinden birinin 'parçaları' ayıklayabilme (herhangi bir şeyi yeniden derlemeye gerek kalmadan) ve bu parçaları başka yerlerde yeniden kullanma yeteneği. Böyle bir kod yazmak için, genel olarak sizi tasarım ilkeleri hakkında uzun ve zor düşünmeye zorlar - Çok daha fazla arayüz yazmayı düşünmeniz ve çeşitli SOLID ilkelerinin takası hakkında dikkatlice düşünmeniz gerekir (Aynı zamanda Davranış Odaklı Gelişme veya TDD için yaptığınız gibi)

Bazen bu monolitik kod yığınından bu ayrılmaya ulaşmak biraz acı vericidir ve çok fazla dikkat çekici yeniden düzenleme gerektirir - sorun değil, bunu aşamalı olarak yapabilmelisiniz - çok fazla montajın olduğu bir noktaya bile ulaşabilir ve karar verebilirsiniz. diğer tarafa geri dönüp bir şeyleri tekrar sarmaya başlamak (tam tersi yönde ilerlemek, bu montajları kendi başlarına oldukça işe yaramaz hale getirme etkisine sahip olabilir)


4

Klasör yapısına göre, önerdiğiniz şey genel olarak sorun değil. Kaynaklar için klasörler eklemeniz gerekebilir (bazen insanlar çeşitli kaynakları desteklemek için her bir kaynak kümesi bir ISO dil kodu altında gruplandırılacak şekilde kaynaklar oluşturur), görüntüler, veritabanı komut dosyaları, kullanıcı tercihleri ​​(kaynaklar olarak ele alınmazsa), yazı tipleri dış borçlar, yerel borçlar vb.

Sınıf eklerken adlandırma kuralı nedir?

Tabii ki, her bir sınıfı formun dışında ayırmak istiyorsun. Ayrıca, sınıf başına bir dosya da tavsiye ederim (MS bunu EF için oluşturulan kodda yapmasa da).

Birçok kişi çoğul olarak anlamlı kısa isimler kullanır (örneğin, Müşteriler). Bazıları adı, ilgili veritabanı tablosu için tekil isme yakın olacak şekilde adlandırır (nesneler ve tablolar arasında 1-1 eşleme kullanıyorsanız).

Sınıfları isimlendirmek için birçok kaynak vardır, örneğin şunlara bir göz atın: .net İsimlendirme Kuralları ve Programlama Standartları - En İyi Uygulamalar ve / veya STOVF-C # Kodlama Kuralları

Yapılması gereken, böylece ana formun tüm kodu Form1.cs'de bitmez.

Yardımcı kod bir veya daha fazla yardımcı sınıfına gitmelidir. Kullanıcı tercihlerini bir ızgaraya uygulamak gibi GUI kontrolleri için çok yaygın olan diğer kod, formdan kaldırılabilir ve yardımcı sınıflara eklenebilir veya söz konusu kontrolü alt sınıflandırarak ve burada gerekli yöntemleri oluşturarak olabilir.

MS Windows Forms’ın etkinlik eylemi doğası nedeniyle, belirsizlik ve çaba eklemeden kodu ana formdan almanıza yardımcı olacak hiçbir şey bilmiyorum. Ancak, MVVM bir seçim olabilir (gelecekteki projelerde), örneğin bakınız: Windows Forms için MVVM .


2

MVP'yi bir seçenek olarak düşünün, çünkü bu büyük iş uygulamalarında her şey olan sunum mantığını düzenlemenize yardımcı olacaktır. Gerçek hayatta, uygulama mantığı çoğunlukla veritabanında bulunur, bu nedenle nadiren yerel kodda bir iş katmanı yazma gereksiniminiz olur ve yalnızca iyi yapılandırılmış sunum işlevine sahip olma ihtiyacı doğurur.

MVP benzeri yapı, birbiriyle koordine olacak ve UI veya eşyanın arkasındaki kodla karışmayacak bir dizi sunucuya veya tercih ederseniz denetleyicilere neden olur. Aynı denetleyiciyle farklı UI'ler bile kullanabilirsiniz.

Son olarak, basit düzenleme kaynakları, bileşenleri ayrıştırmak ve IoC ve DI ile bağımlılıkları belirlemek, bir MVP yaklaşımıyla birlikte, yaygın hataları ve karmaşıklığı önleyen bir sistem kurmanın anahtarlarını size zamanında teslim edecek ve değişikliklere açık olacaktır.


1

Bir projenin yapısı tamamen Projeye ve büyüklüğüne bağlıdır, ancak birkaç klasör ekleyebilirsiniz.

  • Ortak (Sınıfları içeren, örneğin
  • DataAccess (sql kullanarak veri erişimine veya kullandığınız diğer herhangi bir veritabanı sunucusuna ilişkin sınıflar)
  • Stiller (Projenizde herhangi bir CSS dosyanız varsa)
  • Kaynaklar (örneğin Görüntüler, kaynak dosyaları)
  • WorkFlow (Varsa, iş akışına ilişkin sınıflar)

Formları herhangi bir klasöre koymanız gerekmez, formlarınızı uygun şekilde yeniden adlandırın. Demek istediğim, sağduyu, hiç kimse formların kendinizden daha iyi olması için hangi adın olması gerektiğini bilmiyor.

Adlandırma kuralı, eğer sınıfınız "Merhaba Dünya" mesajı basıyorsa, sınıf adı görevle ilgili bir şey olmalı ve sınıfın uygun adı HelloWorld.cs olmalıdır.

örneğin bölgeler de oluşturabilirsiniz

#region Hello ve sonra endregionsonunda dışarı .

Sekmeler için sınıflar oluşturabilirsiniz, yapabileceğinizden eminim ve son bir şey kodunuzu tekrar kullanmaktır, en iyi uygulama yöntemleri yapmak ve gerektiğinde bunları tekrar kullanmaktır.

Kitaplar ? eee.

Her projenin farklı olduğu için size projelerin yapısını söyleyen hiçbir kitap yoktur, bu tür şeyleri deneyimle öğrenirsiniz.

Umarım yardım etti!

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.