Os singletons imutáveis ​​/ sem estado são ruins?

12

Ultimamente, tem havido algum tipo de revolução contra os singletons, mas há algo de errado com eles se são apátridas?

Eu conheço a conversa sobre uso excessivo e tudo ... isso se aplica a tudo, não apenas a singletons.

m3th0dman
fonte
1
Não. Singletons não são, em princípio, ruins, são apenas excessivamente usados.
Bart van Ingen Schenau
3
o que você quer dizer com ultimamente?
precisa
5
@Joachim Sauer: Por que você precisaria substituir; se estiver sem estado, você pode testá-lo diretamente.
M3th0dman
1
Se você possui um singleton sem estado, basicamente tem uma classe de utilidade estática, que tem tendência a crescer no antipadrão da Classe de Deus. Em geral, você pode usar métodos estáticos no contexto em que são usados ​​(ou melhor ainda: use métodos de extensão em C #).
Spoike
1
Possível duplicado de Singleton, sem qualquer estado
Caleth

Respostas:

12
  > Are immutable/stateless singletons bad?
  • Não, se eles não dependem de outros sistemas externos.
    • Exemplo: Uma Stringutility que escapa html dentro de uma string.
    • Motivo: em unittests, não há necessidade de substituí-lo por um simulador / simulador.
  • Sim, se o seu singleton imutável / sem estado depende de outros sistemas / serviços externos e se você deseja fazer a unittesting (teste em isolamento)
    • Exemplo: um serviço que depende de um serviço de calculadora de imposto externo.
    • Motivo: para realizar unittests com este Serviço (isoladamente), você precisa simular / zombar dos Sistemas / Serviços externos.

Para mais detalhes, consulte the-onion-architecture


  • Singleton-s pode tornar o teste de unidade (isoladamente) mais difícil / impossível e
  • dependências / acoplamentos ocultos podem ser vistos como um problema, conforme explicado por @yBee

Não vejo outras razões pelas quais não usar Singletons.

k3b
fonte
Você ainda precisaria zombar desse serviço da Web externo se quiser testar sua classe, mesmo que não seja um singleton (sem estado).
M3th0dman
@ m3th0dman eu concordo
k3b
10

Depende sempre do uso. Eu acho que a revolução vem do fato de que todo programador aprende esse padrão como o padrão orientado a objetos. A maioria esquece de pensar sobre onde faz sentido e onde não faz.
Obviamente, isso é válido para todos os padrões. Apenas usando padrões, você não cria um bom código ou um bom software.

Se você possui um singleton sem estado, por que não usar uma classe que oferece apenas métodos estáticos (ou uma classe estática)?

Aqui estão alguns posts sobre variáveis ​​globais e singletons em geral.

Eu não seria tão rigoroso quanto o autor, mas ele mostra que, na maioria dos casos em que você acha que precisa de um singleton, você realmente não precisa dele.

StampedeXV
fonte
1
Por que não usar uma classe com métodos estáticos? Herança, por exemplo ...
m3th0dman
3
@ m3th0dman: Não parece um bom lugar para herança.
precisa saber é o seguinte
@BillyONeal Você pode dizer que algo é bom ou ruim para a herança, se você sabe o modelo de domínio, o que deve ser modelada dessa maneira ...
m3th0dman
2
@ m3th0dman: Erm, não. Eu posso ser bastante positivo sem saber nada sobre o modelo de domínio. A herança é para comportamento polimórfico. Mas como um singleton, você não terá um comportamento polimórfico.
Billy ONeal
1
@ m3th0dman: Porque, para obter o objeto singleton, é necessário especificar o nome do singleton no site da chamada. O que significa que você não está usando comportamento polimórfico. O que significa que a composição é muito mais flexível que a herança.
Billy ONeal
7

Não há nada que um singleton apátrida imutável possa fazer que uma classe estática não pode.

Simplesmente não há razão para adicionar o nível extra de complexidade que -> Instance () cria, enquanto a chamada simples para um método estático será mais clara, mais conservadora em termos de recursos e provavelmente mais rápida.

Não é que eles estejam errados. É que existe uma maneira melhor de fazer isso. Há cenários em que singletons normais ("com estado") são o caminho certo a seguir. O mal do singleton é que eles são frequentemente abusados, com os mesmos resultados ruins que as variáveis ​​globais, mas há casos específicos em que o uso de um singleton é simplesmente correto. Não existem casos para os apátridas.

SF.
fonte
Aposto que você pode construir alguns casos em que um Singleton tem algumas vantagens. Dependendo do cenário e da linguagem de programação, possivelmente (por exemplo, aproveitando o carregamento lento).
StampedeXV
1
@StampedeXV: Sim, um singleton com estado certamente. Um apátrida e imutável - eu ficaria muito curioso para ouvir alguns exemplos, mas não estou prendendo a respiração.
SF.
Ok, você tem razão. Eu generalizei sua resposta um pouco lá. Para imutáveis ​​apátridas, também não vejo nenhuma vantagem.
StampedeXV
1
Com aulas que têm apenas funções estáticas, você não pode usar a herança / polimorfismo que é um grande limite ...
m3th0dman
1
Não há nada que um singleton apátrida imutável possa fazer que uma classe estática não pode. bem, métodos estáticos não pode implementar uma interface, que um singleton poderia
Michal M
3

O principal problema do singleton é que ele oculta dependências e acoplamentos, especialmente quando usado no cenário de preocupações transversais. Veja Singletons são mentirosos patológicos ou Por que Singletons são maus para leitura adicional.

Por outro lado, um estado menos singleton, se não for abusado, pode ser útil e melhorar o desempenho. Considere um exemplo:

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) { /* ... */ }
}

Aqui, o StatelessSingleton atua como implementação padrão da Interface e é colocado no construtor User. Não há acoplamentos codificados e dependências hiden. Não podemos usar uma classe estática devido à interface subjacente, mas não há razão para criar mais de uma instância de um padrão. É por isso que um singleton apátrida parece ser uma escolha apropriada.

No entanto, talvez devamos usar outro padrão para uma implementação padrão:

class Implementation : Interface
{
    private readonly Action _method;

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

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

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

Ele atinge o desempenho em relação ao StatelessSingleton, mas constitui uma implementação genérica da Interface. Solução semelhante é usada pela interface IProgress .

Embora novamente, por que permitir criar mais de uma implementação do comportamento padrão? No entanto, podemos combinar os dois:

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();
    }
}

Concluindo, acredito que há lugares (como os padrões descritos) em que Singletons são úteis. A principal definição de Singleton afirma que não é permitido criar mais de uma instância de uma classe. É como energia nuclear. Pode produzir uma energia ou uma bomba. Depende do humano.

yBee
fonte