Bagaimana cara menyusun proyek dengan benar di winform?

26

Beberapa waktu yang lalu saya mulai membuat aplikasi winform dan saat itu kecil dan saya tidak memikirkan bagaimana cara menyusun proyek.

Sejak itu saya menambahkan fitur tambahan yang saya butuhkan dan folder proyek semakin besar dan lebih besar dan sekarang saya pikir sudah waktunya untuk menyusun proyek dalam beberapa cara, tetapi saya tidak yakin apa cara yang tepat, jadi saya punya beberapa pertanyaan.

Bagaimana cara merestrukturisasi folder proyek dengan benar?

Saat ini saya sedang memikirkan sesuatu seperti ini:

  • Buat Folder untuk Formulir
  • Buat Folder untuk kelas Utilitas
  • Buat Folder untuk Kelas yang hanya berisi data

Apa konvensi penamaan saat menambahkan kelas?

Haruskah saya juga mengganti nama kelas sehingga fungsinya dapat diidentifikasi dengan hanya melihat nama mereka? Misalnya mengganti nama semua kelas formulir, sehingga nama mereka berakhir dengan Formulir . Atau apakah ini tidak perlu jika folder khusus untuk mereka dibuat?

Apa yang harus dilakukan, sehingga tidak semua kode untuk formulir utama berakhir di Form1.cs

Masalah lain yang saya temui adalah karena bentuk utama semakin masif dengan setiap fitur yang saya tambahkan, file kode (Form1.cs) semakin besar. Misalnya saya memiliki TabControl dan setiap tab memiliki banyak kontrol dan semua kode berakhir di Form1.cs. Bagaimana cara menghindarinya?

Juga, Apakah Anda tahu ada artikel atau buku yang berhubungan dengan masalah ini?

pengguna850010
sumber

Jawaban:

24

Sepertinya Anda telah jatuh ke dalam beberapa perangkap umum, tetapi jangan khawatir, mereka dapat diperbaiki :)

Pertama, Anda perlu melihat aplikasi Anda sedikit berbeda dan mulai memecahnya menjadi potongan-potongan. Kita bisa membagi bongkahan menjadi dua arah. Pertama kita dapat memisahkan logika kontrol (Aturan bisnis, kode akses data, kode hak pengguna, semua hal semacam itu) dari kode UI. Kedua kita dapat memecah kode UI menjadi beberapa bagian.

Jadi kita akan melakukan bagian terakhir terlebih dahulu, memecah UI menjadi beberapa bagian. Cara termudah untuk melakukan ini adalah memiliki bentuk host tunggal di mana Anda menulis UI Anda dengan kontrol pengguna. Setiap kontrol pengguna akan bertanggung jawab atas suatu wilayah formulir. Jadi bayangkan aplikasi Anda memiliki daftar pengguna, dan ketika Anda mengklik pengguna kotak teks di bawahnya diisi dengan rincian mereka. Anda bisa memiliki satu kontrol pengguna yang mengelola tampilan daftar pengguna dan yang kedua mengelola tampilan detail pengguna.

Trik sebenarnya di sini adalah bagaimana Anda mengelola komunikasi antara kontrol. Anda tidak ingin 30 kontrol pengguna pada formulir semua memegang referensi secara acak satu sama lain dan memanggil metode pada mereka.

Jadi, Anda membuat antarmuka untuk setiap kontrol. Antarmuka berisi operasi kontrol akan menerima dan setiap peristiwa yang ditimbulkannya. Ketika Anda berpikir tentang aplikasi ini, Anda tidak peduli apakah pemilihan daftar kotak daftar berubah, Anda tertarik pada kenyataan bahwa pengguna baru telah berubah.

Jadi menggunakan aplikasi contoh kami, antarmuka pertama untuk kontrol yang menjadi tuan rumah kotak daftar pengguna akan mencakup acara yang disebut UserChanged yang melewatkan objek pengguna.

Ini bagus karena sekarang jika Anda bosan dengan listbox dan ingin kontrol mata ajaib zoomy 3d, Anda cukup kode ke antarmuka yang sama dan pasang :)

Ok, jadi bagian kedua, memisahkan logika UI dari logika domain. Nah, ini jalan yang sudah usang dan saya sarankan Anda melihat pola MVP di sini. Sangat sederhana.

Setiap kontrol sekarang disebut Tampilan (V dalam MVP) dan kami telah membahas sebagian besar dari apa yang diperlukan di atas. Dalam hal ini, kontrol dan antarmuka untuk itu.

Yang kami tambahkan hanyalah model dan presenternya.

Model ini berisi logika yang mengelola status aplikasi Anda. Anda tahu hal-hal, itu akan pergi ke database untuk mendapatkan pengguna, menulis ke database ketika Anda menambahkan pengguna, dan seterusnya. Idenya adalah Anda dapat menguji semua ini dalam isolasi lengkap dari yang lainnya.

Presenter sedikit lebih sulit untuk dijelaskan. Ini adalah kelas yang terletak di antara model dan View. Ini dibuat oleh view dan view masuk sendiri ke presenter menggunakan antarmuka yang telah kita bahas sebelumnya.

Presenter tidak harus memiliki antarmuka sendiri, tetapi saya tetap ingin membuatnya. Jadikan apa yang Anda ingin presenter lakukan secara eksplisit.

Jadi presenter akan memaparkan metode seperti ListOfAllUsers yang View akan gunakan untuk mendapatkan daftar penggunanya, atau Anda bisa meletakkan metode AddUser dengan View dan memanggilnya dari presenter. Saya lebih suka yang terakhir. Dengan begitu presenter dapat menambahkan pengguna ke listbox kapan pun diinginkan.

Presenter juga akan memiliki properti seperti CanEditUser, yang akan mengembalikan true jika pengguna yang dipilih dapat diedit. View kemudian akan menanyakan bahwa setiap kali perlu tahu. Anda mungkin ingin yang dapat diedit dalam warna hitam dan hanya membaca yang berwarna abu-abu. Secara teknis itu adalah keputusan untuk Tampilan karena UI fokus, apakah pengguna dapat diedit di tempat pertama adalah untuk Presenter. Presenter tahu karena berbicara dengan Model.

Jadi secara ringkas, gunakan MVP. Microsoft menyediakan sesuatu yang disebut SCSF (Smart Client Software Factory) yang menggunakan MVP seperti yang saya jelaskan. Itu melakukan banyak hal lain juga. Ini cukup rumit dan saya tidak suka cara mereka melakukan semuanya, tetapi mungkin bisa membantu.

Ian
sumber
8

Saya pribadi lebih suka memisahkan area yang berbeda dari perhatian di antara beberapa majelis alih-alih menyatukan semuanya menjadi satu yang dapat dieksekusi.

Biasanya, saya lebih suka menyimpan jumlah minimal kode di titik masuk aplikasi - Tidak ada logika bisnis, tidak ada kode GUI dan tidak ada akses data (basis data / akses file / koneksi jaringan / dll); Saya biasanya membatasi kode titik masuk (yaitu yang dapat dieksekusi) untuk sesuatu di sepanjang baris

  • Membuat dan Menginisialisasi berbagai komponen aplikasi dari semua majelis dependen
  • Mengkonfigurasi komponen pihak ketiga mana pun yang bergantung pada seluruh aplikasi (mis. Log4Net untuk output diagnostik)
  • juga saya mungkin akan memasukkan "tangkap semua pengecualian dan rekam jejak stack" ketik sedikit kode dalam fungsi utama yang akan membantu mencatat keadaan dari setiap kegagalan kritis / fatal yang tidak terduga.

Adapun komponen aplikasi itu sendiri, saya biasanya bertujuan setidaknya tiga dalam aplikasi kecil

  • Lapisan Akses Data (koneksi basis data, akses file, dll) - tergantung pada kerumitan setiap data yang disimpan / disimpan yang digunakan oleh aplikasi, mungkin ada beberapa rakitan ini - Saya mungkin akan membuat rakitan terpisah untuk penanganan basis data (Mungkin bahkan beberapa majelis jika berinteraksi dengan database melibatkan sesuatu yang kompleks - misalnya jika Anda stucx dengan database yang dirancang dengan buruk, Anda mungkin perlu menangani hubungan DB dalam kode, karena itu mungkin masuk akal untuk menulis beberapa modul untuk penyisipan dan pengambilan)

  • Logic Layer - "daging" utama yang berisi semua keputusan dan algoritma yang membuat aplikasi Anda berfungsi. Keputusan ini seharusnya tidak tahu apa-apa tentang GUI (siapa bilang ada GUI?), Dan seharusnya sama sekali tidak tahu apa-apa tentang database (Huh? Ada database? Mengapa tidak file?). Lapisan logika yang dirancang dengan baik diharapkan dapat "dicabut" dan dibuang ke aplikasi lain tanpa perlu dikompilasi ulang. Dalam aplikasi yang rumit, mungkin ada banyak kumpulan logika ini (karena Anda mungkin hanya ingin merobek 'potongan-potongan' tanpa menyeret sepanjang sisa aplikasi)

  • Lapisan presentasi (yaitu GUI); Dalam aplikasi kecil, mungkin hanya ada satu "bentuk utama" dengan beberapa kotak dialog yang semuanya bisa masuk ke dalam satu rakitan - dalam aplikasi yang lebih besar, mungkin ada rakitan terpisah untuk seluruh bagian fungsional GUI. Kelas-kelas di sini akan melakukan sedikit lebih banyak daripada membuat interaksi pengguna berfungsi - itu akan lebih dari sekadar shell dengan beberapa validasi input dasar, menangani animasi apa pun, dll. Setiap klik peristiwa / tombol yang "melakukan sesuatu" akan diteruskan ke lapisan logika (jadi lapisan presentasi saya akan benar-benar tidak mengandung logika aplikasi apa pun, tetapi juga tidak akan menempatkan beban kode GUI apa pun pada lapisan logika - sehingga setiap bilah kemajuan atau hal-hal mewah lainnya juga akan duduk di majelis presentasi / ies)

Alasan utama saya untuk memisahkan lapisan Presentasi, Logika, dan Data ke rakitan terpisah adalah ini: Saya merasa lebih baik untuk dapat menjalankan logika aplikasi utama tanpa basis data atau GUI Anda.

Dengan kata lain; jika saya ingin menulis executable lain yang berperilaku persis sama dengan aplikasi Anda, tetapi menggunakan antarmuka commandline, atau antarmuka web; dan menukar penyimpanan database untuk penyimpanan file (atau jenis database yang berbeda mungkin), maka saya dapat melakukannya tanpa perlu menyentuh logika aplikasi utama sama sekali - yang perlu saya lakukan hanyalah menulis sedikit alat baris perintah dan model data lain, lalu "tancapkan semuanya", dan saya siap berangkat.

Anda mungkin berpikir, "Yah, saya tidak akan pernah mau melakukan semua itu sehingga tidak masalah jika saya tidak bisa bertukar hal-hal ini di sekitar" - intinya adalah bahwa salah satu keunggulan dari aplikasi modular adalah kemampuan untuk mengekstrak 'potongan' (Tanpa perlu mengkompilasi ulang apa pun), dan menggunakan kembali potongan-potongan itu di tempat lain. Untuk menulis kode seperti ini, biasanya memaksa Anda untuk berpikir panjang dan keras tentang prinsip-prinsip desain - Anda harus berpikir tentang menulis lebih banyak antarmuka, dan berpikir dengan hati-hati tentang pertukaran berbagai prinsip SOLID (Dalam hal yang sama cara yang Anda lakukan untuk Pengembangan Perilaku-Didorong-atau TDD)

Terkadang mencapai pemisahan ini dari gumpalan kode monolitik yang ada sedikit menyakitkan dan membutuhkan banyak refactoring yang cermat - tidak apa-apa, Anda harus dapat melakukannya secara bertahap - Anda bahkan dapat mencapai titik di mana ada terlalu banyak majelis dan Anda memutuskan untuk kembali ke arah lain dan mulai menyelesaikan hal-hal bersama lagi (terlalu jauh ke arah yang berlawanan dapat memiliki efek membuat majelis itu agak tidak berguna pada mereka sendiri)

Ben Cottrell
sumber
4

Sesuai struktur folder, apa yang Anda sarankan OK secara umum. Anda mungkin perlu menambahkan folder untuk sumber daya (kadang-kadang orang membuat sumber daya sehingga setiap rangkaian sumber daya dikelompokkan dalam kode bahasa ISO untuk mendukung beberapa bahasa), gambar, skrip basis data, preferensi pengguna (jika tidak ditangani sebagai sumber daya), font , dll eksternal, dll lokal, dll.

Apa konvensi penamaan saat menambahkan kelas?

Tentu saja, Anda ingin memisahkan setiap kelas di luar formulir. Saya akan merekomendasikan juga, file per kelas (walaupun MS tidak melakukannya dalam kode yang dihasilkan untuk EF misalnya).

Banyak orang menggunakan kata benda pendek yang bermakna dalam bentuk jamak (misalnya Pelanggan). Beberapa ptrfer nama agar dekat dengan nama tunggal untuk tabel database yang sesuai (jika Anda menggunakan 1-1 pemetaan antara objek dan tabel).

Untuk kelas penamaan ada banyak sumber, misalnya lihat: .net Konvensi Penamaan dan Standar Pemrograman - Praktik Terbaik dan / atau STOVF-C # Pedoman Pengkodean #

Apa yang harus dilakukan, sehingga tidak semua kode untuk formulir utama berakhir di Form1.cs

Kode pembantu harus masuk ke satu atau beberapa kelas pembantu. Kode lain yang sangat umum untuk kontrol GUI seperti menerapkan preferensi pengguna ke kisi, dapat dihapus dari formulir dan dapat ditambahkan ke kelas pembantu atau dengan mengklasifikasikan kontrol yang dimaksud dan membuat metode yang diperlukan di sana.

Karena sifat peristiwa-tindakan dari MS Windows Forms, tidak ada yang saya tahu yang dapat membantu Anda mengambil kode dari bentuk utama tanpa menambahkan ambiguitas dan upaya. Namun, MVVM dapat menjadi pilihan (dalam proyek mendatang), lihat misalnya: MVVM untuk Formulir Windows .

Tidak ada kesempatan
sumber
2

Pertimbangkan MVP sebagai opsi karena akan membantu Anda mengatur logika presentasi, yang merupakan segalanya dalam aplikasi bisnis besar. Dalam kehidupan nyata, logika aplikasi sebagian besar berada di dalam basis data, jadi Anda jarang perlu menulis lapisan bisnis dalam kode asli, meninggalkannya hanya dengan kebutuhan untuk memiliki fungsi presentasi yang terstruktur dengan baik.

Struktur seperti MVP akan menghasilkan seperangkat presenter, atau pengontrol jika Anda suka, yang akan berkoordinasi satu sama lain dan tidak akan bercampur dengan UI atau kode di belakang barang. Anda bahkan dapat menggunakan UI yang berbeda dengan pengontrol yang sama.

Akhirnya, sumber daya pengorganisasian yang sederhana, komponen-komponen yang dipisahkan dan menentukan depedensi dengan IoC dan DI, bersama dengan pendekatan MVP akan memberi Anda kunci untuk membangun sistem yang menghindari kesalahan dan kompleksitas umum, dikirimkan dalam waktu dan terbuka untuk perubahan.

Panos Roditakis
sumber
1

Struktur proyek sangat tergantung pada Proyek dan ukurannya, namun Anda dapat menambahkan beberapa folder misalnya

  • Umum (Mengandung kelas misalnya Utilitas)
  • DataAccess (kelas yang terkait dengan akses data menggunakan sql atau server database lain yang Anda gunakan)
  • Gaya (Jika Anda punya file CSS di proyek Anda)
  • Sumberdaya (mis. Gambar, file sumber)
  • WorkFlow (Kelas yang terkait dengan alur kerja jika Anda punya)

Anda tidak perlu memasukkan Formulir ke dalam folder apa pun, cukup ganti nama formulir Anda. Maksud saya akal sehat tidak ada yang tahu nama apa yang harus menjadi bentuk Anda lebih baik daripada diri Anda sendiri.

Konvensi penamaan seperti jika kelas Anda mencetak pesan "Hello World" maka nama kelas haruslah sesuatu yang berkaitan dengan tugas dan nama kelas yang sesuai harus HelloWorld.cs.

Anda dapat membuat daerah juga misalnya

#region Hello dan kemudian keluar endregiondi akhir.

Anda dapat membuat kelas untuk tab, cukup yakin Anda bisa, dan satu hal terakhir adalah menggunakan kembali kode Anda jika memungkinkan, praktik terbaik adalah membuat metode dan menggunakannya lagi di mana diperlukan.

Buku? erm.

Tidak ada buku yang memberi tahu Anda struktur proyek karena setiap proyek berbeda, Anda mempelajari hal-hal semacam ini berdasarkan pengalaman.

Semoga ini bisa membantu!

Muhammad Raja
sumber