Dalam MVC itu dianggap praktik yang baik untuk memiliki fungsi pribadi, non-aksi, di kelas controller?

10

Kadang-kadang fungsi aksi di kelas pengontrol bisa menjadi besar dan tidak menyenangkan, dengan banyak-banyak baris kode untuk sekadar mengontrol aliran data dari Model ke Tampilan. Pada titik tertentu fungsi-fungsi besar ini benar-benar kehilangan jejak prinsip-prinsip dasar kode yang baik, yaitu hanya melakukan satu hal, menjadi kecil, dapat dibaca dan dikelola dll.

Apakah akan dianggap praktik yang baik untuk memecah fungsi aksi besar ini menjadi fungsi pribadi yang lebih kecil di kelas controller atau haruskah kebutuhan optimasi seperti itu berarti kita harus menambahkannya dalam model?

Saya akan memilih untuk memiliki fungsi yang lebih kecil sebagai pribadi di controller sehingga mereka relatif terhadap tindakan, tetapi saya telah mendengar argumen bahwa controller sebaiknya sederhana sementara modelnya bisa menjadi besar dan gumpal; dan hanya bertanya-tanya mana yang akan menjadi metode yang paling disukai.

David 'the botak jahe'
sumber

Jawaban:

16

Mungkin bukan analogi terbaik tetapi, pikirkan pengontrol dengan cara yang sama seperti Anda berpikir tentang jaring laba-laba. Tugas utamanya adalah menangkap lalat (permintaan) untuk dicerna laba-laba (lapisan dasar). Web dapat menangkap dan menahan lalat (model) yang lebih kecil atau lebih besar. Peran web laba-laba bukanlah untuk mencerna mangsa, meskipun dapat digunakan untuk tujuan ini. Semakin tipis dan bersih jaring, semakin mudah laba-laba mencari nafkah.

Anda dapat menerapkan logika yang agak sama untuk aplikasi MVC Anda. Fungsi-fungsi besar dan jahat yang Anda gambarkan adalah perilaku yang paling mungkin dari model dan mereka harus termasuk dalam model (perhatikan bahwa model tidak hanya objek yang ditampilkan dalam tampilan). Jika perilaku model berubah itu model yang harus diubah dan bukan pengontrol yang menanganinya.

Juga, menjaga mereka sebagai metode pribadi di controller hanya akan mengacaukannya dan membuatnya sulit untuk dipelihara. Ini juga membuka jalan bagi kebiasaan buruk, karena orang lain yang terlibat dalam pembangunan akan tergoda untuk melakukan hal yang sama, karena mereka pernah melihatnya melakukannya di proyek sebelumnya.

devnull
sumber
+1 untuk analogi kreatif. :) Anda membuat poin yang menarik. Terutama pada pembentukan kebiasaan buruk. Terima kasih.
David 'the botak jahe'
8

Jawaban terbaik yang bisa saya berikan adalah mengutip dari buku hebat karya Robert Martin, "Clean Code" yang sangat saya rekomendasikan kepada siapa pun yang tertarik pada subjek:

Aturan fungsi pertama adalah bahwa mereka harus kecil. Aturan kedua adalah bahwa mereka harus lebih kecil dari itu.

Tidak bisa mengatakannya lebih baik. Kutipan hebat lainnya dari buku yang sama berlaku:

Fungsi harus melakukan satu hal. Mereka harus melakukannya dengan baik. Mereka seharusnya melakukannya saja.

Ketika membagi kode Anda menjadi lebih banyak fungsi, Anda dipaksa untuk memberikan fungsi-fungsi itu nama yang berarti yang dapat sangat meningkatkan keterbacaan kode Anda. Tak perlu dikatakan, semua fungsi yang tidak dimaksudkan untuk digunakan di luar kelas, harus pribadi, sehingga Anda dapat dengan mudah menggunakan kembali kode Anda melalui warisan.

Jika pengontrol Anda sekarang memiliki terlalu banyak fungsi, itu adalah pertanda bahwa ia mungkin melakukan terlalu banyak. Kemudian Anda dapat membaginya menjadi beberapa bagian independen atau mencoba untuk memindahkan beberapa fungsi ke model seperti yang disebutkan dalam jawaban lainnya. Juga jika Anda mengikuti rasa MVC non-klasik, di mana Views diizinkan untuk memiliki beberapa logika, Anda dapat menempatkan beberapa fungsi Anda di sana kapan pun cocok.

Dmitri Zaitsev
sumber
1
Saya tidak berpikir bahwa menempatkan logika bisnis ke pandangan adalah "MVC non-klasik", itu hanya "MVC buruk". Jelas Anda membutuhkan struktur kontrol dasar dalam tampilan, tetapi mereka harus diselaraskan dengan masalah pengguna / UI, bukan masalah domain / bisnis. Fungsi aktual dalam tampilan cukup mengerikan.
Aaronaught
1
@Aronaught Saya tidak jelas dengan "beberapa logika", apa yang ada dalam pikiran saya adalah perpustakaan Backbone.js, di mana Anda meletakkan acara pengguna dan fungsi untuk menanganinya dalam pandangan Anda. Dalam MVC klasik ini adalah tugas pengontrol. Namun ini tidak praktis karena Anda harus menyesuaikan Tampilan dan Pengontrol setiap kali perubahan UI Anda. Dengan meletakkan fungsi UI handler Anda di View, Anda hanya perlu menyesuaikan View. Itu hanya pandangan subjektif saya - apakah saya melewatkan sesuatu?
Dmitri Zaitsev
1
Hanya karena sesuatu disampaikan pada sisi klien tidak berarti bahwa itu secara logis bagian dari pandangan. Penjilidan data dalam tampilan, tentu saja, tetapi Backbone sendiri merupakan kerangka kerja MV * (jenis MVC, jenis MVP, tidak cukup baik) dan skrip sisi klien Anda harus diatur sesuai dengan itu; jika tidak, Anda hanya meretas.
Aaronaught
0

Dalam MVC saya mencoba dan memastikan bahwa pengontrol saya setipis mungkin dan juga bahwa model saya sebodoh mungkin.

Logika dan fungsi pembantu yang diperlukan dimasukkan ke dalam kelas pembantu yang berdiri sendiri secara terpisah. Itu membuat pengujian saya jauh lebih mudah juga (Anda menguji .. benar ??: D) Menguji pengontrol sangat sulit, setiap kali Anda mencoba dan membuat instance pengontrol untuk menguji Anda harus berpikir tentang Konteks HTTP dan memalsukan http ini dan itu, dan itu adalah rasa sakit, tetapi rasa sakit itu sengaja. Anda memerlukan semua itu karena pengontrol terkait erat dengan HTTP dan web. Ini adalah titik masuk ke aplikasi web Anda.

Logika dan fungsi pembantu tidak ada hubungannya dengan web. Mereka sepenuhnya agnostik lingkungan (atau seharusnya). Itu saja seharusnya memberitahu Anda bahwa mereka tidak termasuk bersama di tempat yang sama. Plus, jika Anda mengikat semua logika aplikasi Anda begitu dekat ke web, atau implementasi web tertentu, Anda tidak akan pernah bisa membawanya.

Kami mengembangkan situs MVC kami dengan semua entitas basis data kami (bukan model mvc kami, entitas db kami yang sebenarnya), penyimpanan kami, kelas penolong kami dan logika kami di tempat terpisah, dll. Kami hanya memiliki setiap situs web saja, tetapi kami tetap melakukannya seperti ini.

Beberapa bulan yang lalu kami diminta untuk membuat beberapa aplikasi desktop yang terkait dengan beberapa sistem pinggiran kami. Ini mudah dilakukan karena semua kode kami yang diuji dapat dengan mudah digunakan kembali. Jika kita memasukkan kode kita ke proyek web kita, atau memasukkan pengontrol kita, kita tidak akan pernah bisa melakukan ini.

angkasawan
sumber
2
Model dalam MVC adalah satu-satunya lapisan yang tidak seharusnya bodoh. Jika kecerdasan tidak ada dalam model, dan mereka tidak ada di controller, lalu di mana mereka ... dalam tampilan? Pengontrol juga seharusnya tidak sulit untuk diuji; kemampuan untuk menggunakan DI dan memalsukan / mengolok-olok untuk memfasilitasi pengujian unit adalah salah satu daya tarik MVC atas kerangka kerja lain. Sebagian besar tes pengontrol saya berada di bawah 5 baris.
Aaronaught
saya akan menggunakan "helper" kelas dengan logika daripada merasuki model dengan logika. logika apa yang akan Anda masukkan ke dalam model? apakah ia tahu cara memuat dirinya sendiri dan menyimpannya sendiri? Saya setuju memalsukan / mematikan itu mudah, tetapi itu bukan alasan untuk mulai menggemukkan pengendali Anda.
angkasawan
Saya merasa bahwa jawaban ini berarti baik tetapi kata-katanya salah .. atau, mungkin terminologi yang berbeda.
Simon Whitehead
3
Kelas "Helper" bukan elemen arsitektur. Mereka adalah bagian dari M, V, atau C. Jika Anda tidak yakin yang mana, maka para pembantu itu tidak memiliki kohesi . Kata "helper" juga berada di peringkat atas dengan "handle", "do", "perform", dan Manager yang ditakuti .
Aaronaught
@SimonWhitehead: Sebagian besar jawaban berarti baik tetapi banyak yang salah. Sayangnya, yang ini mempromosikan kesalahpahaman tentang makna "Model" atau merekomendasikan untuk menempatkan logika bisnis penting di luarnya. Saya merasa ragu untuk memelihara situs MVC dengan miliaran "pembantu" - mereka mengerikan.
Aaronaught
-2

Selain Dmitri Zaitsev dan angkasawan jawaban yang bagus saya tidak tahu apakah yang berikut ini juga berlaku untuk PHP: Anda harus mencoba menghindari metode pribadi karena kurangnya kemungkinan tes otomatis.

Ya, Anda dapat menggunakan metaprogramming atau injeksi dependensi untuk menguji metode pribadi juga, tetapi Anda tidak boleh melakukannya karena memiliki dampak besar pada keterbacaan kode Anda.

Selalu ingat prinsip CIUMAN: Tetap sederhana, bodoh.

cHaOs667
sumber
5
Itu bukan alasan yang baik untuk menghindari metode pribadi, dan juga tidak ada hubungannya dengan arsitektur MVC. Anda tidak mencoba menguji metode pribadi, mereka harus dicakup oleh tes pada metode publik . Jika Anda tidak dapat membahasnya, maka itu pertanda bahwa kelas Anda terlalu kompleks dan perlu di refactored; itu tidak berarti Anda tidak boleh memiliki metode pribadi atau (saya sungguh-sungguh berharap ini bukan yang Anda maksudkan dengan sebenarnya) bahwa itu seharusnya menjadi publik.
Aaronaught