Saya telah menghabiskan beberapa jam terakhir membaca tentang penggunaan static
kelas dan mencoba mencari tahu apakah saya harus menggunakannya atau tidak tetapi masih belum sampai pada kesimpulan apa pun. Tampaknya argumennya bisa berjalan baik. Dalam aplikasi saya, saya telah membuat apa yang saya sebut "kelas pembantu" yang berisi metode yang akan melakukan tugas yang sangat umum bagi saya dan akan dipanggil melalui aplikasi saya ( ASP.Net MVC
menggunakan Aplikasi Web C#
) dan pertanyaan sederhananya adalah, haruskah mereka benar-benar statis atau tidak ?
Ini adalah contoh salah satu pembantu saya.
public static class ActiveDirectoryHelper
{
public static PrincipalContext GetPrincipalContext(string ouName)
{
var fullOUName = string.Concat("OU=", ouName,",DC=");
return new PrincipalContext(ContextType.Domain, "", fullOUName, ConfigurationManager.AppSettings["ServiceAccountUser"], ConfigurationManager.AppSettings["ServiceAccountPassword"]);
}
public static PrincipalSearcher GetAllUsersInOU(string ouName)
{
var principalContext = GetPrincipalContext(ouName);
var userPrincipal = new UserPrincipal(principalContext);
return new PrincipalSearcher(userPrincipal);
}
public static UserPrincipal GetUserPrincipal(string userName, string ouName)
{
var principalContext = GetPrincipalContext(ouName);
return UserPrincipal.FindByIdentity(principalContext, userName);
}
}
c#
object-oriented-design
asp.net-mvc
Matius Verstraete
sumber
sumber
PrincipalContext
kelas, dan disebut seperti:PrincipalContext.Get(ouName)
. Ini pada dasarnya metode Pabrik.Jawaban:
Saya pikir kelas statis bagus dalam banyak kasus. Saya hanya bisa mengatakan "gunakan ketika itu berguna" tapi itu tidak terlalu membantu.
Aturan praktis saya adalah (seperti biasa): Apakah saya menyembunyikan dependensi? Jika Anda merasa seperti "kelas pembantu" berguna (walaupun waspadalah terhadap kohesi rendah) maka dengan segala cara, silakan. Pastikan metode Anda tidak mengakses kondisi global. Metode statis murni itu indah. Metode statis yang bergantung pada beberapa global atau yang membuka koneksi DB atau membaca dari disk / beberapa file konfigurasi sedang mengalami bom waktu.
Mereka membuat pengujian aplikasi sangat sulit (satu-satunya cara melakukannya adalah menjalankan seluruh sistem secara manual, atau dengan uji sistem penuh otomatis yang rapuh, Anda tidak akan mendapatkan rincian). Mereka juga membuat tidak mungkin untuk menukar implementasi.
Ingat saja prinsip inversi ketergantungan dan prinsip buka / tutup! Pastikan kelas Anda pluggable. Pastikan mereka tidak mengeluarkan barang dari udara. Jika Anda melakukannya, silakan dan buat metode statis sebanyak yang Anda inginkan!
sumber
Sepertinya Anda menyembunyikan ketergantungan eksternal ke Active Directory menggunakan kelas statis ini. Satu masalah di sini adalah bahwa jika Anda mencoba untuk menguji unit kelas yang memanggil metode ini, Anda tidak dapat memalsukan panggilan statis. Jadi Anda segera menghambat testabilitas kode Anda. Saya akan memperbaiki ini ke antarmuka, sesuatu seperti IProvideActiveDirectoryInformation, dan kelas beton, ActiveDirectoryInformationProvider. Kemudian lewati antarmuka di konstruktor controller Anda. Ini akan memungkinkan Anda untuk memasang kelas beton dengan wadah DI. Ini juga akan memungkinkan Anda untuk memalsukan ActiveDirectoryInformationProvider dan mengembalikan apa pun yang Anda inginkan untuk metode antarmuka.
Saya juga melihat tidak melewatkan kembali hal-hal seperti objek PrincipalSearcher di antarmuka. Jika metode Anda adalah GetAllUsersInOU () saya akan mengharapkan daftar pengguna atau nama pengguna.
sumber
Kelas harus statis jika hanya ada sebagai konsep abstrak di aplikasi Anda.
Misalnya, Anda membuat tiruan dari Twitter. Anda mungkin memiliki 2 jenis tweet, tweet pengguna, dan iklan. Keduanya memiliki perilaku yang sama tetapi berbeda. Jadi, Anda ingin menggunakan polimorfisme dan pabrik untuk membuat satu atau lainnya.
Kedua kelas tweet itu harus kelas konkret, karena mereka adalah entitas nyata. Domain Anda ditentukan oleh kelas-kelas ini.
Pabrik harus statis karena hanya ada pada tingkat abstrak untuk membuat aplikasi Anda lebih baik dirancang dan untuk membantu Anda menggunakan kembali kode yang akan membuat jenis tweet. Domain Anda tidak ditentukan pada level apa pun oleh pabrik ini.
Jadi, jika Anda tidak berpikir bahwa suatu kelas harus dipakai tetapi tidak perlu diperluas untuk digunakan, itu mungkin pertanda baik bahwa itu harus statis.
sumber
static A BuildA() { return new A(); }
yakin, itu bagus. tetapi jika Anda memerlukan sesuatu yang lebih kompleks, seperti ketika A memiliki dependensi yang perlu disuntikkan atau ketika bagian yang berbeda dari sistem Anda membutuhkan instance pabrik yang berbeda (pola pabrik abstrak) maka metode statis tidak akan memotongnya.Salah satu hal yang disarankan dalam Pemrograman Berorientasi Objek adalah Buruk (judulnya adalah untuk menarik perhatian Anda, dan isinya diperdebatkan tetapi menghibur) adalah bahwa
*Handler
,*Manager
dan*Doer
kelas secara umum adalah bau kode yang menunjukkan seseorang yang mencoba untuk memaksakan orientasi objek ke suatu masalah yang lebih cocok untuk implementasi prosedural.Dalam C # Anda dapat menggunakan kelas statis sebagai ruang nama modul untuk prosedur dan lebih baik beri nama seperti itu. Saya pikir ini adalah bagaimana melakukannya, tetapi tidak dalam kasus khusus Anda.
Aplikasi implementasi khusus Anda akan memiliki dependensi perilaku negara global (katakanlah izin pengguna tertentu), dan karenanya harus merupakan ketergantungan yang disuntikkan sehingga kode yang menggunakan ini dapat diuji unit secara terpisah.
sumber
Saya mungkin kehilangan sesuatu tetapi dalam pikiran saya jawabannya bermuara pada metode dan variabel anggota.
Jika ini semua statis, kelas itu sendiri dapat (dan seharusnya) dibuat statis. Jika tidak, maka itu bukan kelas statis.
NB tidak ada yang memaksa kelas menjadi statis bahkan jika metode dan variabel semuanya statis.
sumber
Pertimbangkan bahasa pemrograman yang Anda gunakan (C #) sebagai seperangkat alat.
Tidak ada buku aturan, tidak ada "harus" atau "tidak boleh".
Lihatlah pekerjaan sedang dilakukan, dan pilih alat terbaik untuk pekerjaan itu.
Jika Anda membutuhkan kumpulan metode yang tersedia secara global, sama untuk semua utas, maka kelas statis adalah alat yang baik. Jika Anda ingin menyimpan data dalam kelas (berbeda untuk setiap utas) maka mereka mungkin tidak.
sumber
Tidak ada yang salah di kelas Pembantu Anda. Saya harus yakin bahwa saya menggunakan Utils , Helpers atau Holders semacam ini untuk membuat sumber daya / logika tertentu dapat diakses dari tempat yang berbeda.
Namun seorang arsitek dari perusahaan saya mengatakan berulang kali kepada saya bahwa kelas-kelas ini sering mengumpulkan kode yang saya tidak tahu harus taruh di mana. Dia juga tidak suka karena Anda bisa membawa komponen dari lapisan di mana lapisan atas / bawah tidak boleh memiliki akses dan mereka melakukan tugas dari tanggung jawabnya. Ini juga membawa beberapa masalah saat ujian.
Saya tidak keberatan. Saya menggunakan'em dan saya menggunakan'em sebaik yang saya pikir harus digunakan. Dan itu bekerja dengan baik. Jadi jangan khawatir.
Memang benar bahwa pada saat pengujian unit Anda akan mengalami kesulitan mengejeknya. Tetapi akan memakan waktu sedikit lebih lama untuk melakukannya. Ada lib yang melewati masalah ini.
Pendekatan lain dapat mencegah Anda dari kekurangan semacam ini (saat pengujian). Misalnya, pola Singleton. Menyuntikkan instance sebagai ketergantungan komponen dan mengubah metode menjadi metode instance.
Ngomong-ngomong, sejauh ini saya melihat, solusi Anda terlihat baik bagi saya.
sumber