Apakah singleton abadi / stateless jahat?

12

Akhir-akhir ini ada semacam revolusi melawan lajang, tetapi apakah ada yang salah dengan mereka jika mereka tidak memiliki kewarganegaraan?

Saya tahu pembicaraan berlebihan dan semua ... ini berlaku untuk semuanya bukan hanya lajang.

m3th0dman
sumber
1
Tidak. Lajang pada prinsipnya tidak buruk, mereka hanya terlalu banyak digunakan.
Bart van Ingen Schenau
3
apa yang kamu maksud dengan belakangan ini?
Manoj R
5
@ Joachim Sauer: Mengapa Anda perlu mengganti; jika stateless, Anda dapat mengujinya secara langsung.
m3th0dman
1
Jika Anda memiliki singleton stateless maka pada dasarnya Anda memiliki kelas utilitas statis, yang memiliki kecenderungan tumbuh menjadi anti-pola Kelas Dewa. Anda biasanya dapat menggunakan metode statis sebagai gantinya dalam konteks yang digunakan (atau bahkan lebih baik: gunakan metode ekstensi dalam C #).
Spoike
1
Kemungkinan duplikat Singleton tanpa status apa pun
Caleth

Jawaban:

12
  > Are immutable/stateless singletons bad?
  • Tidak jika mereka tidak bergantung pada Sistem eksternal lainnya.
    • Contoh: Stringutility yang lolos dari html di dalam string.
    • Alasan: Di unittests tidak perlu mengganti ini dengan mock / simulator.
  • Ya jika singleton abadi / stateless Anda bergantung pada Sistem / Layanan eksternal lainnya dan jika Anda ingin melakukan unittesting (pengujian dalam Isolasi)
    • Contoh: Layanan yang bergantung pada Layanan Pajak-Kalkulator-Web Eksternal.
    • Alasan: Untuk melakukan unittests dengan Layanan ini (dalam isolasi) Anda perlu mensimulasikan / mengejek Sistem / Layanan eksternal.

Untuk lebih jelasnya lihat arsitektur bawang


  • Singleton-s dapat membuat unit-testing (dalam isolasi) lebih sulit / tidak mungkin dan
  • ketergantungan tersembunyi / kopling dapat dilihat sebagai masalah seperti yang dijelaskan oleh @yBee

Saya tidak melihat alasan lain mengapa tidak menggunakan lajang.

k3b
sumber
Anda masih harus mengejek layanan web eksternal jika Anda ingin menguji kelas Anda, bahkan jika itu bukan singleton (stateless).
m3th0dman
@ m3th0dman saya setuju
k3b
10

Itu selalu tergantung pada penggunaan. Saya pikir revolusi berasal dari fakta, bahwa setiap programmer belajar pola ini sebagai yang pola berorientasi objek. Kebanyakan lupa untuk memikirkan di mana itu masuk akal dan di mana tidak.
Ini, tentu saja, berlaku untuk setiap pola. Hanya dengan menggunakan pola Anda tidak membuat kode yang baik atau perangkat lunak yang baik.

Jika Anda memiliki singleton stateless, mengapa tidak menggunakan kelas yang hanya menawarkan metode statis (atau menggunakan kelas statis)?

Berikut beberapa postingan mengenai variabel global dan lajang secara umum.

Saya tidak akan seketat penulisnya, tetapi ia menunjukkan bahwa untuk sebagian besar kasus di mana Anda pikir Anda membutuhkan seorang wanita lajang, Anda tidak benar-benar membutuhkannya.

StampedeXV
sumber
1
Mengapa tidak menggunakan kelas dengan metode statis? Warisan misalnya ...
m3th0dman
3
@ m3th0dman: Tidak terdengar seperti tempat yang baik untuk warisan.
Billy ONeal
@BillyONeal Anda dapat mengatakan bahwa ada sesuatu yang baik atau buruk untuk warisan jika Anda tahu model domain, apa yang akan dimodelkan seperti itu ...
m3th0dman
2
@ m3th0dman: Erm, no. Saya bisa sangat positif tanpa mengetahui apa pun tentang model domain. Warisan adalah untuk perilaku polimorfik. Tetapi sebagai seorang singleton, Anda tidak akan memiliki perilaku polimorfik.
Billy ONeal
1
@ m3th0dman: Karena untuk mendapatkan objek singleton diperlukan menentukan nama singleton di situs panggilan. Yang berarti Anda tidak menggunakan perilaku polimorfik. Yang berarti komposisi itu jauh lebih fleksibel daripada warisan.
Billy ONeal
7

Tidak ada yang bisa dilakukan oleh singleton stateless yang abadi yang tidak bisa dilakukan oleh kelas statis.

Tidak ada alasan untuk menambahkan tingkat kompleksitas tambahan yang -> Instance () ciptakan, sementara panggilan biasa ke metode statis akan lebih jelas, lebih konservatif dalam hal sumber daya dan mungkin lebih cepat.

Bukannya mereka salah. Itu ada cara yang lebih baik untuk melakukannya. Ada skenario di mana lajang normal ("stateful") adalah cara yang tepat untuk pergi. Kejahatan dengan singleton adalah bahwa mereka sering disalahgunakan, dengan hasil buruk yang sama dengan variabel global, tetapi ada kasus khusus di mana menggunakan singleton benar. Tidak ada kasus seperti itu untuk yang kewarganegaraan.

SF.
sumber
Saya yakin Anda dapat membangun beberapa kasus di mana Singleton memiliki beberapa kelebihan. Bergantung pada skenario dan Bahasa Pemrograman mungkin (misalnya memanfaatkan pemuatan malas).
StampedeXV
1
@StampedeXV: Ya, singleton negarawan tentu saja. Yang tanpa kewarganegaraan dan kekal - saya akan sangat ingin mendengar contoh apa pun tetapi saya tidak menahan nafas.
SF.
Oke, Anda ada benarnya. Saya menggeneralisasi jawaban Anda sedikit di sana. Untuk kewarganegaraan abadi saya tidak melihat keuntungan apa pun.
StampedeXV
1
Dengan kelas yang hanya memiliki fungsi statis, Anda tidak dapat menggunakan warisan / polimorfisme yang merupakan batasan besar ...
m3th0dman
1
Tidak ada yang bisa dilakukan oleh singleton stateless yang abadi yang tidak bisa dilakukan oleh kelas statis. yah, metode statis tidak bisa mengimplementasikan antarmuka, yang bisa dilakukan oleh seorang singleton
Michal M
3

Masalah utama dengan singleton adalah bahwa ia menyembunyikan ketergantungan dan penggandaan secara khusus ketika digunakan dalam skenario keprihatinan lintas sektoral. Lihat Lajang adalah Pendusta Patologis atau Mengapa Lajang Jahat untuk bacaan lebih lanjut.

Dari sisi lain, negara yang kurang lajang, jika tidak dilecehkan, dapat membantu dan meningkatkan kinerja. Pertimbangkan sebuah contoh:

interface Interface
{
    void Method();
}

class StatelessSingleton : Interface
{
    public static readonly StatelessSingleton Instance = new StatelessSingleton();
    private StatelessSingleton() { }

    public void Method() { }
}

class User
{
    public User(Interface i) { /* ... */ }
}

Di sini, StatelessSingleton bertindak sebagai implementasi standar Antarmuka dan dimasukkan ke dalam konstruktor Pengguna. Tidak ada kopling hard-coded dan dependensi tersembunyi. Kami tidak dapat menggunakan kelas statis karena antarmuka yang mendasarinya tetapi tidak ada alasan untuk membuat lebih dari satu instance dari default. Itulah mengapa singleton yang tidak memiliki kewarganegaraan tampaknya menjadi pilihan yang tepat.

Namun, mungkin kita harus menggunakan pola lain untuk implementasi default:

class Implementation : Interface
{
    private readonly Action _method;

    public Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Itu hits kinerja sehubungan dengan StatelessSingleton tetapi merupakan implementasi generik dari Antarmuka. Solusi serupa digunakan oleh antarmuka IProgress .

Meskipun lagi, mengapa memungkinkan untuk membuat lebih dari satu implementasi perilaku default? Namun kita dapat menggabungkan keduanya:

class Implementation : Interface
{
    public readonly Implementation Default = new Implementation();

    private readonly Action _method;

    private Implementation()
    {
        _method = new Action(() => { /* default */ });
    }

    public Implementation(Action custom)
    {
        _method = custom;
    }

    public void Method()
    {
        _method();
    }
}

Sebagai kesimpulan, saya percaya bahwa ada tempat (seperti yang digambarkan sebagai default) di mana Singletons berguna. Definisi utama Singleton menyatakan bahwa ia tidak diperbolehkan membuat lebih dari satu instance kelas. Ini seperti tenaga nuklir. Dapat menghasilkan energi atau bom. Itu tergantung pada manusia.

yee
sumber