Este Singleton está utilizado corretamente?  XML
Índice dos Fóruns » Arquitetura de Sistemas
Autor Mensagem
gomesrod
GUJ Ranger
[Avatar]

Membro desde: 11/05/2007 19:46:22
Mensagens: 901
Offline

Olá pessoal,

Tenho visto muita discussão sobre o padrão Singleton não ser um bom negócio, algo como as boas e velhas variáveis globais (o "boas" é brincadeira ).
Em alguns projetos, utilizei o Singleton como um ponto de acesso para dados em cache, mais ou menos assim:


A partir disso, em qualquer ponto do sistema (apresentação, ou camada de negócios) posso obter os dados da
seguinte forma:


Como essa lista é mostrada em inúmeras telas e praticamente não sofre alterações no dia-a-dia, a consulta inicial é aproveitada por todo o tempo de vida do aplicativo.

Gostaria de saber a opinião de vocês a respeito desse uso. Estou sendo porco/gambiarreiro ? É possível melhorar essa implementação?
pcalcado
Moderador
[Avatar]

Membro desde: 08/03/2004 17:19:35
Mensagens: 5174
Localização: Sydney - Australia
Offline

Gambiarra

Você está usando Singleton como variável global. No seu exemplo o problema não é ter mais de um cache, o problema é que os clientes devem usar o mesmo cache.

Como fazer isso? Padrão Registry ou Dependency Injection são as soluções mais comuns.

BTW: seu Singleton tem um problema clássico de concorrência, não vou dizer qual é para que você dê uma procurada

Phillip Calçado "Shoes"
http://fragmental.tw/
http://blog.fragmental.com.br/
"It is unfortunate that much of what is called 'object-oriented programming today is simply old style programming with fancier constructs." - Alan Kay
[Email] [WWW] [Yahoo!] [MSN]
gomesrod
GUJ Ranger
[Avatar]

Membro desde: 11/05/2007 19:46:22
Mensagens: 901
Offline

Gambiarra

Você está usando Singleton como variável global. No seu exemplo o problema não é ter mais de um cache, o problema é que os clientes devem usar o mesmo cache.

Muito triste isso....
Mas por outro lado aprendi um conceito em que eu nunca havia pensado antes: "Todo mundo deve acessar o mesmo" e "Só pode existir um" são coisas diferentes!
Como fazer isso? Padrão Registry ou Dependency Injection são as soluções mais comuns.

O padrão Registry é tão simples que eu achei que ele é que fosse Gambiarra . Sobre a Dependency Injection, eu ainda não consegui enxergar como posso utiliza-la nesse caso, vou analisar melhor esse pattern.

BTW: seu Singleton tem um problema clássico de concorrência, não vou dizer qual é para que você dê uma procurada.

Não consegui identificar... acredito que seja algo no construtor, pois os demais métodos só fazem leitura então não haverá problemas de concorrência. Mas não consegui encontrar o erro!
marcelo_mococa
Virtual Machine Man
[Avatar]

Membro desde: 03/03/2005 10:03:32
Mensagens: 622
Localização: São Paulo
Offline

aconselho a leitura (aqui você achará a resposta sobre o que o pcalcado disse):
http://java.sun.com/developer/technicalArticles/Programming/singletons/

apenas reforçand: "esqueça singletons, se você quer apenas uma instância do bean por toda a aplicação use um conteiner de IoC (ex: spring)."

Marcelo Madeira - TCS
SCJP 1.5
SCWCD 1.4
blog

rodrigoallemand
GUJ Ranger
[Avatar]

Membro desde: 21/02/2005 20:19:47
Mensagens: 972
Localização: Rio de Janeiro, Recreio!!!
Offline

Engraçado a dependencia das pessoas com "Conteiner IoC como o Spring"... O Spring, como no exemplo, levanta por default os benas como singleton.. até ai nada... ele precisa de um singleton e não de um framework que faz singleton...

Singleton é um padrão... a implementação pode variar... Se sua concorrencia for pouca, seu singleton funciona... se for alta, existem maneiras de melhorar, usando um check duplo, variaveis volatile, etc...
Mas se vc tiver uma aplicação distribuida, esse seu singleton está furado... neste caso, se for web, tente utilizar o context...

Como vc pode ver, são maneiras diferentes para solucionar um problema... Pattern diz respeito a solução de um problema, podendo ter diferentes codificações... e o melhor pattern é o que resolve o seu problema, eficientemente.

Rodrigo Allemand

A culpa é minha e eu a coloco em quem eu quizer!. (Homer Simpson)
http://blog.rodrigoallemand.com.br
[WWW] [MSN]
alberto_ribeiro
JavaEvangelist
[Avatar]

Membro desde: 01/07/2005 11:15:19
Mensagens: 351
Localização: SP
Offline

boa noite, alguém teria algum exemplo de utilização do padrão Registry, por favor ? ele é usado como uma alternativa para não usar singleton ?

O problema que o pcalcado disse é referente ao método não estar sincronizado ? pois pode acontecer que ele seja chamada por dois processos ao mesmo tempo ? mais como ficaria se acontece isso ? poderia ocorrer duas instancias de um singleton ? (desculpa se estiver falando besteira...rs)

[]'s

Sun Certified Programmer for Java 1.5
[Email] [MSN]
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline



O que vc fez não é cambiarra mas poderia ser melhor. Não refiro a uma melhor implementação mas a um melhor conceito. Afinal, o que vc quer ?
Quer uma classe que seja um ponto central para acessar a coleção de todos os clientes e tb que possa retornar um só cliente. Vc pode fazer isso sem usar singleton explicitamente. Registry é um nome possivel para a implementação a seguir, embora Repository seja mais apropriado. Porque? Porque Registry implica em registro. Uma parte do codigo registra alguma coisa no registro e outra parte do codigo lê o que foi registrado. Registry é um ponto de encontro entre duas, ou mais, partes do codigo.
Repository não tem a parte do registro. Ninguém registra nada nele. Ele obtém as informações e as disponibiliza.

Eis uma implementação possivel. Note que vc pode procurar por mais coisas que apenas clientes





O uso é ainda mais simples que singleton



Melhor que o singleton porque não precisa ter um singleton para cada entidade e porque com um pouco mais de cuidado e usando generics vc poderá implementar de forma mais curta e simples. Ou implementar métodos mais complexos como



Usando generics vc pode tb pensar em ter um so DAO, em vez de um para cada entidade.
Quanto a injecção de dependencia vc pode usar um codigo estático que consulta uma fabrica de DAO, ou se tiver apenas um DAO genérico, uma fabrica que retorna a implementação correcta da interface do DAO. ISto porque usar new XXXDAO() é sempre ruim(*).



(*) Do ponto de vista estritamente de design. Pode ser bom se o projeto for pequeno e/ou tiver que ser implementado depressa.

Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
pcalcado
Moderador
[Avatar]

Membro desde: 08/03/2004 17:19:35
Mensagens: 5174
Localização: Sydney - Australia
Offline

rodrigoallemand wrote:Engraçado a dependencia das pessoas com "Conteiner IoC como o Spring"... O Spring, como no exemplo, levanta por default os benas como singleton.. até ai nada... ele precisa de um singleton e não de um framework que faz singleton...


Não senhor. Se o Spring possui algum Singleton dentro dele eu sinceramente não sei, e não me importa. O que o Spring é para o usuário é uma factory genérica que, por padrão, retorna sempre a mesma instância (isso pdoe ser alterado). Isso é completamente diferente de usar um Singleton na aplicação e mais diferente ainda de usar um Singleton apenas apra poder 'desfrutar' de uma variável global no sistema.

O ponto aqui não chegou ao nível de usar Spring ou não, ainda estamos no mundo dos conceitos.

rodrigoallemand wrote:
Singleton é um padrão... a implementação pode variar... Se sua concorrencia for pouca, seu singleton funciona... se for alta, existem maneiras de melhorar, usando um check duplo, variaveis volatile, etc...


Você está enganado, Singleton (bem implementado) se comporta muito bem com concorrência. Usar variáveis voláteis nem sequer alivia o pior dos problemas de concorrência com Singletons, que é o fato de que no exemplo acima poderem haver mais de um Singleton em memória. Um double check sincronizado evita este problema mas é um senhor desperdício de lock. Existe um meio muito simples e eficaz.

Mas como Singletons são usados apra variáveis globais não há tanto problema, afinal o que se quer é poder acessar uma variável de qualquer lugar do programa, não um objeto que só possa ter uma instância. O padrão trata apenas desta última sentença, ter um objeto que só pode ser instanciado uma vez, por isso usar Singletons quando se quer variáveis globais é uma baita duma gambiarra, infelizmente altamente difundida.

rodrigoallemand wrote:
Como vc pode ver, são maneiras diferentes para solucionar um problema... Pattern diz respeito a solução de um problema, podendo ter diferentes codificações... e o melhor pattern é o que resolve o seu problema, eficientemente.


O problema, Rodrigo, é que me parece que você não leu o problema ao qual este padrão resolve. O problema é ter apenas um bojeto em memória, não acessar recursos.

Phillip Calçado "Shoes"
http://fragmental.tw/
http://blog.fragmental.com.br/
"It is unfortunate that much of what is called 'object-oriented programming today is simply old style programming with fancier constructs." - Alan Kay
[Email] [WWW] [Yahoo!] [MSN]
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

alberto_ribeiro wrote:
poderia ocorrer duas instancias de um singleton ?


Teoricamente não. O objetivo do singleton é garantir que não ha forma de ter duas instâncias. E a palavra importante aqui é garantir. Ter certeza. Poder confiar.

Claro que a implementação pode ser mal feita e isso levar a que possam existir duas instancias da classe. Mas isso não significa que ha dois singletons, significa que a implemnetação está errada e não é , na verdade, a implementação de um singleton.

O singleton, como padrão de projeto (design pattern) , como entidade teorica, como simbolo, não permite conceber que existam duas instancias da mesma classe. Por isso que o padrão se chama assim. Single = Unico, Sozinho. Exatamente para deixar claro o objetivo.

O singleton, como implementação, como código, pode permitir que existam duas instâncias. O que ele não pode permitir é que existam simultaneamente do ponto de vista do sistema que o usa.
Se em alguma hipotese, seja porque o código está mal implementado (por exemplo deixando a classe ser extendida), seja porque o método usado para o construir à partida não garante a singularidade (fábricas de injeção, por exemplo) , então, esse código , não é uma implementação do padrão de projeto Singleton. Se não é uma implementação , então , mesmo que tenha sido esse o objetivo original, essa classe não é um singleton.

O padrão Singleton é para classes. É uma forma de implementar uma classe para garantir que não é possível ter , simultaneamente, dois objetos dessa classe.

Este objetivo é diferente de garantir que não existem mais do 1 objeto de uma certa classe. Aqui , estamos preocupados em poupar recursos e não em impedir que se criem mais objetos da classe. Isto é conhecido como Shared Object Pattern (Objeto partilhado) que não é a mesma coisa que Singleton.
Um singleton é um caso especial de shared object. A diferença é que no shared object se usa um so objeto porque se quer. A classe permite criar outros. No singleton, usa um so objeto porque não consigo criar mais nenhum.

Exemplo de Shared Object são os Servelts e os SessionBeans. Um outro caso especial, além do singleton, são implementações de Connection num pool de conexões.


Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Vou dar a minha opinião sobre o singleton. E aposto que muitos teoricos aqui do GUJ ficarão um tanto decepcionados.

Eu gosto do padrão. E considero ele bastante seguro.

Em primeiro lugar, não estou falando aqui de usar um singleton como variável global, que isso fique bem claro. Mas do uso do Singleton para o que ele foi feito: gerir recursos que realmente são únicos e garantir que determinados objetos tenham somente uma instância.

Agora, sou muito crítico a respeito de designs "perfeitos". Em primeiro lugar, porque isso não existe. Em segundo, existe diversos custos em designs complexo que, com o tempo, percebi que não só são perda de tempo, como um desperdício pagar por eles. Estamos falando aqui de trade-offs.

Por exemplo, qualquer depency injection decente precisa de um framework para ser bem implementado. Isso é um custo. Ele também está sujeito a erros de runtime, uma vez que implementações serão obtidas por meios reflexivos. O framework também está sujeito a bugs e, se for de terceiros, parabéns, você não terá como prever quando serão corrigidos e ainda corre o risco do frameworks ser abandonado. Por fim, o código fica menos claro, você passa a ter que ler arquivos externos ao .jar. E tudo isso faz parte do custo que estou falando.

Por outro lado, o bom e velho singleton não sofre desses males. Qualquer programador Java pode entende-lo facilmente. Não precisa de nenhum .jar externo.

Em segundo lugar. Os tais "problemas de concorrência" que geram duas instâncias singleton geralmente aconterão se suas threads tentaram acessar uma instância não criada de singleton, simultaneamente, pela primeira vez. O que, na minha opinião, é bastante raro. A razão é até lógica. Na absurda maioria das vezes, acessamos o singleton antes mesmo de haver qualquer concorrência no sistema.

Quanto ao caso dos "multiplos classloaders geram multiplos singletons". Honestamente, isso não deve ser uma preocupação a menos que você efetivamente use multiplos class loaders. O que é comum em aplicações web e em sistemas distribuídos (mas, no caso de sistemas distribuídos, muitas vezes nem mesmo o dependency injection resolve o problema).

Eu poderia continuar dando mais e mais argumentos. Mas, o que quero frisar aqui é: saiba o que você está fazendo. Se você usa o singleton só porque acha bonito. Rapaz, realmente, procure outras coisas por aí que dizem que são mais bonitas do que singleton.

Agora, se você conhece bem o domínio de sua aplicação, e está escolhendo usar o singleton por ele representar um pattern mais simples, está ciente de suas limitações e das consequências que elas podem te trazer. Muito bem. O singleton será seu amigo e faça ótimo proveito dele. Tenha sempre em mente que design de sistemas é lidar com trade-offs. Que para tudo que você faz haverá vantagens e desvantagens em faze-lo. E que muitas vezes essas desvantagens não são técnicas.
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Para quem não conhece muito de C++ e outras linguagens do gênero, vale lembrar que o Singleton foi percebido nesse ambiente.

Em primeiro lugar, há algumas características que tornam o singleton mais interessante fora do Java, e que por isso ele se tornou um pattern tão conhecido:

1. No C++ não há multiplos class loaders e há maneiras de torna-lo thread-safe;

2. No C++, o Singleton não precisa ser importado nos header files da classe que o usam. Como ele não é passado por parâmetro, ele pode ser usado diretamente no .cpp. E isso reduz os tempos de compilação;

3. É muitíssimo seguro usar um objeto singleton. Você evita dores de cabeça com dangling pointers ou memory leaks, já que você não acessa o singleton indiretamente.
[WWW]
pcalcado
Moderador
[Avatar]

Membro desde: 08/03/2004 17:19:35
Mensagens: 5174
Localização: Sydney - Australia
Offline

ViniGodoy wrote:Vou dar a minha opinião sobre o singleton. E aposto que muitos teoricos aqui do GUJ ficarão um tanto decepcionados.


Me explica uma coisa: qual o seu conceito de teórico? Teórico é quem estuda sobre sua profissão, lê os livros de referência e aplica as técnicas que são difundidas a anos? Pŕatico é aquele que não quer saber de nada além do básico e mete a mão na massa?

ViniGodoy wrote:
Em primeiro lugar, não estou falando aqui de usar um singleton como variável global, que isso fique bem claro. Mas do uso do Singleton para o que ele foi feito: gerir recursos que realmente são únicos e garantir que determinados objetos tenham somente uma instância.


Aqui concordamos...

ViniGodoy wrote:
Agora, sou muito crítico a respeito de designs "perfeitos". Em primeiro lugar, porque isso não existe. Em segundo, existe diversos custos em designs complexo que, com o tempo, percebi que não só são perda de tempo, como um desperdício pagar por eles. Estamos falando aqui de trade-offs.


Antes de prosseguir neste ponto algumas perguntas:

1) O que é complexidade?
2) O que é um design perfeito e por que você colocou este termo no assunto?

Não estou dizendo que é o seu caso, mas este tipo de comentário é muito típico quando alguém quer dar uma justificativa para usar uma gambiarra ou um anti-pattern. Frases de efeito como "não tem outro jeito melhor", "assim é mais simples", "não dá pra usar OO de verdade", sem argumentos, só afirmações curtas e drásticas. Para que não fiquemos com a impressão que esse é o caso seria legal sedimentar essa tal complexidade em alguns argumentos.

ViniGodoy wrote:
Por exemplo, qualquer depency injection decente precisa de um framework para ser bem implementado. Isso é um custo. Ele também está sujeito a erros de runtime, uma vez que implementações serão obtidas por meios reflexivos. O framework também está sujeito a bugs e, se for de terceiros, parabéns, você não terá como prever quando serão corrigidos e ainda corre o risco do frameworks ser abandonado. Por fim, o código fica menos claro, você passa a ter que ler arquivos externos ao .jar. E tudo isso faz parte do custo que estou falando.

Por outro lado, o bom e velho singleton não sofre desses males. Qualquer programador Java pode entende-lo facilmente. Não precisa de nenhum .jar externo.


Ahm? Do jeito que você está colocando é: ou você usa singleton ou usa um framework externo, que simplesmente não é verdade. Ignorando o gerenciamento de dependências facilitado que uma ferramenta desta te dá você pode ter os efeitos com um simples Registry ou um conjunto de Factories, como aliás já foi citado neste tópico.

A propósito, lá em cima você disse que o ponto que defendia não era sobre Singletons como variáveis globais, como a única maneira de comparar um Singleton com IoC é utilizando um método getInscante()-like que emula uma variável global seu texto ficou bem confuso. Afinal, você defende ou não variáveis globais?

ViniGodoy wrote:
Em segundo lugar. Os tais "problemas de concorrência" que geram duas instâncias singleton geralmente aconterão se suas threads tentaram acessar uma instância não criada de singleton, simultaneamente, pela primeira vez. O que, na minha opinião, é bastante raro. A razão é até lógica. Na absurda maioria das vezes, acessamos o singleton antes mesmo de haver qualquer concorrência no sistema.


Acho que não fui claro lá em cima. Quando mencionei originalmente o problema de concorrência foi apenas uma viso para o autor original, nãoe stava relacionado com o tema Singleton x OO sem variáveis globais (se você parar para ver ot exto vai ver que inicia com um 'BTW', que significa 'a propósito).

Ainda assim, se existe (e não existe na maioria dos casos) necessidade do uso de um Singleton você teria um problema *sim* ao ter duas instâncias. É como ter um Observer e o objeto observado não avisar seus observadores: o padrão foi quebrado.

ViniGodoy wrote:
Agora, se você conhece bem o domínio de sua aplicação, e está escolhendo usar o singleton por ele representar um pattern mais simples, está ciente de suas limitações e das consequências que elas podem te trazer. Muito bem. O singleton será seu amigo e faça ótimo proveito dele. Tenha sempre em mente que design de sistemas é lidar com trade-offs. Que para tudo que você faz haverá vantagens e desvantagens em faze-lo. E que muitas vezes essas desvantagens não são técnicas.


Acho que qualquer um que leia sobre sua profissão (será que ele vira um 'teórico' ao pegar um livro?) vai entender que a vida de um desenvolvedor é feita de escolhas que variam com o cenário.

O ponto é que temos um padrão utilizado como anti-pattern amplamente por uma indústria que não se preocupa em coisas simples como gerenciamento de dependências, testabilidade e flexibilidade (muito prejudicadas com o uso do anti-pattern em questão).
[Email] [WWW] [Yahoo!] [MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

pcalcado wrote:Me explica uma coisa: qual o seu conceito de teórico? Teórico é quem estuda sobre sua profissão, lê os livros de referência e aplica as técnicas que são difundidas a anos? Pŕatico é aquele que não quer saber de nada além do básico e mete a mão na massa?


Não estava falando de maneira pejorativa ao dizer "teórico". A teoria é ótima e ela ajuda muito no desenvolvimento.

Mas a teoria procura ser abrangente e, muitas vezes, procura resolver problemas de ocorrência rara. E na prática, realmente, podemos abrir mão de um pouco de purismo para buscar outros benefícios, como um design mais simples.

pcalcado wrote:1) O que é complexidade?


Bem, a pergunta um é tema de ampla discussão pela humanidade. Aliás, foi até um tanto capiciosa de sua parte, pois você sabe que não há uma resposta concreta. O que temos são definições de complexidade, dadas por diversos autores.

E eu concordo com você. Algumas pessoas podem tentar usar esse comentário para justificar o uso de um anti-pattern, que é o caso de muita gente que faz isso aqui no GUJ.

Mas esse não foi o único argumento que dei e nem de longe quero que fique justificado o uso de uma gambiarra ou de um anti-pattern.

Mas quando um pattern se torna um anti-pattern? Quando ele é usado fora de seu contexto. E é sobre isso que se tratava o meu post. Avaliar corretamente o contexto, não necessariamente justificar um anti-pattern.

pcalcado wrote:2) O que é um design perfeito e por que você colocou este termo no assunto?

Eu estava me referindo justamente a forma como muitos patterns são "vendidos", especialmente pelos fabricantes de frameworks. Vende-se o pattern como se fosse a solução de todos os problemas. Muitos posts do GUJ usam o mesmo argumento: Troque singleton por dependency injection e durma tranquilo. Não estou falando que é o seu caso, aliás, bem pelo contrário. Gosto muito dos seus posts.


pcalcado wrote:você pode ter os efeitos com um simples Registry ou um conjunto de Factories, como aliás já foi citado neste tópico.

Sim, mas meu post foi sobre trade-offs. Trocar um padrão por outro sempre representa ganhos de um lado e perdas de outro. Usar um framework também. Era isso que eu queria ressaltar. E são esses os trade-offs que devem ser avaliados.

Foi o que ressaltei no exemplo do framework. Você tem que estar ciente que está se baseando em códigos de terceiros e tem que estar ciente das implicações disso. Se o framework usa reflexão, você tem que estar preparado para erros em runtime. É sua responsabilidade, como analista ou projetista de software, avaliar o impacto disso no sistema e o transtorno que isso causa a equipe.

O caso do "simples Registry e de Factories", é um bom exemplo. Você ainda terá que se incomodar que suas factories sejam thread-safe e operem de maneira semelhante em múltiplos classloaders. Ou você terá o mesmo problema do bom e velho singleton. Daí eu ter dito que, se seu argumento era aquele, você fatalmente recairá num framework que faça isso para você, ou gastará horas desenvolvendo algo que está fora da lógica de seu negócio, ou correrá o risco. Mas deve-se pensar. Essa minha preocupação é relevante? Preciso mesmo garantir thread-safety nesse sistema? Ele roda em múltiplos class loaders?

pcalcado wrote:Ainda assim, se existe (e não existe na maioria dos casos) necessidade do uso de um Singleton você teria um problema *sim* ao ter duas instâncias. É como ter um Observer e o objeto observado não avisar seus observadores: o padrão foi quebrado.


Sim, eu concordo. Se você tiver duas instâncias de um singleton é um problema sério. Isso foi uma coisa que nunca defendi e até dei algumas situações onde o singleton certamente não se aplica, pois as chances de isso ocorrer são bastante altas.

pcalcado wrote:O ponto é que temos um padrão utilizado como anti-pattern amplamente por uma indústria que não se preocupa em coisas simples como gerenciamento de dependências, testabilidade e flexibilidade (muito prejudicadas com o uso do anti-pattern em questão).


Esse seu último paragrafo resumiu com maestria tudo o que eu vinha dizendo. Usar corretamente qualquer pattern envolve muito estudo, domínio do problema, entendimento dos requisitos técnicos e não técnicos, uso adequado de soluções provisórias e de longo prazo, organização e uma boa dose de disciplina. Em resumo, é necessário conhecer o pattern, seu impacto sobre todos os fatores que você colocou, dentro do sistema que você está desenvolvendo.
[WWW]
pcalcado
Moderador
[Avatar]

Membro desde: 08/03/2004 17:19:35
Mensagens: 5174
Localização: Sydney - Australia
Offline

ViniGodoy wrote:
O caso do "simples Registry e de Factories", é um bom exemplo. Você ainda terá que se incomodar que suas factories sejam thread-safe e operem de maneira semelhante em múltiplos classloaders. Ou você terá o mesmo problema do bom e velho singleton.


Aí que está: não tenho não.

Ao abdicar de uma variável global em forma de Singleton eu não preciso criar factories thread-sfae. A Factory em seu contrato diz que retorna um objeto válido (i.e. invariante satisfeita), não necessariamente que ele retorna sempre um novo objeto ou que retorna sempre o mesmo objeto. Se quisermos manter o mesmo objeto por economia de recursos podemos fazê-los mas como não se trata de um Singleton, não há problema caso mais de um seja criado, é apenas um desperdício de recursos. Caso o desperdício seja um problema pode-se utilizar primiivas bem simples de sincronização.

No caso do Registry é ainda mais simples. O Registry irá guardar as referências em um lugar comum, como um contexto de aplicação, e não nele mesmo. É assim, por exemplo, que JNDI trabalha.

ViniGodoy wrote:
Daí eu ter dito que, se seu argumento era aquele, você fatalmente recairá num framework que faça isso para você, ou gastará horas desenvolvendo algo que está fora da lógica de seu negócio, ou correrá o risco. Mas deve-se pensar. Essa minha preocupação é relevante? Preciso mesmo garantir thread-safety nesse sistema? Ele roda em múltiplos class loaders?


E você não tem este problema com Singletons?

ViniGodoy wrote:
Esse seu último paragrafo resumiu com maestria tudo o que eu vinha dizendo. Usar corretamente qualquer pattern envolve muito estudo, domínio do problema, entendimento dos requisitos técnicos e não técnicos, uso adequado de soluções provisórias e de longo prazo, organização e uma boa dose de disciplina. Em resumo, é necessário conhecer o pattern, seu impacto sobre todos os fatores que você colocou, dentro do sistema que você está desenvolvendo.


Se alguém no GUJ entra perguntando se a tecnologia utilizada em Java para criar aplicações desktop é EJB ou Swing o que você responderia? E se após ser informado que deve buscar por Swing ele avisa que na verdade ele já tem a tela em Delphi e quer algo que fique residente na máquina do usuário e seja acessado pelo Delphi em CORBA?

Casos de exceção semrpe vão acontecer e para estes casos espera-se que o desenvolvedor conheça um mínimo de opções. O problema é nivelar pela exceção.

No caso de gerenciamento de dependências em específico eu realmente nunca ouvi nenhum argumento que faça um Singleton ser mais interessante que uma Factory que retorna o mesmo objeto.
[Email] [WWW] [Yahoo!] [MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

pcalcado wrote:Ao abdicar de uma variável global em forma de Singleton eu não preciso criar factories thread-sfae. A Factory em seu contrato diz que retorna um objeto válido (i.e. invariante satisfeita), não necessariamente que ele retorna sempre um novo objeto ou que retorna sempre o mesmo objeto. Se quisermos manter o mesmo objeto por economia de recursos podemos fazê-los mas como não se trata de um Singleton, não há problema caso mais de um seja criado, é apenas um desperdício de recursos. Caso o desperdício seja um problema pode-se utilizar primiivas bem simples de sincronização.

No caso de xunxar o singleton para usa-lo como uma variável global, tem toda razão. Mas você pode ter sérios problemas caso o objetivo de usar um singleton seja o original: Você estar controlando um recurso restrito do sistema. Eu não estava falando de usar o singleton como uma variável global, em primeiro lugar. Foi uma das primeiras coisas que ressaltei.

Mas, se seu singleton é o manager de uma conexão socket, que é a única porta de entrada de um determinado servidor, ou se seu singleton atuava como um gerente de memória num profiler, sua factory terá que garantir que as classes tenham acesso a esse recurso único, mesmo entre múltiplas threads. Mas, isso deve ser uma preocupação se seu sistema tiver multiplas threads. E se ele eventualmente um dia utilizar mais de um class loader. E se os malefícios de usar uma outra tecnologia forem inferiores aos malefícios da sua. Trade-offs, trade-offs...

ViniGodoy wrote:
Daí eu ter dito que, se seu argumento era aquele, você fatalmente recairá num framework que faça isso para você, ou gastará horas desenvolvendo algo que está fora da lógica de seu negócio, ou correrá o risco. Mas deve-se pensar. Essa minha preocupação é relevante? Preciso mesmo garantir thread-safety nesse sistema? Ele roda em múltiplos class loaders?


Como eu falei. Se meu sistema não roda em múltiplas threads, não tem vários class loaders, não faz lazy initialization na classe singleton, não. E muitas vezes, posso preferir conviver com isso e ter erros em tempo de compilação quando a classe dependente faltar, ao invés de recorrer a reflexão e ter erros somente em Runtime. Se meu cliente valorizar um código pequeno, ou estiver rodando num hardware com restrições, também posso preferir conviver com os problemas em prol de um requisito mais importante. Novamente, a "moral da história" aqui não é sobre singletons, mas sobre trade-offs.


pcalcado wrote:
Se alguém no GUJ entra perguntando se a tecnologia utilizada em Java para criar aplicações desktop é EJB ou Swing o que você responderia? E se após ser informado que deve buscar por Swing ele avisa que na verdade ele já tem a tela em Delphi e quer algo que fique residente na máquina do usuário e seja acessado pelo Delphi em CORBA?

Casos de exceção sempre vão acontecer e para estes casos espera-se que o desenvolvedor conheça um mínimo de opções. O problema é nivelar pela exceção.

No caso de gerenciamento de dependências em específico eu realmente nunca ouvi nenhum argumento que faça um Singleton ser mais interessante que uma Factory que retorna o mesmo objeto.


Mas é exatamente disso que estou falando: conhecer o domínio do problema. Aqui no GUJ, já vi muita gente criticar o Singleton sem nem mesmo saber do que se tratava a aplicação em questão. Simplesmente postam algo vago como "não use singleton, use depency injection que é melhor". Por que? Talvez porque tenham lido isso em algum lugar, ou por que seja a propaganda que o framework dele esteja fazendo.

E não porque identificou uma situação (como a do colega deste post) onde havia uma solução mais adequada. E aqui, não estou falando exclusivamente do Singleton, mas de qualquer pattern.
[WWW]
 
Índice dos Fóruns » Arquitetura de Sistemas
Ir para:   
Powered by JForum 2.1.8 © JForum Team