Quebra de encapsulamento

Galera, outro dia presenciei a discussa aqui no guj uma discussao sobre quebra de encapsulamento. Exemplo, uma modelagem para um site de vendas de qualquer coisa. Eu teria uma interface IProduto uma implementacao concreta Produto com algumas funcionalidades implementadas e alguma coisa tipo carro que herda de produto. Isso eh quebra de encapsulamento? Compor a classe com a classe produto seria correto? me parece estranho. Alguem tem algo a acrescentar? Queria saber mais sobre isso. Qualquer coisa eh valida.

Alberto

Acho bobagem vc ter uma interface IProduto. Por mim, colocava tudo na classe concreta produto. Afinal, por um acaso vc vai ter várias implementações diferentes da interface produto?
Ou eu estou errado?

Antes de mais anda esqueça essa nomenclatura IProduto, em chama não é padrão utilizar I antes do identificador de uma interface.

Provavelmente você está se referindo a uma discussão apagada no acidente sobre mentawai e VRaptor2.

No caso a discussão era sobre se uma classe filha utilizar atributos protected de uma classe mãe era quebra de encapsulamento. De maneira geral eu responderia não.

A classe superior deve tratar suas classes inferiores como seus clientes e seus membros protected fazem parte da API, devendo ter os mesmos cuidados que membros públicos.

Olá,
tem quem diga que é uma boa prática utilizar interfaces para todas as implementações possíveis, o padrão estrutural Bridge, por exemplo tenta separar esses segmentos (interface da implementação).
Isso IMHO, só seria válido caso você precise de um ‘engine’ ou algum processamento mais abstrato, que boa parte da lógica seria implementada a base de interfaces e não de classes.

Enfim, depende do problema específico colocar ou não uma interface para Produto, e também concordo que esse nome ‘IProduto’ não ficou claro, eu particularmente nomeio as interfaces com palavras que expressam um comportamento, tipo o padrão da sun, …able.

O java sendo uma linguagem O.O. permite que vc utilize a herança, e permite também que você sobreescreva os métodos da classe pai, isso é um conceito O.O., então cabe ao projetista arquitetural da aplicação decidir se o programador vai poder sobrescrever ou não tal método.

os OO mais puristas vao fazer vc criar interfaces para tudo (e ateh concordo nisso) e acessar os objetos somente pela interface (ou seja, nunca saber a implementacao que esta sendo usada no momento)…
mais que isso, os mais puristas vao ainda te falar para nao usar heranca, fazendo classes concretas por composicao e delegates (uma vez, perguntaram ao J.Gosling o que ele mudaria se fizesse o JAVA de novo, e ele disse que tiraria a heranca), mas acho um tanto quanto exagerado essa exigencia…
lembrando ainda que vc deve adaptar as regras a sua realidade (prazo, pessoal capacitado, etc)…

onde vc viu isso ?

[quote=takeshi10]os OO mais puristas vao fazer vc criar interfaces para tudo (e ateh concordo nisso)

mais que isso, os mais puristas vao ainda te falar para nao usar heranca, fazendo classes concretas por composicao e delegates (uma vez, perguntaram ao J.Gosling o que ele mudaria se fizesse o JAVA de novo, e ele disse que tiraria a heranca), mas acho um tanto quanto exagerado essa exigencia…
[/quote]

De quais ‘puristas’ você está falando?

Interfaces têm uso, acesso direto à classe concreta também. Geralmente o que se é recomendado é que se trabalhe com interfaces quando se lida com especificações.

achei nos meus links:
http://www.javaworld.com/javaone01/j1-01-gosling_p.html

procure nos livros como o ‘Effective JAVA’ e ali vc vai encontrar puristas…
tambem acho que, algumas vezes, eh interessante ter acesso as classes concretas, mas mais por simplicidade e facilidade…

Eu acho que desenvolver usando interfaces muito mais facil que o contrario, ainda mais se usarmos mocks e stubs para os vários tipos de testes do sistema.

[quote=takeshi10]achei nos meus links:
http://www.javaworld.com/javaone01/j1-01-gosling_p.html
[/quote]

[quote=takeshi10]procure nos livros como o ‘Effective JAVA’ e ali vc vai encontrar puristas…
tambem acho que, algumas vezes, eh interessante ter acesso as classes concretas, mas mais por simplicidade e facilidade…[/quote]

Nem o Gosling no seu link nem o Effective java falam em:

[quote=takeshi10]os OO mais puristas vao fazer vc criar interfaces para tudo (e ateh concordo nisso) e acessar os objetos somente pela interface (ou seja, nunca saber a implementacao que esta sendo usada no momento)…
[/quote]

E o dia que James Gosling for purista de OO é sinal de que o mundo está acabando :wink:

Como falei existem casos para interfaces e existem casos para implementações.

fala philip…
vc misturou meus dois posts… o primeiro era a entrevista do Gosling q eu tinha dito no post anterior…

agora quanto a acessar somente pela interface, repare q essa eh a maneira pela qual normalmente acessamos as coisas um pouco mais complexas (como as collections)…
eu tinha lido em algum livro (e acho qera no effective java) q, idealmente, deveriamos acessar td somente pela interface, mas no sentido amplo da palavra (e nao somente a interface de java)…
meu livro esta emprestado, mas assim que me devolverem, eu olho melhor para nao falar besteira…

soh para constar, tah no item 34 do livro:
“Refer to objects by their interfaces”

[quote=takeshi10]soh para constar, tah no item 34 do livro:
“Refer to objects by their interfaces”
[/quote]

Acho que você precisa reler este item.

Colando do resumo da Bani:

Está muito bem resumido mas vou colar alguns trechos do livro também:

O que eu quis dizer com isso: Joshua Bloch não diz que você deve usar interfaces apra todos os objetos, dia que trabalhar com interfaces torna seu programa flexível e deve ser feito sempre que fizer sentido.

Existem objetos, como ele cita no livro, que são criados para terem múltiplas implementações. Outras vezes nós lidamos com conceitos que são implementados, não com classes. Nestes dois casos interfaces são ideais.

Phiilp, e vc viria alguma situação em que interfaces não ajudaria ?

ola philip,
por essa passagem, eu entendo que o ideal eh se criar e se utilizar interfaces sempre que possivel, evitando nos casos citados, mas talvez a minha interpretacao esteja equivocada…
porem, leia o trecho:

para mim, me parece que ele sugere a utilizacao de interfaces sempre (embora nao diga explicitamente que se deva criar interfaces, jah que ele fala sobre classes preexistentes)…

Eu já programei usando interfaces para os meus beans.

Eu tinha uma interface Profile e eu fazia algo assim:


public interface Profile extends Persistent {


}

public class DBProfile extends DBBean implements Profile {


}

// carrega um profile do banco:

Profile p = ProfileFactory.getDBProfile();
p.setId(2);
p.load();

Sei lá. Hoje estou achando isso mó loucura. Trabalhoso e chato tb. Eu só parti pra esse lado pois eu tinha meu próprio mecanismo de persistencia para meus beans. Se depois eu mudasse o mecanismo de persistencia, eu não precisaria mexer no código que utilizava meus profiles. Poderia até ter um Profile vindo do banco, outro vindo de um arquivo, etc misturados que não haveria problema. Tudo seria a interface Profile.

Mais sei lá. Acho isso overkill hoje em dia. Melhor usar o bom e velho DAO mesmo com IoC. E fazer os beans concretos mesmo. O que se ganharia fazendo eles como Interface ? Vc dobraria o número de suas classes e ainda teria mais trabalho de manutenção e organização. Teria que criar factories, tb. Não sei se o custo-benefício vale a pena aqui.

O que ele diz (e não quer dizer que esteja absolutamente certo mas Joshua Bloch é uma referência cheia de crdibilidade) é que você deve utilizar interfaces quando disponíveis (e eu acrescento: quando fizerem sentido!). O exemplo dado é bem claro: em vez de usar ArrayList, use List mas para String use String mesmo.

Esse é exatamente o tipo de caso em que não se usa itnerfaces. Objetos de negócio só devem ser manipulados unicamente por interfaces se:

  • Possuem diversas implementações
  • Você está manipulando um conceito, não uma implementação. Ok, vamos a um exemplo simples sobre esse ponto.

(notem que sou ignorante em contabilidade, é apenas um exemplo ilustrativo)

Temos o conceito de MovimentacaoFinanceira no nosso sistema. O que é isso? É uma quantidade de capital que entrou ou saiu da empresa, algo que tem um valor total, uma data, se é entrada ou saída e está relacionado a uma pessoa (emrpesa ou pessoa mesmo). Isso é um conceito abstrato e vamos implementá-lo por uma interface:

interface MovimentacaoFinanceira {
 
 BigDecimal getValorTotal();
 Pessoa getPessoaRelacionada();
 Date getData();
 TipoMovimentação getTipo();
}

Na parte de vendas do sistema, temos a classe Venda que representa uma movimentação financeira. Neste caso é um capital entrando relacionado a um cliente.

class Venda implements MovimentacaoFinanceira {
 //METODOS ESPECIFICOS DESTA CLASSE...

 public BigDecimal getValorTotal(){
    //some o preço de todos os itens vendidos e retorne
 }
 
 public Pessoa getPessoaRelacionada(){ return this.getCliente(); }

 public Date getData(){return this.data;}

 public TipoMovimentação getTipo(){return TipoMovimentação.ENTRADA;}
}

Agora, quando usamos a classe e quando usamos a interface?

Se você está alterando o sistema de vendas, você não tem tanto interesse no conceito de movimentação financeira. Use a classe.

Se você está fazendo o sistema que contabiliza as operações e cospe um relatório contábil, para consolidar tudo você não quer saber se é uma venda, uma devolução, pagamento da conta de luz ou se é despesa de viagem do programador que você mandou para o RioJavaSummit 2006, dia 6 de Maio, no Rio de Janeiro. O que te interessa é que no fim das contas todas estas operações são movimentações financeiras, então você trabalha com a interface.

E porque MovimentaçaoFinanceira é uma interface e não uma classe abstrata?

Porque ela representa um conceito apenas, não uma implementação. A linha entre ambas é sutil e não é toda linguagem que oferece interfaces e classes (em java eu creio que a existência de interfaces como coisas separadas só se deu porque não existe herança múltipla).

Utilize classes abstratas quando você tem uma implementação parcial de um conceito que deve ser extendida. Utilize interfaces quando você tem apenas uma especificação do conceito.

ok talvez eu tenha entendido mal o livro (e sim, ele nao pode ser considerado a verdade absoluta, mas eh um otimo livro de qualquer maneira)…
mas ainda sim, a meu ver, quando ele fala que devemos usar a interface relevante sempre que possivel, quando estamos em fase de desenvolvimento, isso significa sempre (jah que sempre podemos desenvolver as interfaces, certo?)…

concordo em parte com vc, sergio, e o uso citado por vc pode parecer um overkill, mas acho q a flexibilidade oferecida (nesse caso) compensa, mas isso eh apenas a minha humilde opiniao…

Não podemos ser dogmaticos demais.
Conclusão: use Interfaces quando for algum serviço (persistência, por exemplo) e Classes Concretas quando for lógica de negócio. Afinal o mais importante e o que menos deveria mudar é a lógica de negócio.