Kapan kelas atau modul berada di Majelis / DLL yang terpisah?

22

Apakah ada pedoman untuk memutuskan kapan suatu kelas harus berada di assembly / DLL sendiri? Saya sering melihat dua aliran pemikiran:

1) Setiap "pengelompokan" kelas termasuk dalam DLL sendiri mis. Repositori, Layanan, DTO, Infrastruktur, dll.

2) Semuanya harus dalam DLL tunggal tetapi dipisahkan melalui ruang nama / folder misalnya memiliki "Core" DLL dengan ruang nama tambahan misalnya Core.Repositori, Core.Services, Core.DTO, dll.

Di tempat kerja kami hanya menyatukan semuanya dalam satu Majelis yang disebut "Bisnis". Ada beberapa folder tetapi tidak ada pemisahan nyata - objek bisnis (dengan logika, beberapa di antaranya bahkan tidak boleh kelas) disatukan dalam folder "BusinessObjects" tanpa perawatan. Hal-hal yang digunakan di lebih dari satu kelas ada di folder "Core". Utilitas ada di folder "Utilitas", infrastruktur akses data adalah folder "Data" - Anda dapat idenya.

Untuk modul baru yang sedang saya kerjakan, saya ingin / perlu memiliki lapisan akses data terpisah (pikirkan implementasi Repositori yang belum sempurna) tetapi saya tidak ingin hanya membuangnya di bawah folder "BusinessObjects" dengan 160 folder lainnya (!) kelas di sana. Pada saat yang sama saya khawatir tentang membuat Perpustakaan Kelas baru karena semua orang terbiasa memasukkan kelas di Perpustakaan tunggal; folder / namespace bisa berfungsi.

Wayne Molina
sumber

Jawaban:

12

Saya merasa lebih baik memiliki lebih banyak proyek (yaitu rakitan) dengan kelas yang dibagi berdasarkan kategori di setiap proyek daripada satu proyek dengan semua kelas ini di ruang nama yang terpisah. Anda harus bertujuan agar proyek Anda dapat digunakan kembali dan mewakili lapisan yang berbeda dalam suatu aplikasi. Anda kemudian dapat menggunakan kembali proyek-proyek ini secara layak di aplikasi masa depan tanpa harus menyertakan sejumlah kelas yang tidak perlu.

Misalnya, berdasarkan apa yang telah Anda sebutkan, saya pasti akan memiliki proyek berikut:

  • Inti
  • Data
  • Domain (atau BusinessObjects)
  • Jasa
  • Utilitas (atau Pembantu)
Bernard
sumber
2
Menyesal saya tidak bisa memilih jawaban. Inilah yang disarankan di perusahaan kami. Akibatnya memiliki 6 atau lebih proyek misalnya untuk situs web ukuran sedang, Anda tidak dapat mempertahankan hierarki direktori berbasis fitur, dll. Sebagai hasilnya, Anda berakhir dengan enam proyek dengan masing-masing proyek menjadi sangat tidak mungkin untuk menavigasi tumpukan file. Biasanya orang yang memberi saran ini tidak pernah mencoba struktur berdasarkan fitur proyek pada proyek yang relatif besar (maaf untuk penilaian langsung tetapi berurusan dengan hasil dari overweening seperti itu adalah rasa sakit yang nyata). Jawaban jammycakes menyarankan pendekatan yang benar.
alehro
Membagi kelas berdasarkan kategori adalah apa yang menyebabkan kekacauan dalam proyek-proyek besar. Membaginya berdasarkan fitur / aspek. Maka namespaces hanya akan mencerminkan divisi ini. Dan seluruh struktur akan mencerminkan leksikon dari spesifikasi. Membagi kelas berdasarkan kategori seperti menambahkan singkatan tipe ke nama variabel - biasanya bau.
alehro
Mudah untuk menyalahgunakan kedua solusi yang diusulkan (yaitu terlalu banyak proyek atau terlalu sedikit). Menemukan keseimbangan yang baik di mana usabilitas dan kopling rendah diingat harus mengarah pada sesuatu yang lebih dapat diuji dan dipelihara.
Bernard
16

"Paman Bob" Martin dari Clean Code, ketenaran SOLID Principles telah menjabarkan tiga prinsip di sini :

  • Prinsip Ekuivalensi Penggunaan Kembali Rilis: Butiran reuse adalah butiran rilis.
  • Prinsip Penutupan Umum: Kelas-kelas yang berubah bersama dikemas bersama.
  • Prinsip Penggunaan Kembali Bersama: Kelas yang digunakan bersama dikemas bersama.

Aturan umum adalah Anda harus menjaga jumlah proyek dalam solusi Anda serendah mungkin. Hanya pisahkan mereka jika Anda perlu melakukannya untuk menerapkan satu atau lebih cerita pengguna tertentu, atau jika memiliki satu perakitan menyebabkan masalah kinerja yang terukur (biasanya setelah mereka mencapai beberapa megabyte ukuran).

jammycakes
sumber
2
+1 prinsip-prinsip ini adalah pedoman yang baik. Memisahkan kelas menjadi rakitan yang berbeda memperkenalkan pertimbangan desain tambahan (misalnya versi mana dari setiap rakitan yang diizinkan untuk bekerja bersama) meningkatkan basis kode keseluruhan sehingga meningkatkan biaya pemeliharaan.
Ben
1
Namun, di samping prinsip-prinsip ini saya akan menambahkan bahwa sering kali merupakan ide bagus untuk mengemas kode yang kemungkinan akan diganti atau ditukar dalam perakitan terpisah. Kode ini akan mendapat manfaat dari pertimbangan tambahan yang diperlukan untuk menggabungkan rakitan terpisah dan memisahkannya akan membuatnya lebih mudah untuk menguji dan membandingkan versi yang berbeda.
Ben
4
Ya, tetapi pastikan bahwa ada persyaratan asli untuk diganti atau ditukar. Misalnya, kerangka kerja dan perpustakaan pihak ketiga - paket NuGet dan sejenisnya - biasanya perlu mendukung beberapa wadah IOC dan beberapa kerangka kerja logging. Untuk kode pengguna lahan, di sisi lain, abstraksi seperti itu biasanya murni spekulatif, tidak perlu dan obstruktif, dan tidak pernah berhasil pada akhirnya pada kesempatan langka ketika mereka benar-benar diperlukan.
jammycakes
"Hanya pisahkan mereka jika Anda perlu melakukannya untuk menerapkan satu atau lebih cerita pengguna tertentu, atau jika memiliki satu perakitan menyebabkan masalah kinerja yang terukur (biasanya setelah mereka mencapai beberapa megabyte ukuran)." -
Benar
1
Maaf, tapi sebenarnya apa yang "benar-benar acak dan tidak didasarkan pada kenyataan" tentang hal itu? Saya memposting jawaban ini setelah bertahun-tahun mengerjakan solusi yang dipecah menjadi lebih banyak proyek daripada yang diperlukan tanpa alasan apa pun selain Itulah Cara Anda Seharusnya Melakukannya. Hasil? Waktu kompilasi es dan banyak neraka ketergantungan (terutama di hari-hari sebelum NuGet). Membagi hal-hal menjadi majelis terpisah memiliki biaya, dan jika tidak ada manfaat untuk mengimbangi biaya itu, maka itu hanya kasus mencuri dari bisnis.
jammycakes
4

Beberapa prinsip panduan lainnya yang bekerja dengan saya:

  • Apakah Anda pikir Anda akan menggunakan kembali kode ini di proyek lain? Untuk satu grup aplikasi web terkait, kami memiliki satu modul terkait akun pengguna yang digunakan semua aplikasi, karena mereka semua menggunakan model yang sama untuk akun dan login pengguna. Saya telah melakukan hal yang sama dengan perpustakaan geometri dan matematika dan menggunakannya kembali dalam berbagai aplikasi, hanya dengan menyertakan DLL.

  • Apakah Anda ingin dapat memodifikasi / menggunakan kode ini tanpa menggunakan kembali / mengkompilasi ulang seluruh proyek? Terkadang berguna untuk membangun kembali modul, menyebarkan, dan memulai ulang aplikasi web.

Kedengarannya seperti dalam kasus Anda Repositori dasar dan generik dapat berguna lagi di masa depan, mungkin layak untuk memisahkannya menjadi DLL baru jika Anda bisa.

FrustratedWithFormsDesigner
sumber
Saya pikir poin kedua Anda benar-benar masuk akal. Membagi menjadi modul harus membantu pengembangan / pengujian dan waktu kompilasi.
WM