Variavel global, mas bem global :P

28 respostas
M

Bom, programo em java já a algum tempo, mas nunca parei pra pensar neste problema em particular
tenho uma classe A onde existe uma variavel
a classe A é instanciada e utilizada em B
porém necessito fazer consulta à tal variavel na classe C
mas aí que está. não posso fazer a var static e instanciar a classe de novo, pq ela é runnable, thread, e nao pára, só pode haver uma execução da mesma

uma soluçao que pensei é manter esta tal variavel fora destas classes e transforma-la em uma variavel acessivel a todas as classes

qual é o jeito elegante de fazer isso?

obrigado

28 Respostas

pablosaraiva

Variável global nunca é elegante.

Mas o melhor jeito de fazer é implementar um Singleton.

M

entendo, pesquisei por este padrão singleton que vc disse, porem nao entendo como devo proceder, como instancio a classe pela primeira vez
se ele diz que o metodo eh privado…

pablosaraiva

O construtor é privado, mas você vai ter um método público que vai sempre retornar a mesma instância do Singleton pra você.

Assim:

public class MeuSingleton {
	private static MeuSingleton meuSingleton = new MeuSingleton();
	
	private MeuSingleton() {
		
	}

	public static MeuSingleton getInstance() {
		return meuSingleton;
	}

}

Repare no seguinte. A classe possui uma instância do Singleton. Como o construtor é privado, a classe conseguiu instanciar, mas você não consegue fazer isso de fora.

O método público getInstance() vai te retornar sempre a mesma instância do seu Singleton.

M

poxa que maravilha
haha

muito obrigado ai eh isso mesmo que eu queria… heheheh valeu!

porem, isso nao é uma especie de gambiarra? :stuck_out_tongue:

pablosaraiva

É um padrão de projeto bem conhecido.

Se torna gambiarra se for feito mal uso dele, mas existem casos em que ele é bem aplicado.

Repare que editei o post acima e tornei o método getInstance() static.

M

ah bom, então ta show, pois é eu achei um exemplo tb que usa um tal de “synchronized” aí deixei tbm…
acho que neste caso essa solução eh a melhor mesmo, pois tem mesmas as caracteristicas
valeuu aí cara

pablosaraiva

synchronized você vai usar apenas se a sua aplicação foi multi-thread.

Você marca os recursos compartilhados como synchronized e o java não permite que duas threads acessem simultaneamente o conteúdo.

maior_abandonado

o mais indicado é deixar o metodo sincronizado mesmo… é uma garantia a mais que só terá uma unica instancia (objetivo do singleton…)

ViniGodoy

pablosaraiva:
Variável global nunca é elegante.

Mas o melhor jeito de fazer é implementar um Singleton.

Na verdade, essa foi uma péssima sugestão. Você efetivamente está dizendo para ele criar um Singleton para ser usado como variável global, e esse não é propósito do Singleton. É um exemplo de uso errado do padrão.

Existem três coisas distintas:

a) A thread;

b) O runnable, que é o trecho da código onde a thread inicia;

c) O executor da thread (classe Thread).

Seu runnable continuará com os valores definidos, mesmo que a thread tenha terminado sua execução. Se você explicar melhor o que cada classe faz, talvez seja possível chegar a uma solução melhor. Mas algumas alternativas podem ser:

  1. Usar um trecho sincronizado na classe C. Isso é interessante se a thread ainda estiver rodando sobre o Runnable. Trechos sincronizados reduzem o paralelismo, mas podem ser adequados em diversas situações;
  2. Usar o próprio Runnable, desde que a thread já tenha terminado. Você pode fazer isso criando um método get() do valor em C, com uma instrução join() logo no início. Assim, quem chamar o método será obrigado a esperar a thread terminar, antes de obter o valor em C. Outra alternativa é transformar C num Future;
  3. Fazer C copiar o valor para um objeto qualquer, e fazer com que B leia desse objeto. Cópias de dados são boas alternativas usando threads pois elas maximizam o paralelismo.

Tudo vai depender de como seu programa esteja organizado.

pablosaraiva

ViniGodoy:
pablosaraiva:
Variável global nunca é elegante.

Mas o melhor jeito de fazer é implementar um Singleton.

Na verdade, essa foi uma péssima sugestão. Você efetivamente está dizendo para ele criar um Singleton para ser usado como variável global, e esse não é propósito do Singleton. É um exemplo de uso errado do padrão.

Eu comecei dizendo que usar variável global nunca é elegante. Na sequencia, mostrei como fazer.

Concordo que conhecendo o problema dele, pode-se sugerir soluções mais apropriadas.

ViniGodoy

pablosaraiva:

Eu comecei dizendo que usar variável global nunca é elegante. Na sequencia, mostrei como fazer.

Concordo que conhecendo o problema dele, pode-se sugerir soluções mais apropriadas.

O que estou dizendo é que usar o Singleton não é uma solução. O Singleton deve ser usado quando sua classe representa um recurso único, não quando você precisa disfarçar um global. Existem muitas discussões sobre isso no GUJ, por isso não vou me estender mais no assunto, quem tiver curiosidade pode ler:
http://www.guj.com.br/posts/list/62048.java ou
http://www.guj.com.br/posts/list/91240.java ou ainda
http://www.guj.com.br/posts/list/142721.java

M

pablosaraiva:
ViniGodoy:
pablosaraiva:
Variável global nunca é elegante.

Mas o melhor jeito de fazer é implementar um Singleton.

Na verdade, essa foi uma péssima sugestão. Você efetivamente está dizendo para ele criar um Singleton para ser usado como variável global, e esse não é propósito do Singleton. É um exemplo de uso errado do padrão.

Eu comecei dizendo que usar variável global nunca é elegante. Na sequencia, mostrei como fazer.

Concordo que conhecendo o problema dele, pode-se sugerir soluções mais apropriadas.

pablosaraiva:
Variável global nunca é elegante.

Mas o melhor jeito de fazer é implementar um Singleton.

Decida-se.

pablosaraiva

marcio_gs,

Eu estava decidido.

Disse que não é elegante ter variáveis globais e que caso o cara realmente queira fazer isso, que um Singleton seria uma boa escolha.

Obviamente o Vini e outros discordam.

Acredito então que quem estiver interessado no assunto deve realmente ler o link que o Vini postou para outros posts.

In Vini we Trust. :slight_smile:

ViniGodoy

Na verdade, existem soluções melhores para o problema, e era elas que eu queria discutir. Por isso o colega deve postar algum código, e dar mais exemplos do que quer fazer. Se formos falar de singleton, teremos outro post longo, como os dos links que postei.

M

pablosaraiva:
marcio_gs,

Eu estava decidido.

Disse que não é elegante ter variáveis globais e que caso o cara realmente queira fazer isso, que um Singleton seria uma boa escolha.

Obviamente o Vini e outros discordam.

Acredito então que quem estiver interessado no assunto deve realmente ler o link que o Vini postou para outros posts.

Entendi diferente. Meu erro então =)


In Vini we Trust. :)

É, realmente a educação e inteligência do ViniGodoy fazem suas respostas terem bastante crédito.

lina

pablosaraiva:
Variável global nunca é elegante.

Oi,

Uma dúvida: Pq utilizar uma variavel global nunca é elegante? :wink:

Tchauzin!

ViniGodoy

Com o tempo, você começa a perder o controle de que locais ela é alterada. E isso torna o sistema muito complicado de se manter.

É diferente no entanto de se ter constantes globais. Constantes são plenamente válidas.

ViniGodoy

marcio_gs:
pablosaraiva:

In Vini we Trust. :)

É, realmente a educação e inteligência do ViniGodoy fazem suas respostas terem bastante crédito.

Opa, valeu pessoal. A gente faz o que pode… :slight_smile:
(podem ver que eu não dou pitaco no fórum de web)

lina

Com o tempo, você começa a perder o controle de que locais ela é alterada. E isso torna o sistema muito complicado de se manter.

É diferente no entanto de se ter constantes globais. Constantes são plenamente válidas.

Oi,

Claro, você poderá perder o controle sobre ela, porém a palavra utilizada: nunca foi um tanto que inadequada.
Se você tem uma classe “pequena” não tem pq não utiliza-la.

Constantes globais (final) é uma coisa totalmente diferente, até porque não é permitido a alteração do seu valor.

Tchauzin!

M

olá caros colegas, vejam bem

há uma classe main que estancia todas as outras classes que são telas ou procedimentos do meu programa

então existe uma classe responsavel de enviar dados coletados para uma das telas que trata dados, então enquanto o programa roda, esta classe está funcionando

a classe main instancia essa classe que vai coletar dados, e essa classe que coleta dados instancia esta classe que trata dados

a classe que trata os dados grava em banco de dados e também manda eles para uma classe instanciada de medidores. onde serão exibidos…

porém essa classe de medidores foi instanciada em Main, e a classe que trata dados mexe nela fazendo isto: Main.telaMedidores.funcao() pois ela é static

poderia eu utilizar então a variavel da classe que coleta dados static e mexer nela desta forma na tela de medidores, onde tenho que alterá-la?

abraços

luistiagos

aproveitando o embalo…
sobre problemas de sincronismo com Singletons
se fizermos isto:

private static final BancoCore INSTANCIA = new BancoCore();

    public static BancoCore getInstancia() {
        return INSTANCIA;
    }

resolve o problema de sincronismo?
ou tem que ser realmente isto:

private static BancoCore INSTANCIA;

    public static synchronized  BancoCore getInstancia() {
        if (INSTANCIA == null)
           INSTANCIA = new BancoCore();
        return INSTANCIA;
    }

pois se for pensar bem… posso estar enganado mais no primeiro codigo usa uma constante ou seja a primeira thread que carregar o objeto vai instanciar e o resto vai pegar a mesma instancia…

á diferença em termos de sincronismo entre estes 2 codigos?

luistiagos

mais alguem?

ViniGodoy

O primeiro código é tão seguro quanto o segundo. Com a diferença de ser mais simples.

gomesrod

Com o tempo, você começa a perder o controle de que locais ela é alterada. E isso torna o sistema muito complicado de se manter.

Para que não pareça uma “baboseira teórica”, um daqueles “Faça assim porque SE UM DIA…”, vou dar meu testemunho!

[i]Em uma empresa onde eu trabalhava há alguns anos, havia um aplicativo em VB que cuidava da criptografia e formatação de mensagens. Essas mensagens eram transmissões de transações financeiras do cliente para outras instituições.

Quem aqui conhece o velho VB (versões anteriores ao .NET) sabe que ele é bastante permissivo e até mesmo incentiva as mais grotescas gambiarras. Uma delas é a declaração e uso de variáveis globais, é facinho facinho. É o jeito utilizado por uma boa parcela dos desenvolvedores para passar informação entre funções ou entre módulos.

Pois bem… um certo diz começou a acontecer um erro na formatação dessas mensagens. O erro era daquele tipo que acontece esporadicamente em Produção e JAMAIS em desenvolvimento. Resultado: Essa situação continuou por meses sem que se descobrisse a causa. E agora é que vem a pior parte, dependendo da transação e do horário em que ocorria o erro, o cliente precisava pagar uma multa que era repassada para a software house (nós), o valor era de R$6.000,00 em cada ocorrência. O prejuízo ao longo desses meses foi enorme!

Depois de muito muito muito (MAS MUITO MESMO! AO QUADRADO) trabalho, descobriu-se a causa: em certas situações era necessário dar um tratamento diferenciado para determinadas mensagens, e como isso era feito? ATIVANDO UMA FLAG GLOBAL antes de tratar essas mensagens específicas. E nas próximas transações, adivinha o que acontecia… esta flag estava ativada e zuava toda a formatação.
Claro que depois de se saber isso o problema foi resolvido rapidamente…[/i]

Moral da história:
#1: Mesmo que sua linguagem permita ou você descubra aqueeele esqueminha fácil, NAO USE VARIAVEIS GLOBAIS! NUNCA! Lembre-se que sempre existem outras alternativas.
#2: Eu não tive culpa nesse caso, na época eu não era desenvolvedor e sim um simples analista de suporte :smiley:

ViniGodoy

Onde eu trabalhava um grupo menos experiente criou uma variável global e importantíssima chamada i. Ocorria direto shadowing com essa variável. E, em alguns módulos, alguns programadores usavam o i no for, achando que a variável global servisse só com um syntax suggar para não ter que ficar redeclarando i…

Ou seja, instabilidade em todo lugar.

pedroroxd

ViniGodoy:
Onde eu trabalhava um grupo menos experiente criou uma variável global e importantíssima chamada i. Ocorria direto shadowing com essa variável. E, em alguns módulos, alguns programadores usavam o i no for, achando que a variável global servisse só com um syntax suggar para não ter que ficar redeclarando i…

Ou seja, instabilidade em todo lugar.


Poco burro O_o
Chamar 1 variável de global de i, bem fácil de diferenciar
¬¬’

lina

Com o tempo, você começa a perder o controle de que locais ela é alterada. E isso torna o sistema muito complicado de se manter.

Para que não pareça uma “baboseira teórica”, um daqueles “Faça assim porque SE UM DIA…”, vou dar meu testemunho!

[i]Em uma empresa onde eu trabalhava há alguns anos, havia um aplicativo em VB que cuidava da criptografia e formatação de mensagens. Essas mensagens eram transmissões de transações financeiras do cliente para outras instituições.

Quem aqui conhece o velho VB (versões anteriores ao .NET) sabe que ele é bastante permissivo e até mesmo incentiva as mais grotescas gambiarras. Uma delas é a declaração e uso de variáveis globais, é facinho facinho. É o jeito utilizado por uma boa parcela dos desenvolvedores para passar informação entre funções ou entre módulos.

Pois bem… um certo diz começou a acontecer um erro na formatação dessas mensagens. O erro era daquele tipo que acontece esporadicamente em Produção e JAMAIS em desenvolvimento. Resultado: Essa situação continuou por meses sem que se descobrisse a causa. E agora é que vem a pior parte, dependendo da transação e do horário em que ocorria o erro, o cliente precisava pagar uma multa que era repassada para a software house (nós), o valor era de R$6.000,00 em cada ocorrência. O prejuízo ao longo desses meses foi enorme!

Depois de muito muito muito (MAS MUITO MESMO! AO QUADRADO) trabalho, descobriu-se a causa: em certas situações era necessário dar um tratamento diferenciado para determinadas mensagens, e como isso era feito? ATIVANDO UMA FLAG GLOBAL antes de tratar essas mensagens específicas. E nas próximas transações, adivinha o que acontecia… esta flag estava ativada e zuava toda a formatação.
Claro que depois de se saber isso o problema foi resolvido rapidamente…[/i]

Moral da história:
#1: Mesmo que sua linguagem permita ou você descubra aqueeele esqueminha fácil, NAO USE VARIAVEIS GLOBAIS! NUNCA! Lembre-se que sempre existem outras alternativas.
#2: Eu não tive culpa nesse caso, na época eu não era desenvolvedor e sim um simples analista de suporte :D



Onde eu trabalhava um grupo menos experiente criou uma variável global e importantíssima chamada i. Ocorria direto shadowing com essa variável. E, em alguns módulos, alguns programadores usavam o i no for, achando que a variável global servisse só com um syntax suggar para não ter que ficar redeclarando i…

Oi,

Tudo na programação envolve estudo.
Dica: Antes de sair programando é necessário ter: Modulação, Estruturas, Desenhos (UML) etc…

Provavelmente o que aconteceu na sua empresa foi realmente um CDPG*. Onde o programador não sabia o que estava fazendo, ou seja, não fez a analise da programação antes de faze-la.

Como eu disse: utilizar uma variavel global em programas/sistemas grandes é muito complicado. Principalmente em sistemas que fazem uso de processamento paralelo ou threads…

O fato disso é essa tal flag!
Você define um valorzinho nela globalmente (Pensando assim: AAAA! quando ela chegar aqui o status dela vai ser esse…) porém como existem outros processos, ela irá chegar com o status diferente do esperado.

E como fazer para encontrar esse problema?! Debugando!!! não!!! pois em debug não acontece…
Pronto. CDPG* completa.

Antes de usar uma variavel global (em sistema grande), deve-se pensar: O que eu posso fazer para evitar essa variavel?? R: Estudar…

*CDPG: Cagada de programador…GRANDE!

Obs: Não preciso nem comentar em relação: Definir variáveis com ‘a’, ‘b’ e ‘i’

Tchauzin!

M

Genial! Tão genial que chega a ser engraçado… :lol:

Criado 17 de dezembro de 2009
Ultima resposta 18 de dez. de 2009
Respostas 28
Participantes 10