Caelum | Ensino e Inovação - Cursos de Java, Scrum, Ruby on Rails


Singletons e static: perigo a vista

Por Paulo Silveira em 08/08/06

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 :) .

  • Share/Bookmark

16 Comments »

  1. 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. ;)

    Comment by Carlos Villela — August 15, 2006 @ 8:29 am

  2. 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

    Comment by Urubatan — August 15, 2006 @ 12:14 pm

  3. 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

    Comment by Urubatan — August 15, 2006 @ 12:15 pm

  4. 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?).

    Comment by peas — August 15, 2006 @ 12:20 pm

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

    Comment by Urubatan — August 16, 2006 @ 1:08 am

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

    Comment by Carlos Villela — August 17, 2006 @ 8:31 am

  7. 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

    Comment by George Gastaldi — August 21, 2006 @ 10:58 pm

  8. 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.

    Comment by George Gastaldi — August 21, 2006 @ 11:03 pm

  9. 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.

    Comment by Paulo Silveira — August 22, 2006 @ 6:05 pm

  10. [...] 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. [...]

    Pingback by blog.caelum.com.br » Ei! Como é o seu DAO? Ele é tão abstraído quanto o meu? — August 26, 2006 @ 11:06 pm

  11. [...] 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. [...]

    Pingback by blog.caelum.com.br » Livros: escolhendo a trindade do desenvolvedor Java — September 22, 2006 @ 12:35 am

  12. 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.

    Comment by Rafael Naufal — October 19, 2006 @ 10:33 am

  13. [...] 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. [...]

    Pingback by blog.caelum.com.br » Design Patterns: um mau sinal? — December 17, 2006 @ 11:43 pm

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

    Pingback by singleton = antipattern ?! « TJRN Developers — December 10, 2007 @ 12:52 pm

  15. 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.

    Comment by Marcelo Daniel — January 29, 2009 @ 1:56 am

  16. [...] 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 [...]

    Pingback by Implementando o padrão Singleton « Felipe Benevides — February 15, 2009 @ 4:55 am

RSS feed for comments on this post. TrackBack URL

Leave a comment




Caelum | Ensino e Inovação
São Paulo: Rua Vergueiro, 3185, cj. 87, próximo ao Metrô Vila Mariana   |   Tel. (11) 5571-2751
Rio de Janeiro: Rua Senador Dantas, 80, cj. 307/308 - Centro   |   Tel. (21) 2220-4156 ou 2297-0033
Brasília: SCS Qd. 8 Bl. B-50, Sala 521 - Ed. Venâncio 2000   |   Tel. (61) 3039-4222