Singletons e static: perigo a vista

Postado em 08. ago, 2006 por em Arquitetura

Este post no guj trouxe uma discussão já conhecida de volta a ativa: singleton. Devemos usar singletons ou métodos estáticos?

O Carlos Villela já coloca uma opinião muito interessante:

Estado mantido de forma estática numa aplicação é tão venenoso quanto variáveis globais. Não importa como esse estado é acessado. Seja via singletons ou métodos estáticos, vai continuar sendo venenoso.

Mais para frente, ele ainda diz:

Singletons é um indício de que você precisa pensar melhor sua arquitetura

Muitas pessoas (inclusive eu) consideram o Carlos Villela um extremista da orientação a objeto. Mas nesse tópico eu concordo totalmente com ele: estamos viciados em usar Singletons apenas para facilitar nossa busca por uma varáivel global (no caso de OO, uma referência a um objeto que é compartilhado globalmente). Quando que realmente faz sentido existir um e apenas um objeto de determinado tipo? É raro.

Em outras palavras, você deve evitar ao máximo a utilização de métodos estáticos (que tem um sabor de função procedural) e nem singletons (com o sabor variável global). Como resolver essa nossa necessidade? Certamente com injeção de dependências. Algumas pessoas já classificam Singleton como um antipattern: uma má solução para o seu problema.

A idéia é que você tire a responsabilidade de fazer lookup de recursos da sua lógica de negócio, e que esse seu recurso (essa sua dependência) seja lhe dada (injeção de dependências, DI) por outra pessoa, invertendo assim os papéis (inversão de controle, IOC): você não mais busca por um recurso, esse recurso é dado a você!

Entendo que muitos dos leitores já estão cansados de usar essas técnicas, mas vale lembrar que elas são úteis também no nosso caso de Singletons. Tanto que você vai encontrar diversos tópicos por aí como este: Como refatorar Singleton para injeção de dependências.

Mais abaixo o Villela fala do interessante recurso que alguns linguagens consideradas mais puramente OO tem, que no Java seria equivalente ao seguinte trecho (apenas ficção):

Integer i = 5;
Integer raiz = i.squareRoot();

Imagine todas as classes wrappers terem todos os tipos imagiáveis de operações? Não só elas, mas também BigInteger e BigDecimal? Nesse caso ainda prefiro as funçõezinhas procedurais da java.lang.Math :) .

Paulo Silveira

Mais sobre o autor

Tags: , , , ,

22 Respostas para “Singletons e static: perigo a vista”

  1. Carlos Villela

    15. ago, 2006

    Sobre as classes wrappers ter todo tipo de operacao: funciona bem pra Smalltalk, Ruby, Io e diversas outras linguagens. O que todas essas tem em comum? “Classes” abertas: voce pode adicionar novos metodos a classes (ou prototipos) ja existentes.

    Assim da pra fazer coisas como o 9.days.ago do Rails, ou o 3/2 -> 3/2 do mathn. ;)

  2. Urubatan

    15. ago, 2006

    Quanto aos singletons …
    Acho que varia bastante, não tem como tomar isto como verdade absoluta :D
    também é possivel olhar pelo lado contrário, por exemplo …
    Faz sentido instanciar esta classe a todo momento?
    por exemplo um DAO, que é completamente Stateless.
    eu posso utilizar a mesma instancia para toda a minha aplicação, em diversos threads que não terei problema nenhum.
    Tudo bem, um Dao não é o exemplo mais orientado a objetos do mundo …
    Mas existem diversos outros serviços dentro da aplicação que não faz sentido criar instancias a todo momento.
    normalmente uso apenas DI para injetar a mesma instancia em todos os pontos necessários, mas não vejo razão para o container criar uma nova instancia destes serviços sempre que eu precisar deles …
    Até por que isto daria mais trabalho desnecessário para o Garbage Collector :D
    Bom, esta é só a minha opinião :D

  3. Urubatan

    15. ago, 2006

    Mais uma coisa …
    Não vejo muita diferença de um singleton implementado manualmente (com um getInstance estático por exemplo)
    para um criado por um container de DI
    Nos dois casos vai haver apenas uma instancia daquela classe na aplicação :D

  4. peas

    15. ago, 2006

    Urubatan, a questão é que quem daria o new seria o Container, e ele vai dar um new só. O dia que você não quiser mais que aquele bean seja como um singleton, isso é, o dia que quiser mudar a política de instanciação daquele objeto, não precisará fazer mudanças estruturais no código dele (abrir o construtor, remover a referência estática para ele mesmo, remover o getInstance, etc).

    E o dia que seu DAO não for stateless? Os meus DAOs por exemplo não são: o HibernateDAO recebe Session no construtor.

    Eu entendo que o efeito final é o mesmo, porém evitar o Singleton te facilita as futuras modificações (e não é isso que queremos com OO?).

  5. Urubatan

    16. ago, 2006

    verdade …
    pensando desta forma não da na mesma o DI e o singleton hardcoded mesmo :D

  6. Carlos Villela

    17. ago, 2006

    Outro otimo motivo pra nao usar singletons: tenta escrever um singleton com TDD. ;)

  7. George Gastaldi

    21. ago, 2006

    Excelente Post ! Realmente a DI é muito melhor que Singleton. Eu conseguia ver isso de uma forma turva, mas depois desse post tudo ficou mais claro ! :D

  8. George Gastaldi

    21. ago, 2006

    Um comentário, me corrijam se eu estiver errado:
    “Não existe um mecanismo de injeção de dependência que não seja um Singleton, ou seja, para alcançar o propósito de um mecanismo de injeção de dependência, o próprio mecanismo deve ser um Singleton.”

    Certo ? Errado ? Opinem.

  9. Paulo Silveira

    22. ago, 2006

    George, talvez você tenha razão quanto a isso, pois temos um problema ovo-galinha… Por exemplo, se fizermos nossa injeção de dependências em um Servlet Filter, deve haver alguém que controla esses filtros, que pode vir a ser um Singleton dentro do tomcat.

    Mas o interessante é que você ficou livre disso.

  10. Rafael Naufal

    19. out, 2006

    Para quem quiser entender um pouco mais de injeção de dependências, um modo de inversão de controle, vale a pena dar uma olhada neste artigo de Martin Fowler: Fowler IOC. Inclusive ele faz comparações da obtenção de recursos via um lookup com JNDI, utilizando ServiceLocator(que seria um Singleton) e o paradigma de inversão de controle.

  11. Marcelo Daniel

    29. jan, 2009

    Eu concordo com o Urubatan, no final das contas eu acredito que tudo depende da necessidade. Também acho Singleton uma espécie de variável global (na verdade instância global). Acho radicalismo demais rotular singleton como anti pattern.

  12. Marcelo F Andrade

    29. mar, 2012

    Em termos práticos, um revés de se usar métodos estáticos extensivamente é lembrar que não há herança dos mesmos. Portanto, se um dia você pensar em dividir a responsabilidade por aquele monte de métodos estáticos em mais de uma classe, vai ter um trabalho a mais do que se já tivesse os escrito como métodos de classe originalmente.

Trackbacks/Pingbacks

  1. blog.caelum.com.br » Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? - agosto 26, 2006

    [...] Na minha humilde opinião, DAO é uma maneira de você encapsular o seu acesso a dados. Não importa se é através de uma factory de objetos que recebem uma Session do hibernate por injeção de dependências, ou se é um montão de métodos estáticos cheio de SQL dentro deles (argh!). Obviamente a última opção envolve diversos outros antipatterns (como singleton e métodos estáticos, que já criticamos anteriormente), porém ela consegue isolar seu acesso a dados, cumprindo o papel do DAO e de alguma maneira organizando sua camada. [...]

  2. blog.caelum.com.br » Livros: escolhendo a trindade do desenvolvedor Java - setembro 22, 2006

    [...] Apesar disso, todos eles revelam sinais de sua idade. No Design Patterns, muita gente já considera Singleton como um antipattern (como discutido neste post). Mais ainda, alguns vão além, dizendo que se você precisou utilizar um design pattern, é provável que a sua linguagem não tenha um nível de abstração suficiente para suprir as suas necessidades. Na minha opinião, uma crítica válida. [...]

  3. blog.caelum.com.br » Design Patterns: um mau sinal? - dezembro 17, 2006

    [...] Singleton – Este é bem fácil e já bloguei sobre os problemas do Singleton. É raríssimo querermos que uma classe possua uma única instância por modelagem. Normalmente usamos o singleton apenas para fazer lookup a uma instância: quase que uma variável global. Pode ser totalmente substituído com o uso de injeção de dependências. [...]

  4. singleton = antipattern ?! « TJRN Developers - dezembro 10, 2007

    [...] singleton = antipattern ?! “…Singletons é um indício de que você precisa pensar melhor sua arquitetura…&#8… [...]

  5. Implementando o padrão Singleton « Felipe Benevides - fevereiro 15, 2009

    [...] muita gente e podem ser apontadas mais desvantagens do que vantagens do seu uso.  Concordo com o post (bem antigo, é verdade) do Paulo Silveira da Caelum, quando ele [...]

  6. Vinicius Quaiato » Blog Archive » Singletons são um problema, veja - outubro 22, 2010

    [...] uma discussão até que acalorada sobre Singletons no grupo .NET Architects (veja aqui a thread). E aqui temos um post sobre isso no blog da Caelum [...]

  7. Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? | blog.caelum.com.br - janeiro 18, 2011

    [...] a última opção envolve diversos outros antipatterns (como singleton e métodos estáticos, que já criticamos anteriormente), porém ela consegue isolar seu acesso a dados, cumprindo o papel do DAO e de alguma maneira [...]

  8. Design Patterns: um mau sinal? | blog.caelum.com.br - janeiro 19, 2011

    [...] – Este é bem fácil e já bloguei sobre os problemas do Singleton. É raríssimo querermos que uma classe possua uma única instância por modelagem. Normalmente [...]

  9. Padrões de Projeto (Design Patterns) – Introdução « De tudo um pouco – Luiz Feltes - janeiro 29, 2011

    [...] http://blog.caelum.com.br/singletons-e-static-perigo-a-vista/ [...]

  10. Java EE versus Spring: retomando a discussão | blog.caelum.com.br - março 27, 2012

    [...] inicio, baseando-se em POJOs seguindo convenções, deixando configurações obsoletas, com muita injeção de dependências e baixo acoplamento para não interferir na testabilidade. Diversos conceitos e recursos que o J2EE [...]

Deixar uma Resposta