Eu li e tal, concordei e entendi os motivos pelos quais o autor sugere diminuir os getters e setters da aplicação, o que eu não entendi muito bem é como fazer isso
Alguém poderia me dar alguma dica de como evitar getters e setters?
1- Passar todos os valores das variaveis por um construtor
ou
2- deixar as variáveis como public
Eu acho que é isso…
sahusahu[/quote]
Aí é que está! Se você define métodos get/set para cada variável da sua classe, na prática acaba virando a mesma coisa que torna-lás públicas! O ideal é que o usuário de uma classe não faça nem idéia dos atributos private de uma classe, ao invés disso ele deve se concentrar no comportamento e na interface oferecida pela classe.
na real, nao pude ler o artigo, pois aqui no trampo é bloqueado ¬¬
asaushashhus
ai só levei em consideracao o que ele falou no post…
mas qdo chegar em casa vou ler sim, parece interessante!
Eu li e tal, concordei e entendi os motivos pelos quais o autor sugere diminuir os getters e setters da aplicação, o que eu não entendi muito bem é como fazer isso
Alguém poderia me dar alguma dica de como evitar getters e setters?
[/quote]
Releia esta parte:
O texto não diz que acessores/modificadores são maus, o que ele diz é que violar o encapsulamento é mau.
Existe uma diferença ? Sim! E é essa diferença que vc precisa enxergar antes de perguntar como resolver o problema. O autor já lhe explica como resolver o problema.
Porque usamos acessores (getter) e modificadores (setters)?
Porque queremos isolar os atributos da classe. Não queremos que eles sejam manipulados diretamente.
Usar get/set evita que alguem manipule os dados ? Não. E esse é o problema. Vc colocou um camada à volta do atributo, mas não o isolou. O objeto externo continua podendo fazer o mesmo que fazia antes - alterar e ler qualquer atributo à vontade. Ele apenas o faz de uma forma diferente.
O mal está ai, em deixar o objeto externo controlar o estado dos atributos internos, mesmo que indiretamente.
É isso que é necessário evitar.
É obvio - o próprio autor fala disso - que em certas circunstâncias você é obrigado a ler/escreve o estado do objeto ( UI e JDBC)
Mas isso são exceções , não a regra.
Pode crer cara, eu entendi essa parte. Mas assim, não sei se tú ou algum dos colegas aqui do fórum compartilham da minha opnião, mas salvo raras excessões, getters e setters violam o encapsulamento (pelo menos ao meu ver) :?
Principalmente porque fica complicado manter a autonomia que os objetos devem ter sobre o gerenciamento de seus estados. Já que um objeto A poderia alterar o valor de um atributo do objeto B (no caso de utilização de um setter).
Talvez eu tenha aprendido OO de forma incorreta, mas a questão é que é ligeiramente difícil pra mim conseguir “enxergar” formas de manter um design mais OO - pelo menos eu acho.
Lendo alguns desses artigos na internet eu acabei ficando inseguro com relação a práticas que eu adotava no passado e que ao meu ver eram corretas.
Concordo com o teu ponto de vista, no entanto esse é um dos outros pontos que me causam confusão…
Eu aprendi patterns tipo Façade ou Controller encapsulam regras de negócio, manipulam POJOS, delegam funções… Só que analisando melhor, acredito que eles vão contra alguns conceitos de OO - ou pelo menos a forma que eu os utilizo - porque objetos não devem ter autonomia sobre o seu estado? não devem apenas receber mensagens? Então, esses patterns acabam tirando a autonomia, e transformando objetos em objetos fantoches, ou eu estou enganado?
Primeiro temos que separar dois tipos de objetos : de dados e “os outros”. Os objetos de dados (OD para encurtar)
têm que ser carregados com os dados, certo ? não tem como fugir disso. Mas o “tem que carregar dados” é diferente de objeto tem que fornecer interface para isso. Por exemplo poderíamos usar o construtor, ou como o autor do artigo sugere ; reflection.
Mas isso seria matar uma mosca com um canhão. Os OD têm que existir e tem o seu papel ( por exemplo o padrão Memento usa algo assim). Aliás o próprio conceito de Serializable é um pouco OD.
Os outros objetos têm um estado, mas às vezes nem é um estado é uma configuração. Por exemplo a injeção de um service num outro service da vida. Isso não se qualifica como problema. Eu estou apenas canalizando as dependências.
O problema ocorre quando um objeto não controla o seu estado, quando outros objetos ficam constantemente pedindo informações e alterado informações dele. Se ele é um OD, isso não tem problema a principio.
O passo possibel é tvl imutabilizar os objetos, i.e. tirar os modificadores. Assim, mesmo que tenhamos 30 gets não ha problema, não ha violação do encaspulamento. Se tivermos que mudar alguma coisa, mude-se usando um método. A classe String é um otimo exemplo disto.
Outra opção seria criar um objeto apenas com atributos private e não criar nem get nem set para esses atributos.
Apenas quando um outro objeto necessitasse muito dessa informação poderiamos analizar como a fornecer. se por um get, ou se por um método que recebe um parametro e cospe um resultado. Inverter a responsabilidade um pouco. Desconfiar que coisas to tipo “dê-seus-dados-para-eu-fazer-algo”. Ou seja, ser critico com o design e o modelo. Que é o que o autor quer dizer com “not program blindly”. Não programar às cegas. Não usar funções do ecplise como “cria get/set automaticamente” etc…
são pequenas coisas, pequenas práticas, e não ha receita universal.
Nem sempre. Digamos que haja um objeto imutável com uma operação public double getSome() e por qualquer motivo interno à classe este atributo tenha que passar a ser implementado com BigInteger, para continuar tendo o get teríamos que alterar a interface da classe. Ou seja, uma mudança na implementação da classe causou uma mudança em sua interface pública. Quebra de encapsulamento.
[editado]
Por sinal, gosto muito dos artigos do Holub. Ele é bastante radical em alguns pontos e isto ajuda a ampliar os horizontes.Colei uma frase dele na parede da sala onde trabalho:
Acho que o Sergio Taborda ja deixou bem claro: o problema é a quebra de encapsulamento. Nao é para nunca usar, mas tome cuidado para eles nao virarem FANTOCHES na mao dos outros objetos e servirem apenas como estruturinha de dados.
Eu escrevi um artigo sobre esse assunto:
Tambem concordo com o Sergio sobre a imutabilidade: classes imutaveis sao simples, faceis de dar manutencao, thread safe e elegantes. Santo Bloch ja dizia faz tempo…
Nem sempre. Digamos que haja um objeto imutável com uma operação public double getSome() e por qualquer motivo interno à classe este atributo tenha que passar a ser implementado com BigInteger, para continuar tendo o get teríamos que alterar a interface da classe. Ou seja, uma mudança na implementação da classe causou uma mudança em sua interface pública. Quebra de encapsulamento.
[/quote]
Esse é exactamente o tipo de pensamento que destroi o encapsulamento. Se a sua classe passou a ser implementado com BigDecimal não tem porque mudar o retorno do método.
Se vc se enganou ao criar um método com double que deveria ter a exatidão de BigDecimal e ainda vai a tempo de alterar faça um simples refractoring da classe. Se a classe já está em produção marque o método como deprecated, explique que ele não têm a exatidão necessária e que o método getSomeBigger deve ser usado em vez. Explique que o método getSome será retirado da API na versão x.y.z. O método getSomeBigger é um método novo. O método getSome permanece inalterado.
[quote=sergiotaborda]Esse é exactamente o tipo de pensamento que destroi o encapsulamento. Se a sua classe passou a ser implementado com BigDecimal não tem porque mudar o retorno do método.
Se vc se enganou ao criar um método com double que deveria ter a exatidão de BigDecimal e ainda vai a tempo de alterar faça um simples refractoring da classe. Se a classe já está em produção marque o método como deprecated, explique que ele não têm a exatidão necessária e que o método getSomeBigger deve ser usado em vez. Explique que o método getSome será retirado da API na versão x.y.z. O método getSomeBigger é um método novo. O método getSome permanece inalterado.
[/quote]
Este “tipo de pensamento” - e vejo que os ânimos andam meio exaltados por este fórum - foi apenas um exemplo de que assumir de modo naïve que basta ter um objeto imutável e está tudo encapsulado pode não ser bem assim. Quanto ao recurso do deprecated, sim, é uma boa solução para a questão. Mas a solução final para este tipo de problema - se exatidão numérica for importante para o modelo - é um pattern como o Money do PoEAA.
Infelizmente somos obrigados a colocar getters e setters nas nossas classes somente para satisfazer algum framework MVC que se utiliza da especificação JavaBeans. Porém não é só porque temos estes métodos que devemos utiliza-los quando estivermos trabalhando na camada de negócios.
Mas enfim, alguém conhece algum framework MVC que não te obrigue a utilizar getters e setters? Eu particularmente desconheço.
Abraços.
Se vc se enganou ao criar um método com double que deveria ter a exatidão de BigDecimal e ainda vai a tempo de alterar faça um simples refractoring da classe. Se a classe já está em produção marque o método como deprecated, explique que ele não têm a exatidão necessária e que o método getSomeBigger deve ser usado em vez. Explique que o método getSome será retirado da API na versão x.y.z. O método getSomeBigger é um método novo. O método getSome permanece inalterado.
[/quote][/quote]
Me corrigam se eu estiver errado, mas para resolver isso você poderia usar um pattern do GOF chamado Adapter que tem outro exemplo de implementação em java aqui
Se esse era o seu ponto, o seu exemplo não o demonstra. Não ha nenhuma intenção secundária nas minhas palavras. Quando a forma interna dos objetos muda o seu exterior não muda e vice versa. Isso é encapsulamento. O seu exemplo parecia apresentar que quando o interior muda o exterior tb muda. E isso é anti-encapsulamento: a ideia que se o interior muda o exterior tb muda. É isso que o artigo chama a atenção que é um erro.
[quote]
Quanto ao recurso do deprecated, sim, é uma boa solução para a questão. Mas a solução final para este tipo de problema - se exatidão numérica for importante para o modelo - é um pattern como o Money do PoEAA.[/quote]
Money é um objeto imutável. Se o seu ponto é que a imutabilidade não resolve o problema, mas a sua solução é usar um padrão de objeto imutável … alguma coisa não faz sentido. Afinal imutabilidade é ajuda ou não a tornar o estado do mais encapsulado ?
(nota :Quando me referi a exatidão me referia a double versus BigDecimal, e não em relação a dinheiro. O seu exemplo não falada nada sobre dinheiro)
Eu citei o Money como um exemplo de se encapsular um valor numérico e não ter problemas com alterações na representação interna, para as quais o recurso de deprecated é um paliativo. Porém, relendo o thread, meu primeiro post foi bastante truncado mesmo.
Meu ponto é que não basta. Dai o “nem sempre” no meu primeiro post. Não é qualquer imutabilidade que resolve o problema, mas sim algo mais “sistemático” como o Money.
[edit: o Money, no caso, é tão-somente um exemplo, não tem mesmo nada a ver com dinheiro]
Se vc se enganou ao criar um método com double que deveria ter a exatidão de BigDecimal e ainda vai a tempo de alterar faça um simples refractoring da classe. Se a classe já está em produção marque o método como deprecated, explique que ele não têm a exatidão necessária e que o método getSomeBigger deve ser usado em vez. Explique que o método getSome será retirado da API na versão x.y.z. O método getSomeBigger é um método novo. O método getSome permanece inalterado.
[/quote][/quote]
Me corrigam se eu estiver errado, mas para resolver isso você poderia usar um pattern do GOF chamado Adapter que tem outro exemplo de implementação em java aqui [/quote]