Prinsip Tanggung Jawab Tunggal menyatakan bahwa "kelas harus memiliki satu alasan perubahan".
Dalam pola MVC, tugas Pengontrol adalah memediasi antara View dan Model. Ini menawarkan antarmuka untuk tampilan untuk melaporkan tindakan yang dibuat oleh pengguna pada GUI (misalnya memungkinkan tampilan untuk memanggil controller.specificButtonPressed()
), dan dapat memanggil metode yang sesuai pada Model untuk memanipulasi data itu atau menjalankan operasi itu (misalnya model.doSomething()
) .
Ini berarti:
- Pengontrol perlu mengetahui tentang GUI, untuk menawarkan tampilan antarmuka yang sesuai untuk melaporkan tindakan pengguna.
- Ini juga perlu tahu tentang logika dalam Model, agar dapat memanggil metode yang sesuai pada Model.
Itu berarti ada dua alasan untuk berubah : perubahan dalam GUI, dan perubahan dalam logika bisnis.
Jika GUI berubah, misalnya tombol baru ditambahkan, Pengontrol mungkin perlu menambahkan metode baru untuk memungkinkan Tampilan melaporkan pengguna yang menekan tombol ini.
Dan jika logika bisnis dalam Model berubah, Controller mungkin harus berubah untuk memanggil metode yang benar pada Model.
Oleh karena itu, Pengendali memiliki dua kemungkinan alasan untuk berubah . Apakah itu merusak SRP?
sumber
Jawaban:
Jika Anda melanjutkan dengan alasan tentang SRP, Anda akan mengetahui bahwa "satu tanggung jawab" sebenarnya adalah istilah yang kenyal. Otak manusia kita entah bagaimana dapat membedakan antara tanggung jawab yang berbeda dan beberapa tanggung jawab dapat diabstraksikan menjadi satu tanggung jawab "umum". Misalnya, bayangkan dalam keluarga 4 orang yang umum ada satu anggota keluarga yang bertanggung jawab untuk membuat sarapan. Sekarang, untuk melakukan ini, kita harus merebus telur dan roti panggang dan tentu saja menyiapkan secangkir teh hijau yang sehat (ya, teh hijau adalah yang terbaik). Dengan cara ini Anda dapat memecah "membuat sarapan" menjadi potongan-potongan kecil yang secara bersamaan disarikan menjadi "membuat sarapan". Perhatikan bahwa setiap karya juga merupakan tanggung jawab yang dapat misalnya didelegasikan kepada orang lain.
Kembali ke MVC: jika memediasi antara model dan tampilan bukan hanya satu tanggung jawab tetapi dua, lalu apa lapisan abstraksi berikutnya di atas, menggabungkan keduanya? Jika Anda tidak dapat menemukannya, Anda tidak bisa abstrak dengan benar atau tidak ada yang berarti Anda benar. Dan saya merasa itu adalah kasus dengan controller, menangani tampilan dan model.
sumber
Jika kelas memiliki "dua kemungkinan alasan untuk berubah", maka ya, itu melanggar SRP.
Pengontrol biasanya harus ringan dan memiliki tanggung jawab tunggal untuk memanipulasi domain / model sebagai respons terhadap beberapa peristiwa yang didorong GUI. Kita dapat menganggap masing-masing manipulasi ini pada dasarnya menggunakan case atau fitur.
Jika tombol baru ditambahkan pada GUI, pengontrol hanya harus mengubah jika tombol baru itu mewakili beberapa fitur baru (yaitu berlawanan dengan tombol yang sama yang ada pada layar 1 tetapi tidak ada di layar 2, dan kemudian ditambahkan ke layar 2). Perlu ada perubahan baru yang sesuai dalam model juga, untuk mendukung fungsi / fitur baru ini. Pengontrol masih memiliki tanggung jawab untuk memanipulasi domain / model dalam menanggapi beberapa peristiwa yang didorong GUI.
Jika logika bisnis dalam model berubah karena bug diperbaiki, dan itu memerlukan pengontrol untuk berubah, maka ini adalah kasus khusus (atau mungkin model melanggar prinsip buka-tutup). Jika logika bisnis dalam model berubah untuk mendukung beberapa fungsionalitas / fitur baru, maka itu tidak serta-merta berdampak pada pengontrol - hanya jika pengontrol perlu memaparkan fitur tersebut (yang hampir selalu merupakan kasusnya, jika tidak mengapa akan ditambahkan ke model domain jika tidak akan digunakan). Jadi dalam hal ini pengontrol harus dimodifikasi juga, untuk mendukung memanipulasi model domain dengan cara baru ini sebagai respons terhadap beberapa peristiwa yang didorong oleh GUI.
Jika controller harus berubah karena, katakanlah, layer persistence diubah dari flat file ke database, maka controller tersebut tentunya melanggar SRP. Jika controller selalu bekerja pada lapisan abstraksi yang sama, maka itu dapat membantu dalam mencapai SRP.
sumber
Pengontrol tidak melanggar SRP. Saat Anda menyatakan, tanggung jawabnya adalah memediasi antara model dan tampilan.
Yang sedang berkata, masalah dengan contoh Anda adalah bahwa Anda mengikat metode pengontrol untuk logika dalam pandangan, yaitu
controller.specificButtonPressed
. Memberi nama metode dengan cara ini mengikat controller ke GUI Anda, Anda telah gagal untuk hal-hal abstrak dengan benar. Pengontrol harus tentang melakukan tindakan spesifik, yaitucontroller.saveData
ataucontroller.retrieveEntry
. Menambahkan tombol baru di GUI tidak berarti menambahkan metode baru ke controller.Menekan tombol dalam tampilan, berarti melakukan sesuatu tetapi apa pun yang dapat dengan mudah dipicu dalam sejumlah cara lain atau bahkan tidak melalui tampilan.
Dari artikel Wikipedia tentang SRP
Pengontrol tidak peduli dengan apa yang ada dalam tampilan hanya bahwa ketika salah satu metodenya disebut itu memberikan data yang ditentukan untuk tampilan. Ia hanya perlu tahu tentang fungsionalitas model sejauh ia tahu bahwa ia perlu memanggil metode yang akan mereka miliki. Tidak tahu apa-apa lebih dari itu.
Mengetahui bahwa suatu objek memiliki metode yang tersedia untuk dipanggil tidak sama dengan mengetahui fungsinya.
sumber
specificButtonsPressed()
ini adalah karena saya membaca bahwa view tidak tahu apa-apa tentang fungsi tombol-tombolnya dan elemen GUI lainnya. Saya telah diajarkan bahwa ketika sebuah tombol ditekan, tampilan harus melapor ke controller, dan controller harus memutuskan 'apa artinya' (dan kemudian memanggil metode yang sesuai pada model). Membuat panggilan panggilancontroller.saveData()
berarti pandangan harus tahu tentang apa arti tombol ini ditekan, selain fakta bahwa itu ditekan.specificButtonPressed()
), memang controller tidak akan terlalu terikat pada GUI. Haruskah saya membuangspecificButtonPressed()
metode? Apakah keuntungan saya pikir memiliki metode ini masuk akal bagi Anda? Atau memilikibuttonPressed()
metode di controller tidak sepadan dengan masalahnya?specificButtonPressed()
metode di controller, adalah bahwa ia memisahkan View dari arti penekanan tombol sepenuhnya . Namun, kerugiannya adalah bahwa ia mengikat controller ke GUI dalam arti tertentu. Pendekatan mana yang lebih baik?foo
, atau dengan mudahfireZeMissiles
. Ia hanya akan tahu bahwa ia harus melapor ke fungsi tertentu. Tidak tahu apa fungsinya hanya yang akan memanggilnya. Pengontrol tidak peduli dengan bagaimana metodenya dipanggil hanya karena akan merespons dengan sopan santun ketika mereka melakukannya.Satu tanggung jawab pengendali adalah menjadi kontrak yang memediasi antara pandangan dan model. Tampilan hanya bertanggung jawab atas tampilan, model hanya bertanggung jawab atas logika bisnis. Tanggung jawab pengendali untuk menjembatani kedua tanggung jawab itu.
Itu semua baik dan bagus, tetapi untuk sedikit menjauhkan diri dari akademisi; sebuah pengontrol di MVC umumnya terdiri dari banyak metode aksi yang lebih kecil. Tindakan ini umumnya sesuai dengan hal-hal yang dapat dilakukan oleh sesuatu. Jika saya menjual produk, saya mungkin akan memiliki ProductController. Pengontrol itu akan memiliki tindakan seperti GetReviews, ShowSpecs, AddToCart dll ...
Tampilan memiliki SRP untuk menampilkan UI, dan bagian dari UI itu termasuk tombol yang mengatakan AddToCart.
Pengendali memiliki SRP untuk mengetahui semua Tampilan dan Model yang terlibat dalam proses.
Kontroler AddToCart pengendali memiliki SRP khusus untuk mengetahui semua orang yang perlu dilibatkan saat item ditambahkan ke troli.
Model Produk memiliki SRP pemodelan logika produk, dan Model ShoppingCart memiliki SRP pemodelan bagaimana item disimpan untuk checkout berikutnya. Model Pengguna memiliki SRP pemodelan pengguna yang menambahkan barang ke keranjang mereka.
Anda dapat dan harus menggunakan kembali model untuk menyelesaikan bisnis Anda dan model-model itu perlu digabungkan pada beberapa titik dalam kode Anda. Pengontrol mengontrol setiap cara unik yang terjadi kopling.
sumber
Pengendali sebenarnya hanya memiliki satu tanggung jawab: mengubah status aplikasi berdasarkan input pengguna.
source: wikipedia
Jika sebaliknya Anda memiliki "pengendali" gaya Rails (yang menyulap instance rekaman aktif dan templat bisu) , maka tentu saja keluar melanggar SRP.
Kemudian lagi, aplikasi Rails-style sebenarnya bukan MVC.
sumber