Programar para a interface

10 respostas
giselezr

Bom dia

Sempre me deparo com essa frase “Programar para a interface e não para a implementação”, não entendo ao certo. Seria +/- isso: List teste = new ArrayList(), programar para a interface para ter flexibilidade de código? vi topicos relacionadas a herança, polimorfismo, etc. Sera que alguem pode me explicar?

abraço

10 Respostas

nel

giselezr:
Bom dia

Sempre me deparo com essa frase “Programar para a interface e não para a implementação”, não entendo ao certo. Seria +/- isso: List teste = new ArrayList(), programar para a interface para ter flexibilidade de código? vi topicos relacionadas a herança, polimorfismo, etc. Sera que alguem pode me explicar?

abraço

Oi Gisele.

O significado disso é basicamente que a declaração de seus métodos devem ser focados em interfaces e não em classes, pois oferece uma flexibilidade muito maior.
Imagine a Interface List, ela possui, facilmente, 10 classes que a implementam. Vamos imaginar que você simples declare um método assim:

public ArraList<Integer> findAllCodes();

Ok. A principio, você só vai precisar responder com um ArrayList e mais nada. Vamos supor que daqui um mês, surge a necessidade de alterar de ArrayList para LinkedList, e agora?
Temos um problema. Você terá que buscar em todo o seu código as referências para este método e alterar o retorno em cada linha. Pense em um sistema com muitas chamadas, todo o retrabalho envolvido e etc. Isso é apenas um exemplo simples.

Se ali estivesse declarado como um List e você alterar o retorno para um LinkedList, qual o problema? 0, nenhum. Simplesmente porque está trabalhando com a interface e não sua respectiva implementação. O que você precisa é dos códigos e não saber se será um LinkedList, ArrayList ou qualquer outra. É um exemplo simples, mas espero ter clareado a ideia.

Abraços.

arthurgon

Dá uma lida nesse texto. Vai te ajudar a entender.

http://www.brasiltech.net/agilez/2009/08/09/como-programar-para-uma-interface-e-nao-para-uma-implementacao/

douglaskd

é bem complexo…

mais vc precisa se ater a teoria

imagine por exemplo, que algumas classes com alguns métodos criadas por outros programadores. ex (List getFuncionarios() )

então você começa a desenvolver um sistema, a parte onde mostra os resultados na tela…

vamos supor que há uma outra classe encapsulada que mostra esses resultados…ex: ListarFuncionarios()

você esta lá desenvolvendo o sistema, por questões de performance vai ser necessário enviar/receber tipos váriados de listas, se você for converter essas listas para um formato especifico vai piorar ainda mais.

usando as interfaces, você envia um tipo “genérico” de dados e recebe um tipo “genérico” de dados…, mais deve-se usar com cautela =)

outro exemplo: vamos dizer que eu quero criar uma classe PDF e um método gerarPDF();

dentro desse método ele tem que diferenciar se é DOC, XSL, HTML etc…

eu quero usar o método assim gerarPDF (arquivoASerGerado), e não assim gerarPDF(ArquivoASerGerado, DOC)…Interfaces…

Resumindo Grotescamente: "Você tem que deixar seus método mais reutilizaveis, sem que precisem serem alterados, e que sejam mais faceis de serem usados na hora de mostrar na tela, reduzindo aclopamento…se você mudar o tipo de retorno la na tela, seu código continua funcionando, porque o método se “adapta”.

também gostaria de saber se eu estou totalmente certo sobre o que disse acima…

Alexandre_Saudate

douglaskd:
é bem complexo…

mais vc precisa se ater a teoria

imagine por exemplo, que algumas classes com alguns métodos criadas por outros programadores. ex (List getFuncionarios() )

então você começa a desenvolver um sistema, a parte onde mostra os resultados na tela…

vamos supor que há uma outra classe encapsulada que mostra esses resultados…ex: ListarFuncionarios()

você esta lá desenvolvendo o sistema, por questões de performance vai ser necessário enviar/receber tipos váriados de listas, se você for converter essas listas para um formato especifico vai piorar ainda mais.

usando as interfaces, você envia um tipo “genérico” de dados e recebe um tipo “genérico” de dados…, mais deve-se usar com cautela =)

outro exemplo: vamos dizer que eu quero criar uma classe PDF e um método gerarPDF();

dentro desse método ele tem que diferenciar se é DOC, XSL, HTML etc…

eu quero usar o método assim gerarPDF (arquivoASerGerado), e não assim gerarPDF(ArquivoASerGerado, DOC)…Interfaces…

Resumindo Grotescamente: "Você tem que deixar seus método mais reutilizaveis, sem que precisem serem alterados, e que sejam mais faceis de serem usados na hora de mostrar na tela, reduzindo aclopamento…se você mudar o tipo de retorno la na tela, seu código continua funcionando, porque o método se “adapta”.

também gostaria de saber se eu estou totalmente certo sobre o que disse acima…

Em vários sistemas que já fiz, tive a necessidade de criar conversores de dados. Então, criei uma interface:

public interface Transformer {

public <T> T from (String source) throws TransformerException;

public <T> String to(T source) throws TransformerException;

}

E as implementações:

public class JSONTransformer implements Transformer {
// métodos...
}


public class XMLTransformer implements Transformer {
// métodos...
}

Cada vez que vou usar uma dessas interfaces, eu referencio somente o transformer:

public class Service {

private Transformer transformer;


public Service(Transformer transformer) {
this.transformer = transformer;
}


public void doSomething() throws TransformerException{
 MyObject myObject = new MyObject();
 String myObjectAsString = transformer.to(myObject);
 MyObject newMyObject = transformer.from(myObjectAsString);

}
}

Ou seja… na classe Service, a qualquer momento eu posso mudar a transformação de dados de XML para String, sem precisar alterar uma única linha de código (isso porque, além de tudo, eu usei injeção de dependências - no caso, a dependência é o transformer).

Isso cria uma flexibilidade incrível, porque, se eu precisar modificar o tipo de dado gerado, eu só preciso injetar um transformador compatível com o novo tipo de dado. Por exemplo, se eu quiser criar um CSV, basta criar uma classe que implemente Transformer e injetar essa classe na minha classe Service.

[]'s

R

Ok galera, na verdade eu sempre encontro na internet discussões sobre o tema e a maioria das pessoas explicam o assunto programar para interface referenciando a API Collections como foi feito aqui.
Uma dúvida que eu tenho e que não encontrei citações claras nas buscas que fiz diz respeito a utilizar este conceito de programar para interface com objetos que serão persistidos no banco de dados.

Ex:
Vamos supor que eu tenho um sistema para controlar os atendimentos feitos aos pacientes de uma clínica. O diagrama de classes bem simplificado é como o ilustrado na figura do link abaixo:

https://picasaweb.google.com/117697736991283756484/16DeAgostoDe201202?authuser=0&feat=directlink#5777380672568240498

Se eu tenho que programar para interface, como faço o relacionamento destes objetos acontecerem de tal modo que eu possa mapeá-los no banco de dados utilizando hibernate por exemplo? Vamos supor que os objetos Paciente, Profissional e Atendimento serão respectivamente mapeados para as tabelas PACIENTE, PROFISSIONAL e ATENDIMENTO.
Ressalvo que não estou procurando código fonte para fazer tal mapeamento no hibernate, minha intenção mesmo é entender como aplicar este conceito de programar para interface nessa questão de relacionamento com banco de dados. Mesmo assim fiquem a vontade caso achem necessário mover este post para outra seção.

Não sei se consegui ser claro na minha pergunta, mas qualquer coisa terei prazer em repostá-la.
Obrigado.

almircampos

arthurgon:
Dá uma lida nesse texto. Vai te ajudar a entender.

http://www.brasiltech.net/agilez/2009/08/09/como-programar-para-uma-interface-e-nao-para-uma-implementacao/

Oi, arturgon.

Ao clicar no link indicado, aparece o seguinte erro:

[i]Warning: require(./portal/wp-blog-header.php) [function.require]: failed to open stream: No such file or directory in /home/brasiltech/brasiltech.net/index.php on line 17

Fatal error: require() [function.require]: Failed opening required ‘./portal/wp-blog-header.php’ (include_path=’.:/usr/local/lib/php:/usr/local/php5/lib/pear’) in /home/brasiltech/brasiltech.net/index.php on line 17
[/i]
Sds,
Almir.

Alexandre_Saudate

rafaelmranieri:
Ok galera, na verdade eu sempre encontro na internet discussões sobre o tema e a maioria das pessoas explicam o assunto programar para interface referenciando a API Collections como foi feito aqui.
Uma dúvida que eu tenho e que não encontrei citações claras nas buscas que fiz diz respeito a utilizar este conceito de programar para interface com objetos que serão persistidos no banco de dados.

Ex:
Vamos supor que eu tenho um sistema para controlar os atendimentos feitos aos pacientes de uma clínica. O diagrama de classes bem simplificado é como o ilustrado na figura do link abaixo:

https://picasaweb.google.com/117697736991283756484/16DeAgostoDe201202?authuser=0&feat=directlink#5777380672568240498

Se eu tenho que programar para interface, como faço o relacionamento destes objetos acontecerem de tal modo que eu possa mapeá-los no banco de dados utilizando hibernate por exemplo? Vamos supor que os objetos Paciente, Profissional e Atendimento serão respectivamente mapeados para as tabelas PACIENTE, PROFISSIONAL e ATENDIMENTO.
Ressalvo que não estou procurando código fonte para fazer tal mapeamento no hibernate, minha intenção mesmo é entender como aplicar este conceito de programar para interface nessa questão de relacionamento com banco de dados. Mesmo assim fiquem a vontade caso achem necessário mover este post para outra seção.

Não sei se consegui ser claro na minha pergunta, mas qualquer coisa terei prazer em repostá-la.
Obrigado.

Nessa questão, especificamente, não cabe a idéia de programar para interfaces, pelo seguinte:

  1. Incluir interfaces no seu modelo só iria aumentar a complexidade do sistema, sem necessariamente incluir benefícios. Se você criar uma interface “X” e depois criar uma classe “XImpl”, grandes chances de você estar fazendo algo de errado.

  2. O Hibernate não suportaria interfaces de outras classes, e iria reclamar… muito trabalho para pouco benefício.

Perceba que a idéia de programar para interfaces se refere a contextos onde faz sentido ter interfaces (não somente interfaces, mas classes abstratas, como é o caso de InputStream, por exemplo). Se você já tem uma interface e algumas implementações, é preferível que você trabalhe com a interface, e não somente com cada implementação (a menos que você precise de comportamentos específicos de implementações).

Não sei se me fiz entender… em linhas gerais, eu quero dizer que você não deve sair introduzindo interfaces no seu sistema sem critérios. Interfaces são boas para responder a diversas necessidades parecidas, mas perceba que não fazem sentido se você não tiver diversas necessidades, mas apenas uma só. Isso é percebidamente o caso em 99,999999% dos modelos de domínio.

[]'s

R

rafaelmranieri:
Ok galera, na verdade eu sempre encontro na internet discussões sobre o tema e a maioria das pessoas explicam o assunto programar para interface referenciando a API Collections como foi feito aqui.
Uma dúvida que eu tenho e que não encontrei citações claras nas buscas que fiz diz respeito a utilizar este conceito de programar para interface com objetos que serão persistidos no banco de dados.

Ex:
Vamos supor que eu tenho um sistema para controlar os atendimentos feitos aos pacientes de uma clínica. O diagrama de classes bem simplificado é como o ilustrado na figura do link abaixo:

https://picasaweb.google.com/117697736991283756484/16DeAgostoDe201202?authuser=0&feat=directlink#5777380672568240498

Se eu tenho que programar para interface, como faço o relacionamento destes objetos acontecerem de tal modo que eu possa mapeá-los no banco de dados utilizando hibernate por exemplo? Vamos supor que os objetos Paciente, Profissional e Atendimento serão respectivamente mapeados para as tabelas PACIENTE, PROFISSIONAL e ATENDIMENTO.
Ressalvo que não estou procurando código fonte para fazer tal mapeamento no hibernate, minha intenção mesmo é entender como aplicar este conceito de programar para interface nessa questão de relacionamento com banco de dados. Mesmo assim fiquem a vontade caso achem necessário mover este post para outra seção.

Não sei se consegui ser claro na minha pergunta, mas qualquer coisa terei prazer em repostá-la.
Obrigado.

asaudate:

Nessa questão, especificamente, não cabe a idéia de programar para interfaces, pelo seguinte:

  1. Incluir interfaces no seu modelo só iria aumentar a complexidade do sistema, sem necessariamente incluir benefícios. Se você criar uma interface “X” e depois criar uma classe “XImpl”, grandes chances de você estar fazendo algo de errado.

  2. O Hibernate não suportaria interfaces de outras classes, e iria reclamar… muito trabalho para pouco benefício.

Perceba que a idéia de programar para interfaces se refere a contextos onde faz sentido ter interfaces (não somente interfaces, mas classes abstratas, como é o caso de InputStream, por exemplo). Se você já tem uma interface e algumas implementações, é preferível que você trabalhe com a interface, e não somente com cada implementação (a menos que você precise de comportamentos específicos de implementações).

Não sei se me fiz entender… em linhas gerais, eu quero dizer que você não deve sair introduzindo interfaces no seu sistema sem critérios. Interfaces são boas para responder a diversas necessidades parecidas, mas perceba que não fazem sentido se você não tiver diversas necessidades, mas apenas uma só. Isso é percebidamente o caso em 99,999999% dos modelos de domínio.

[]'s

asaudate, muito obrigado pelo feedbak.
Essa sua resposta vai ao encontro daquilo que eu penso a respeito do assunto.
Perguntei para ver a opinião de outras pessoas a cerca desta questão e saber se apenas eu pensava assim (pelo visto não) =)

Valeu.

sergiotaborda

rafaelmranieri:
Ok galera, na verdade eu sempre encontro na internet discussões sobre o tema e a maioria das pessoas explicam o assunto programar para interface referenciando a API Collections como foi feito aqui.
Uma dúvida que eu tenho e que não encontrei citações claras nas buscas que fiz diz respeito a utilizar este conceito de programar para interface com objetos que serão persistidos no banco de dados.

Simplesmente não se aplica.
As entidades são objetos muito especificos. Aliás , são os mais especificos que vc pode imaginar. Portanto, não faz sentido abstrai-los usando interfaces. Classes abstratas ainda vai, mas interfaces não.
Nesse caso as interfaces podem fornecer suporte a conceitos que várias entidades possuem. Um exemplo é quando a entidade tem conhecimento do usuário que a criou e a data de criação. Neste caso uma interface Auditable pode ajudar a simplificar o codigo em alguns pontos ( onde saber que o objeto é Auditable é suficiente).

A API de collections é uma das mais bem desenhadas da API Java , que envolve vários conhecimentos, praticas, padrões, etc… e por isso é dada como exemplo. No geral é bom modelar usando interfaces, como elas se relacionam , etc… e só depois partir para a concretização ( o inverso de abstração). Mas em entidades, isto simplesmente não faz muto sentido. Mas veja, é possivel, construções - não triviais - podem ser feitas para usar esse mecanismo, mas na prática não rola porque normalmente vc irá usar ferramentas como o hibernate que exigem o uso do padrão bean.

sergiotaborda

giselezr:
Bom dia

Sempre me deparo com essa frase “Programar para a interface e não para a implementação”, não entendo ao certo. Seria +/- isso: List teste = new ArrayList(), programar para a interface para ter flexibilidade de código? vi topicos relacionadas a herança, polimorfismo, etc. Sera que alguem pode me explicar?

A frase “Programar para a interface e não para a implementação” deve entender-se como “Programar para o contrato e não para a implementação”.
A diretiva não se relaciona ao conceito java de interface, e sim ao conceito de OO chamado contrato. A interface java é a mais simples forma de definir um contrato, mas não a única.

Muito simplesmente isto significa que ao pensar em objetos ha que pensar primeiro como eles se comportam e como interagem com outros objetos e nunca em como implementar em codigo esses comportamentos. Isto permite desacoplar o design da implementação.

Porque o contrato é algo relacionado ao comportamento isso gera práticas na programação.
Na prática, em java, tudo se resume a usar corretamente o polimorfismo que o java oferece.
Utilizar variáveis o mais polimorficas possivel ( ou seja, usar a interface na declaração de variáveis e parametros), não usar static e ter cuidado com o uso de herança.
Mas isso é como o conceito se traduz em java, e não o que o conceito é.

O conceito de “Programar para o contrato e não para a implementação” é uma diretiva de design OO, não de programação.

Criado 10 de janeiro de 2012
Ultima resposta 16 de ago. de 2012
Respostas 10
Participantes 8