Bagaimana cara mengatur MVP untuk solusi Winforms?


14

Saya telah menggunakan MVP dan MVC di masa lalu, dan saya lebih suka MVP karena mengontrol aliran eksekusi jauh lebih baik menurut saya.

Saya telah membuat infrastruktur saya (kelas datastore / repositori) dan menggunakannya tanpa masalah saat mengode data sampel, jadi sekarang saya pindah ke GUI dan menyiapkan MVP saya.

Bagian A

  1. Saya telah melihat MVP menggunakan tampilan sebagai titik masuk, yaitu dalam metode view constructor yang menciptakan presenter, yang pada gilirannya menciptakan model, menghubungkan peristiwa yang diperlukan.

  2. Saya juga telah melihat presenter sebagai titik masuk, di mana pandangan, model dan presenter dibuat, presenter ini kemudian diberi tampilan dan objek model dalam konstruktornya untuk menghubungkan peristiwa.

  3. Seperti pada 2, tetapi model tidak diteruskan ke presenter. Sebaliknya model adalah kelas statis di mana metode dipanggil dan respons dikembalikan secara langsung.

Bagian B

Dalam hal menjaga tampilan dan model dalam sinkronisasi saya telah melihat.

  1. Setiap kali nilai dalam tampilan berubah, yaitu TextChangedacara di .Net / C #. Ini menembakkan DataChangedEventyang dilewatkan ke dalam model, untuk membuatnya tetap sinkron setiap saat. Dan di mana model berubah, yaitu peristiwa latar belakang yang didengarnya, maka tampilan diperbarui melalui ide yang sama untuk memunculkan a DataChangedEvent. Ketika seorang pengguna ingin melakukan perubahan, SaveEventia akan menyala, meneruskannya ke dalam model untuk melakukan save. Dalam hal ini model meniru data tampilan dan memproses tindakan.

  2. Mirip dengan # b1, namun tampilan tidak disinkronkan dengan model setiap saat. Alih-alih ketika pengguna ingin melakukan perubahan, SaveEventdipecat dan presenter mengambil detail terbaru dan meneruskannya ke dalam model. dalam hal ini model tidak tahu tentang data tampilan sampai diminta untuk menindaklanjutinya, dalam hal ini ia melewatkan semua detail yang diperlukan.

Bagian C

Menampilkan objek bisnis dalam tampilan, yaitu objek (MyClass) bukan data primitif (int, dobel)

  1. Tampilan memiliki bidang properti untuk semua datanya yang akan ditampilkan sebagai objek domain / bisnis. Seperti view.Animalsmemaparkan IEnumerable<IAnimal>properti, meskipun tampilan memprosesnya menjadi Node dalam TreeView. Kemudian untuk hewan yang dipilih itu akan diekspos SelectedAnimalsebagai IAnimalproperti.

  2. Pandangan tidak memiliki pengetahuan tentang objek domain, itu memperlihatkan properti untuk primitif / framework (.Net / Java) termasuk hanya tipe objek. Dalam hal ini presenter akan melewatkan objek adaptor objek domain, adaptor kemudian akan menerjemahkan objek bisnis yang diberikan ke kontrol yang terlihat pada tampilan. Dalam hal ini adaptor harus memiliki akses ke kontrol aktual pada tampilan, bukan sembarang tampilan sehingga menjadi lebih erat.

Bagian D

Beberapa tampilan digunakan untuk membuat kontrol tunggal. yaitu Anda memiliki tampilan yang kompleks dengan model sederhana seperti menyimpan objek dari berbagai jenis. Anda dapat memiliki sistem menu di samping dengan setiap klik pada item kontrol yang sesuai ditampilkan.

  1. Anda membuat satu tampilan besar, yang berisi semua kontrol individu yang diekspos melalui antarmuka tampilan.

  2. Anda memiliki beberapa tampilan. Anda memiliki satu tampilan untuk menu dan panel kosong. Tampilan ini menciptakan tampilan lain yang diperlukan tetapi tidak menampilkannya (terlihat = salah), tampilan ini juga mengimplementasikan antarmuka untuk setiap tampilan yang dikandungnya (yaitu tampilan anak) sehingga dapat terpapar ke satu presenter. Panel kosong diisi dengan tampilan lain ( Controls.Add(myview)) dan ( (myview.visible = true). Peristiwa-peristiwa yang diangkat dalam pandangan "anak" ini ditangani oleh pandangan orang tua yang pada gilirannya meneruskan acara tersebut kepada presenter, dan sebaliknya visa untuk memasok acara kembali ke elemen anak.

  3. Setiap tampilan, baik itu tampilan induk utama atau anak kecil masing-masing ditransfer ke sana sendiri presenter dan model. Anda benar-benar dapat menjatuhkan kontrol tampilan ke bentuk yang sudah ada dan itu akan memiliki fungsionalitas siap, hanya perlu kabel ke presenter di belakang layar.

Bagian E

Jika semuanya memiliki antarmuka, sekarang berdasarkan bagaimana MVP dilakukan dalam contoh di atas akan mempengaruhi jawaban ini karena mereka mungkin tidak kompatibel lintas.

  1. Semuanya memiliki antarmuka, View, Presenter, dan Model. Masing-masing ini jelas memiliki implementasi konkret. Bahkan jika Anda hanya memiliki satu tampilan, model, dan presenter yang konkret.

  2. Tampilan dan Model memiliki antarmuka. Ini memungkinkan pandangan dan model berbeda. Presenter membuat / diberi objek tampilan dan model dan itu hanya berfungsi untuk menyampaikan pesan di antara mereka.

  3. Hanya tampilan yang memiliki antarmuka. Model memiliki metode statis dan tidak dibuat, sehingga tidak perlu antarmuka. Jika Anda menginginkan model yang berbeda, presenter memanggil serangkaian metode kelas statis yang berbeda. Menjadi statis, Model tidak memiliki tautan ke presenter.

Pikiran pribadi

Dari semua variasi berbeda yang telah saya sajikan (kebanyakan saya mungkin telah menggunakan dalam beberapa bentuk) yang saya yakin ada lebih banyak. Saya lebih suka A3 menjaga logika bisnis dapat digunakan kembali di luar hanya MVP, B2 untuk lebih sedikit duplikasi data dan lebih sedikit peristiwa yang dipecat. C1 untuk tidak menambahkan di kelas lain, tentu saja menempatkan sejumlah kecil logika non unit yang dapat diuji ke dalam tampilan (bagaimana objek domain divisualisasikan) tetapi ini bisa ditinjau kode, atau hanya dilihat dalam aplikasi. Jika logikanya kompleks saya akan setuju untuk kelas adaptor tetapi tidak dalam semua kasus. Untuk bagian D, saya merasa D1 menciptakan tampilan yang terlalu besar setidaknya untuk contoh menu. Saya telah menggunakan D2 dan D3 sebelumnya. Masalah dengan D2 adalah Anda akhirnya harus menulis banyak kode untuk merutekan acara ke dan dari presenter ke tampilan anak yang benar, dan itu tidak kompatibel dengan drag / drop, setiap kontrol baru perlu lebih banyak kabel untuk mendukung presenter tunggal. D3 adalah pilihan saya yang lebih disukai tetapi menambahkan lebih banyak kelas sebagai presenter dan model untuk menangani tampilan, bahkan jika tampilan sangat sederhana atau tidak perlu digunakan kembali. Saya pikir campuran D2 dan D3 terbaik berdasarkan keadaan. Mengenai bagian E, saya pikir semua yang memiliki antarmuka bisa berlebihan saya sudah melakukannya untuk domain / objek bisnis dan sering melihat tidak ada keuntungan dalam "desain" dengan melakukannya, tetapi itu membantu dalam mengejek objek dalam pengujian. Secara pribadi saya akan melihat E2 sebagai solusi klasik, meskipun telah melihat E3 digunakan dalam 2 proyek yang telah saya kerjakan sebelumnya. Saya pikir campuran D2 dan D3 terbaik berdasarkan keadaan. Mengenai bagian E, saya pikir semua yang memiliki antarmuka bisa berlebihan saya sudah melakukannya untuk domain / objek bisnis dan sering melihat tidak ada keuntungan dalam "desain" dengan melakukannya, tetapi itu membantu dalam mengejek objek dalam pengujian. Secara pribadi saya akan melihat E2 sebagai solusi klasik, meskipun telah melihat E3 digunakan dalam 2 proyek yang telah saya kerjakan sebelumnya. Saya pikir campuran D2 dan D3 terbaik berdasarkan keadaan. Mengenai bagian E, saya pikir semua yang memiliki antarmuka bisa berlebihan saya sudah melakukannya untuk domain / objek bisnis dan sering melihat tidak ada keuntungan dalam "desain" dengan melakukannya, tetapi itu membantu dalam mengejek objek dalam pengujian. Secara pribadi saya akan melihat E2 sebagai solusi klasik, meskipun telah melihat E3 digunakan dalam 2 proyek yang telah saya kerjakan sebelumnya.

Pertanyaan

Apakah saya menerapkan MVP dengan benar? Apakah ada cara yang benar untuk melakukannya?

Saya telah membaca karya Martin Fowler yang memiliki variasi, dan saya ingat ketika saya pertama kali mulai melakukan MVC, saya mengerti konsepnya, tetapi pada awalnya tidak bisa mengetahui di mana titik masuknya, semuanya memiliki fungsi sendiri tetapi apa yang mengontrol dan menciptakan yang asli mengatur objek MVC.


2
Alasan untuk mengajukan pertanyaan ini adalah saya mencari untuk memperbaikinya pada hampir upaya pertama. Saya lebih suka memiliki MVP standar untuk diikuti, daripada membuat 6 aplikasi menggunakan variasi yang berbeda untuk pola yang sama.
JonWillis

Sempurna ... Saya ingin menanyakannya sejak lama
The King

Jawaban:


4

Banyak hal yang Anda presentasikan di sini sangat masuk akal dan sehat. Beberapa pilihan akan bergantung pada spesifik dengan aplikasi dan mana yang "terasa" benar. Seperti halnya sebagian besar waktu, tidak akan ada satu jawaban yang benar. Beberapa pilihan akan masuk akal di sini dan pilihan itu bisa sepenuhnya salah untuk aplikasi dan keadaan selanjutnya. Tanpa mengetahui beberapa hal spesifik dari aplikasi ini, saya pikir Anda berada di jalur yang benar dan telah membuat beberapa keputusan yang masuk akal.

Bagi saya, saya merasa bahwa Presenter hampir selalu menjadi titik masuk. Memiliki UI sebagai titik masuknya menempatkan terlalu banyak logika di UI dan menghilangkan kemampuan untuk mengganti UI baru tanpa perubahan kode besar. Dan memang itu pekerjaan presenter.


Mungkin pertanyaan yang harus saya tanyakan adalah salah satu cara untuk menggunakan MVP yang salah. Saya akan setuju dengan variasi yang sesuai dengan skenario yang berbeda, tetapi merasa harus ada pendekatan yang diterima secara umum. Contoh-contoh MVP adalah semua contoh sederhana dan hampir semua dengan kebutuhan yang sama, untuk mengedit objek domain dan menyimpan perubahan. Namun dari contoh-contoh dengan tujuan yang sama variasi di atas telah dihasilkan. Saya baru saja mengkodekan bagian dari aplikasi yang menggunakan acara yang dipecat dalam tampilan untuk ditangani di presenter tetapi saya bisa meminta pandangan memegang referensi ke presenter dan langsung memanggil metode.
JonWillis

Saya setuju dengan segala upaya yang akan menyederhanakan pandangan untuk membenarkan tidak sedang diuji unit, maka presenter harus memiliki kendali. Satu-satunya kekhawatiran saya dengan ini (berpikir di kepala saya jadi bisa salah) adalah mengatakan winforms / usercontrols mungkin perlu dikaitkan dengan elemen induk dan bertanya-tanya apakah logika tambahan diperlukan dalam presenter untuk menuliskannya.
JonWillis

@ Jon - Cara MVP salah? Dalam buku saya itu akan terjadi ketika pandangan tahu tentang presenter. Ini mungkin tidak "salah" dalam arti bahwa itu bekerja tetapi itu tidak akan menjadi MVP, itu berubah menjadi sesuatu yang lain pada saat itu. Masalah dengan pola desain adalah bahwa contoh selalu bersih dan sesederhana mungkin. Kemudian ketika Anda pergi untuk mengimplementasikannya untuk pertama kalinya dan dunia nyata melompat dan berkata 'hei aplikasi nyata jauh lebih rumit daripada contoh kecil itu.' Di situlah pertumbuhan Anda dimulai. Temukan apa yang cocok untuk Anda dan keadaan aplikasi.
Walter

Terima kasih atas sarannya. Saya ingat belajar MVC di universitas. Kedengarannya hebat tetapi dengan kanvas kosong Anda bertanya-tanya di mana untuk memulai dan bagaimana cara kerjanya. Dalam hal MVP yang salah, maksud saya adalah salah satu ide / mode MVC saya diposting di atas cara yang salah melakukannya, yaitu ketika pandangan tahu bagaimana presenter bekerja. Atau jika pandangan memiliki referensi ke antarmuka presenter atau tipe beton dll. Hanya banyak variasi berbeda yang semuanya dapat bekerja untuk tujuan yang sama.
JonWillis

1
@ Jon - Variasi Anda sangat sesuai dengan semangat MVP. Sejauh bekerja dengan antarmuka atau tipe konkret, itu akan tergantung pada keadaan aplikasi. Jika aplikasinya cukup kecil, tidak terlalu rumit, maka mungkin menambahkan antarmuka tidak perlu. Saya suka menjaga hal-hal sesederhana mungkin, sampai cukup jelas bahwa aplikasi benar-benar perlu menerapkan arsitektur X. Lihat jawaban ini untuk detail lebih lanjut: programmers.stackexchange.com/questions/34547/…
Walter

4

Kami menggunakan bentuk MVP yang dimodifikasi pada aplikasi .NET 2.0 Winforms kami. Dua bagian yang kami lewatkan adalah adaptor yang dimodifikasi dari WPF ViewModel, dan menambahkan pengikatan data. Pola spesifik kami adalah MVPVM.

Kami terhubung sebagai penyaji-pertama dalam hampir setiap kasus, kecuali untuk kontrol-kontrol pengguna khusus, yang terhubung terlebih dahulu-untuk kenyamanan perancang. Kami menggunakan injeksi dependensi, ViewModels yang dihasilkan kode, BDD untuk presenter, dan TDD / TED untuk model.

VM hanyalah sebuah properti yang besar dan datar yang meningkatkan PropertyChanged ketika diubah. Sangat mudah untuk menghasilkan ini dengan kode (dan tes unit latihan terkait). Kami menggunakannya untuk membaca dan menulis ke kontrol yang dapat berinteraksi dengan pengguna, dan mengendalikan status yang diaktifkan. ViewModel digabungkan dengan View, karena kami menggunakan penyatuan data untuk hampir semua hal lain.

View kadang-kadang akan memiliki metode untuk mencapai hal-hal yang VM tidak bisa. Ini biasanya mengontrol visibilitas item (WinForms bisa pilih-pilih tentang hal itu), dan hal-hal yang menolak untuk dijadikan databound. Tampilan selalu memperlihatkan peristiwa seperti "Login" atau "Restart", dengan EventArgs yang sesuai untuk bertindak pada perilaku pengguna. Kecuali jika kami harus menggunakan retasan seperti "View.ShowLoginBox", View sepenuhnya dapat dipertukarkan selama memenuhi persyaratan desain umum.

Kami membutuhkan sekitar 6-8 bulan untuk menemukan pola ini. Ini memiliki banyak potongan, tetapi sangat fleksibel dan sangat kuat. Implementasi spesifik kami sangat asinkron dan berdasarkan-peristiwa, yang mungkin hanya merupakan artifak dari persyaratan lain daripada efek samping dari perilaku desain. Sebagai contoh, saya menambahkan sinkronisasi utas ke baseclass dari mana VM kami mewarisi (yang hanya mengekspos metode OnPropertyChanged untuk meningkatkan peristiwa) - dan puf, sekarang kita dapat memiliki presenter dan model multithreaded.


Saya tahu MVPVM Anda mungkin menarik secara komersial, tetapi jika boleh Anda berikan kode sampel? Di samping catatan, di mana Anda menggambar garis pada apa yang ada dalam model dan apa yang terjadi di presenter. Saya telah melihat presenter menjadi sangat dasar sehingga mereka menangani peristiwa tampilan dan hanya memanggil model, kepada presenter mengakses lapisan data untuk meneruskan objek bisnis ke model, sampai model diganti oleh presenter.
JonWillis

Yap, saya selesaikan sebuah contoh. Ini akan sedikit disesuaikan dengan bisnis kami, karena saya menggunakannya sebagai alat pelatihan in-house.
Bryan Boettcher

Terima kasih, saya akan memeriksanya pada akhir pekan untuk melihat apakah saya memahaminya
JonWillis

@insta - tautannya mati, bisakah Anda mengunggahnya kembali ke suatu tempat?
Yves Schelpe

1
Sial, saya baru saja menghapusnya seminggu yang lalu. Angka :(
Bryan Boettcher

2

Saya menggunakan versi PureMvc yang telah dimodifikasi untuk .Net, dan kemudian diperluas sendiri.

Saya sudah terbiasa dengan PureMvc dari menggunakannya di aplikasi Flex. Ini adalah jenis kerangka tulang sehingga cukup mudah untuk beradaptasi jika Anda ingin menyesuaikannya.

Saya mengambil kebebasan berikut ini:

  • Menggunakan refleksi saya bisa mendapatkan properti pribadi di view-mediator untuk pergi ke kelas bentuk dan mengambil referensi (pribadi) untuk setiap kontrol yang saya mediasi.
  • Dengan menggunakan refleksi saya dapat secara otomatis menyambungkan kontrol ke tanda tangan acara di mediator saya, yang bersifat umum, jadi saya hanya mengaktifkan parameter pengirim.
  • Biasanya, PureMvc ingin mediator turunan untuk menentukan minat notifikasi mereka dalam fungsi yang akan mengembalikan array string. Karena minat saya sebagian besar statis, dan saya ingin memiliki cara yang lebih mudah untuk melihat kepentingan mediator, saya melakukan modifikasi sehingga mediator juga dapat menyatakan minatnya dengan menetapkan variabel anggota dengan tanda tangan tertentu: _ _ _ <classname> _ <notification-name>. Dengan cara ini saya bisa melihat apa yang terjadi menggunakan pohon anggota IDE daripada melihat ke dalam suatu fungsi.

Di PureMvc, Anda bisa menggunakan Perintah untuk menjadi titik masuk, perintah Mulai yang khas akan mengatur Model sejauh mungkin, lalu buat MainForm, buat dan daftarkan mediator untuk dan dengan formulir itu, lalu lakukan Application.Run pada formulir.

Mediator untuk formulir akan bertanggung jawab untuk mengatur semua sub-mediator, beberapa di antaranya dapat diotomatisasi dengan, sekali lagi, menggunakan trik refleksi.

Sistem yang saya gunakan kompatibel dengan drag / drop, jika saya mengerti maksud Anda. Bentuk aktual semua dibuat dalam VS, tetapi pengalaman saya hanya dengan bentuk yang memiliki kontrol yang dibuat secara statis. Hal-hal seperti item menu yang dibuat secara dinamis tampaknya layak dengan sedikit penyesuaian mediator untuk menu atau submenu itu. Di mana itu akan menjadi berbulu adalah ketika mediator tidak memiliki elemen root statis untuk dihubungkan dan Anda masuk ke dalam menciptakan mediator 'instance' yang dinamis.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.