Haruskah saya menggunakan kelas statis untuk metode yang akan melakukan tugas umum dan akan dipanggil melalui aplikasi saya?

8

Saya telah menghabiskan beberapa jam terakhir membaca tentang penggunaan statickelas 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 MVCmenggunakan 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);
    }
}
Matius Verstraete
sumber
Tidak ada mandat untuk menghindari kelas statis. Gunakan saat berguna untuk melakukannya. Ada alasan bagus mengapa desainer bahasa memasukkannya.
Robert Harvey
5
Mengapa Anda tidak memasukkan metode ini sebagai metode statis di kelas terkait, alih-alih menempatkan semuanya ke dalam kelas pembantu? Sebagai contoh, metode pertama Anda bisa menjadi metode statis di PrincipalContextkelas, dan disebut seperti: PrincipalContext.Get(ouName). Ini pada dasarnya metode Pabrik.
Robert Harvey
@RobertHarvey Saya rasa saya tidak mengikuti. Kelas ini ada di BLL saya dan dipanggil dari banyak kelas lain (pengontrol) di WebUI dan juga Aplikasi Konsol C # yang melakukan perawatan malam hari dan untuk menghindari pengodean ulang sepanjang waktu, saya hanya menulisnya di kelas pembantu.
Matthew Verstraete
5
Pengembangan perangkat lunak selalu merupakan serangkaian pengorbanan. Teknik mana yang Anda pilih untuk digunakan tergantung pada set pengorbanan yang ingin Anda terapkan.
Robert Harvey
4
@RobertHarvey: PrincipalContext dan UserPrincipal adalah kelas perpustakaan,
kevin cline

Jawaban:

3

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!

sara
sumber
2

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.

Fran
sumber
Tidak yakin apa yang Anda maksud dengan "menyembunyikan ketergantungan eksternal ke Active Directory". Saya membuat bacaan dari AD dan kelas ini dibangun untuk mengurangi pengkodean yang diperlukan untuk membuat koneksi dan mendapatkan data dasar.
Matthew Verstraete
itu yang aku maksud. lihat jawaban Kai untuk penjelasan yang lebih lengkap. Tetapi yang Anda lakukan adalah tidak, buat kode Anda bergantung pada semua dependensi kode panggilan Anda.
Fran
1

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.

Steve Chamaillard
sumber
Ini akan sangat tergantung pada jenis pabrik. Sebuah sederhana 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.
sara
Terima kasih atas komentar Anda. Itu tidak terdengar seperti pabrik yang Anda bicarakan sangat abstrak pada akhirnya, sepertinya itu adalah konsep konkret yang perlu dipakai (terutama karena Anda mengatakan Anda membutuhkan beberapa pabrik yang berbeda). Dan lagi, tidak ada yang ditetapkan dalam batu dan hanya saran yang dapat diberikan tentang subjek ini.
Steve Chamaillard
1
Ada banyak entitas yang merupakan "Pabrikasi Murni", yang tidak dengan cara apa pun atau bentuk menerjemahkan ke domain, misalnya UserDao. Ini bukan indikasi apakah harus statis atau tidak. Itu harus statis jika unit pekerjaan itu, tidak saling bergantung, dan harus diperpanjang, misalnya kelas matematika.
Chris Wohlert
@ChrisWohlert komentar yang sangat menarik (diacungi jempol), tetapi bukankah itu hanya bergantung pada konteksnya? Saya merasa seperti aplikasi tentang matematika ingin kelas Matematika menjadi salah satu kelas inti dan instantiable. Apakah UserDao semacam repositori antara lapisan Pengguna dan DB? Jika demikian, mengapa Anda ingin membuat instantiate? Anda masih bisa menyuntikkannya meskipun Anda tidak akan pernah membuat objek untuk ini, karena itu tidak "ada", bagaimana menurut Anda?
Steve Chamaillard
1
@SteveChamaillard Anda memiliki asumsi bahwa masuk akal untuk hanya instantiate objek "nyata". Itu mengingatkan saya analogi OOP 101 ini di mana Anda memiliki kelas abstrak "Buah" dan "Apple" yang diwariskan - di mana objek OOP mewakili objek dunia nyata. Tetapi tidak perlu membatasi diri Anda seperti ini. OOP adalah alat, jadi orang menggunakan benda untuk "fabrikasi murni" bahkan yang membuat hidup mereka lebih mudah dan saya tidak melihat ada yang salah dengan itu ...
qbd
1

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, *Managerdan *Doerkelas 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.

Robert Jørgensgaard Engdahl
sumber
0

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.

Robbie Dee
sumber
Kelas yang sama melakukan hal yang sama dapat dirancang menjadi statis dan non-statis. Selalu ada pilihan desain yang harus dibuat.
sara
Mungkin ada pilihan desain tetapi implementasinya agak sewenang-wenang. Tidak ada yang memaksa Anda untuk memberi label metode atau kelas statis - bahkan dengan kurangnya variabel contoh meskipun beberapa alat seperti ReSharper mengambil ini ...
Robbie Dee
Tetapi kapan saya harus membuat semua metode / anggota statis atau tidak? Itu pertanyaannya. Kapan menggunakan statis dan kapan tidak.
Matthew Verstraete
Jika tidak ada variabel atau metode anggota yang bergantung pada turunan kelas - Anda memiliki kelas statis yang bonafid. Menurut sifatnya, ini cenderung menjadi hal-hal seperti kelas pembantu atau utilitas dan sejenisnya.
Robbie Dee
0

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
0

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.

Laiv
sumber