Saya mencoba menerapkan metode MVP untuk pertama kalinya, menggunakan WinForms.
Saya mencoba memahami fungsi setiap lapisan.
Dalam program saya, saya memiliki tombol GUI yang ketika diklik membuka jendela openfiledialog.
Jadi menggunakan MVP, GUI menangani peristiwa klik tombol dan kemudian memanggil presenter.openfile ();
Dalam presenter.openfile (), haruskah itu mendelegasikan pembukaan file itu ke lapisan model, atau karena tidak ada data atau logika untuk diproses, haruskah itu hanya bertindak atas permintaan dan membuka jendela openfiledialog?
Pembaruan: Saya telah memutuskan untuk menawarkan hadiah karena saya merasa saya membutuhkan bantuan lebih lanjut tentang ini, dan lebih disukai disesuaikan dengan poin spesifik saya di bawah ini, sehingga saya memiliki konteks.
Oke, setelah membaca tentang MVP, saya telah memutuskan untuk menerapkan Tampilan Pasif. Secara efektif saya akan memiliki banyak kontrol pada Winform yang akan ditangani oleh Presenter dan kemudian tugas didelegasikan ke Model. Poin spesifik saya ada di bawah ini:
Ketika winform dimuat, itu harus mendapatkan tampilan pohon. Apakah saya benar dalam berpikir bahwa tampilan harus memanggil metode seperti: presenter.gettree (), ini pada gilirannya akan mendelegasikan ke model, yang akan mendapatkan data untuk treeview, membuatnya dan mengkonfigurasinya, mengembalikannya ke presenter, yang pada gilirannya akan meneruskan ke tampilan yang kemudian akan dengan mudah menetapkannya ke, katakanlah, panel?
Apakah ini akan sama untuk semua kontrol data di Winform, karena saya juga memiliki datagridview?
Aplikasi Saya, memiliki sejumlah kelas model dengan perakitan yang sama. Ini juga mendukung arsitektur plugin dengan plugin yang perlu dimuat saat startup. Akankah tampilan hanya memanggil metode presenter, yang pada gilirannya akan memanggil metode yang memuat plugin dan menampilkan informasi dalam tampilan? Tingkatan mana yang kemudian akan mengontrol referensi plugin. Apakah tampilan tersebut menyimpan referensi ke mereka atau presenter?
Apakah saya benar dalam berpikir bahwa tampilan harus menangani setiap hal tentang presentasi, dari warna node tampilan pohon, ke ukuran datagrid, dll?
Saya pikir itu adalah perhatian utama saya dan jika saya mengerti bagaimana alurnya untuk ini, saya pikir saya akan baik-baik saja.
Jawaban:
Ini adalah pendapat saya yang sederhana tentang MVP dan masalah spesifik Anda.
Pertama , apa pun yang dapat berinteraksi dengan pengguna, atau hanya ditampilkan, adalah tampilan . Hukum, perilaku, dan karakteristik tampilan seperti itu dijelaskan oleh antarmuka . Antarmuka itu dapat diimplementasikan menggunakan WinForms UI, UI konsol, UI web atau bahkan tanpa UI sama sekali (biasanya saat menguji penyaji) - implementasi konkret tidak masalah selama mematuhi hukum antarmuka tampilan .
Kedua , tampilan selalu dikontrol oleh presenter . Hukum, perilaku dan karakteristik penyaji semacam itu juga dijelaskan oleh antarmuka . Antarmuka tersebut tidak tertarik pada implementasi tampilan konkret selama mematuhi hukum antarmuka tampilan.
Ketiga , karena penyaji mengontrol pandangannya, untuk meminimalkan ketergantungan, sebenarnya tidak ada gunanya memiliki tampilan yang mengetahui apa pun tentang penyaji. Ada kontrak yang disepakati antara penyaji dan tampilan dan itu dinyatakan oleh antarmuka tampilan.
Implikasi dari Ketiga adalah:
Untuk masalah Anda, di atas mungkin terlihat seperti ini dalam kode yang agak disederhanakan:
interface IConfigurationView { event EventHandler SelectConfigurationFile; void SetConfigurationFile(string fullPath); void Show(); } class ConfigurationView : IConfigurationView { Form form; Button selectConfigurationFileButton; Label fullPathLabel; public event EventHandler SelectConfigurationFile; public ConfigurationView() { // UI initialization. this.selectConfigurationFileButton.Click += delegate { var Handler = this.SelectConfigurationFile; if (Handler != null) { Handler(this, EventArgs.Empty); } }; } public void SetConfigurationFile(string fullPath) { this.fullPathLabel.Text = fullPath; } public void Show() { this.form.ShowDialog(); } } interface IConfigurationPresenter { void ShowView(); } class ConfigurationPresenter : IConfigurationPresenter { Configuration configuration = new Configuration(); IConfigurationView view; public ConfigurationPresenter(IConfigurationView view) { this.view = view; this.view.SelectConfigurationFile += delegate { // The ISelectFilePresenter and ISelectFileView behaviors // are implicit here, but in a WinForms case, a call to // OpenFileDialog wouldn't be too far fetched... var selectFilePresenter = Gimme.The<ISelectFilePresenter>(); selectFilePresenter.ShowView(); this.configuration.FullPath = selectFilePresenter.FullPath; this.view.SetConfigurationFile(this.configuration.FullPath); }; } public void ShowView() { this.view.SetConfigurationFile(this.configuration.FullPath); this.view.Show(); } }
Selain di atas, saya biasanya memiliki
IView
antarmuka dasar tempat saya menyimpan fileShow()
dan setiap tampilan pemilik atau judul tampilan yang biasanya menguntungkan pandangan saya.Untuk pertanyaan Anda:
1. Saat winform dimuat, ia harus mendapatkan tampilan pohon. Apakah saya benar dalam berpikir bahwa tampilan harus memanggil metode seperti: presenter.gettree (), ini pada gilirannya akan mendelegasikan ke model, yang akan mendapatkan data untuk treeview, membuatnya dan mengkonfigurasinya, mengembalikannya ke presenter, yang pada gilirannya akan meneruskan ke tampilan yang kemudian akan dengan mudah menetapkannya ke, katakanlah, panel?
2. Apakah ini akan sama untuk semua kontrol data di Winform, karena saya juga memiliki datagridview?
3. Aplikasi Saya, memiliki sejumlah kelas model dengan perakitan yang sama. Ini juga mendukung arsitektur plugin dengan plugin yang perlu dimuat saat startup. Akankah tampilan hanya memanggil metode presenter, yang pada gilirannya akan memanggil metode yang memuat plugin dan menampilkan informasi dalam tampilan? Tingkatan mana yang kemudian akan mengontrol referensi plugin. Apakah tampilan tersebut menyimpan referensi ke mereka atau presenter?
4. Apakah saya benar dalam berpikir bahwa view harus menangani setiap hal tentang presentasi, dari warna node tampilan pohon, ukuran datagrid, dll?
Bagaimana dengan data untuk node yang diklik?
5. Jika ketika saya mengklik treenode, haruskah saya melewati node tertentu ke presenter dan kemudian dari situ presenter akan menentukan data apa yang dibutuhkan dan kemudian menanyakan model untuk data itu, sebelum menampilkannya kembali ke tampilan?
sumber
Presenter, yang berisi semua logika dalam tampilan, harus menanggapi tombol yang diklik seperti yang dikatakan @JochemKempe . Dalam istilah praktis, klik tombol event handler memanggil
presenter.OpenFile()
. Presenter kemudian dapat menentukan apa yang harus dilakukan.Jika memutuskan bahwa pengguna harus memilih file, ia memanggil kembali ke tampilan (melalui antarmuka tampilan) dan membiarkan tampilan, yang berisi semua teknis UI, menampilkan
OpenFileDialog
. Ini adalah perbedaan yang sangat penting karena penyaji tidak boleh melakukan operasi yang terkait dengan teknologi UI yang digunakan.File yang dipilih kemudian akan dikembalikan ke presenter yang melanjutkan logikanya. Ini mungkin melibatkan model atau layanan apa pun yang harus menangani pemrosesan file.
Alasan utama menggunakan pola MVP, imo adalah untuk memisahkan teknologi UI dari logika tampilan. Jadi, penyaji mengatur semua logika sementara tampilan membuatnya tetap terpisah dari logika UI. Ini memiliki efek samping yang sangat bagus membuat penyaji dapat diuji sepenuhnya.
Pembaruan: karena penyaji adalah perwujudan dari logika yang ditemukan dalam satu tampilan tertentu , hubungan tampilan-penyaji adalah IMO hubungan satu-ke-satu. Dan untuk semua tujuan praktis, satu contoh tampilan (katakanlah Formulir) berinteraksi dengan satu contoh penyaji, dan satu contoh penyaji berinteraksi hanya dengan satu contoh tampilan.
Yang mengatakan, dalam implementasi MVP dengan WinForms, presenter selalu berinteraksi dengan tampilan melalui antarmuka yang mewakili kemampuan UI tampilan. Tidak ada batasan tentang tampilan apa yang mengimplementasikan antarmuka ini, sehingga "widget" yang berbeda dapat mengimplementasikan antarmuka tampilan yang sama dan menggunakan kembali kelas penyaji.
sumber
Penyaji harus bertindak atas permintaan dan menunjukkan jendela openfiledialog seperti yang Anda sarankan. Karena tidak ada data yang diperlukan dari model, penyaji dapat, dan seharusnya, menangani permintaan tersebut.
Mari asumsikan Anda membutuhkan data untuk membuat beberapa entitas dalam model Anda. Anda dapat meneruskan aliran melalui ke lapisan akses tempat Anda memiliki metode untuk membuat entitas dari aliran, tetapi saya sarankan Anda menangani penguraian file di presenter Anda dan menggunakan konstruktor atau metode Buat per entitas dalam model Anda.
sumber