A ameaça dos singletons
Há muito tempo que ouvia sobre os problemas que o padrão singleton representa. É claro que com tantos argumentos não tinha como eu não concordar. Mas eu concordava sem dar muita importância pois nunca havia sentido na pele seus malefícios. Até que finalmente passei por uma grande dificuldade causada por um singleton. Isso finalmente despertou meu ódio por este abominável padrão. Neste artigo explico qual o problema e como o resolvi.
Ontem no desenvolvimento do Menu do GloboVideos 4.2, resolvi exercitar a prática de TDD, ou seja, eu implementeria os testes unitários para guiar o desenvolvimento das classes. O problema é que a classe que representaria o Menu do GloboVideos precisaria utilizar a classe MenuBO (com.globo.portal.cda.menu.business.MenuBO) do Portal.
A idéia era simples, mocar o MenuBO, para isolar o acesso ao banco da minha classe de forma a só testar as regras de negócio do menu do GloboVideos. Mas isso não foi possível, pois esta classe, meus amigos, segue o padrão singleton. Ou seja, o construtor dela é privado, o que impossibilita a criação de Mocks e de SubClasses.
A solução que encontrei foi criar uma classe Proxy. A MenuBOProxy. Não sem antes testar de várias maneiras um jeito de criar mocks com classes de construtor privado. Não consegui. A classe MenuBOProxy apenas implementa todos os métodos de MenuBO, delegando cada uma delas a uma instância do objeto único de MenuBO. Veja como a classe ficou:
public class MenuBOProxy {
private MenuBO menuBo;
public MenuBOProxy() {
this.menuBo = MenuBO.getInstance();
}
public MenuBOProxy(MenuBO menuBo) {
this.menuBo = menuBo;
}
public Vector listaItem(MenuVO menu)
throws BusinessException {
return menuBo.listaItem(menu);
}
public MenuVO listaMenu(MenuVO menu)
throws BusinessException {
return menuBo.listaMenu(menu);
}
public Vector listaMenus()
throws BusinessException {
return menuBo.listaMenus();
}
public String retornaListaNomeMenu(Vector vetMenuId)
throws BusinessException {
return menuBo.retornaListaNomeMenu(vetMenuId);
}
public MenuVO listaMenuPorPortalNome(MenuVO menu)
throws BusinessException {
return menuBo.listaMenuPorPortalNome(menu);
}
public MenuVO listaMenuPorId(MenuVO menu)
throws BusinessException {
return menuBo.listaMenuPorPortalNome(menu);
}
}
Com esse proxy foi possivel criar um mock e enfim testar separadamente a lógica do Menu do GloboVideos.
Por hora, a versão atual do GloboVideos também foi desenvolvido utilizando-se singletons seguindo o padrão do Portal. Mas aos poucos estamos migrando suas funcionalidades de forma a permitir uma maior testabilidade no código. Sempre seguindo a máxima de que o padrão singleton é mal, pega um pega geral.
Outros links com mais argumentos e exemplos disso estão disponíveis abaixo:
http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx
http://c2.com/cgi/wiki?SingletonsAreEvil
http://www.softwarereality.com/design/singleton.jsp
http://members.capmac.org/~orb/blog.cgi/tech/coding/no_singletons.writeback
http://www.testingreflections.com/node/view/552
September 13th, 2007 at 6:32 pm
A coisa é tão problemática que temos uma nova ferramenta:
http://code.google.com/p/google-singleton-detector/
The Google Singleton Detector, or GSD, is a tool which analyzes Java bytecode and detects the use of Singletons.
It’s not quite as simple as that, however. First, GSD doesn’t only detect singletons; it detects four different types of global state, including singletons, hingletons, mingletons and fingletons (see the usage section for descriptions). Second, it outputs a graph with all these different types of static state highlighted, and shows all the classes that are directly dependent on them. The point of this tool is to allow you to see all of the uses of global state inside a project, as well as how they are all interrelated. Hopefully you’ll be able to locate global state that is heavily depended on and remove it.
But wait, why would I want to remove my global state and/or singletons? In a nutshell, because they can make testing difficult and hide problems with your design. Again, it’s more complicated than that, so check out the FAQ for more info.
Great, ready to get rid of some singletons? Head over to the downloads section to get the latest release, or checkout code from the SVN repository and build it yourself.
Keep in mind this is still an early build; if you find that some classes are not being labeled properly, check the known limitations and file an issue if appropriate.
September 13th, 2007 at 8:22 pm
Se for para usar Singletons que sejam ao menos gerenciados por um conteiner. Ao menos serão singletons por configuração, não será uma patologia.
September 14th, 2007 at 8:38 pm
O que são TDDs?
September 17th, 2007 at 10:19 pm
Oi lsilva. TDD é isso aqui: http://gc.blog.br/2007/05/09/test-driven-development-in-a-nutshell/
September 21st, 2007 at 11:40 am
Segundo Jabá….

http://blog.globoi.com/aplicativos/2007/09/17/qualidade-de-codigo-parte-1/#comment-6