Uma coisa que ainda não entendi bem: Como interfaces promovem a flexibilidade?

6 respostas
MrDataFlex

Pessoas, não estou falando de polimorfismo, e sim em flexibilidade de código.

Por quê precisamos de tudo baseado em interfaces para criar mais “facilmente” Testes unitários, IoC, etc. ?

Qual vantagem de se ter uma interface e sua implementação, FORA do conceito de polimorfismo ?

Valeu!

6 Respostas

R

:arrow: Flexibilidade em IoC:

Por exemplo você tem a interface UsuarioDAO e injeta a implementação JDBCUsuarioDAO… se um belo dia você injetar a HibernateUsuarioDAO… vai ser transparente pro sistema.

:arrow: Flexibilidade nos testes:

Você tem um objeto que contém as regras de negócio e tem como dependencia, por exemplo, nosso UsuarioDAO… pra testar você pode passar um Mock que implementa UsuarioDAO e injetar no objeto de negócio… assim você testa exatamente sua regra de negócio mas com um mock, não com uma base de dados real (se quiser, claro).

:arrow: Flexibilidade de código:

Segue a mesma linha do exemplo do IoC, você pode mudar todo um layer que isso vai ser invisível para os outos (se estiver bem projetado)

E o polimorfimso, por mais que pareca só um conceito, engloba uma série de outros itens como reutilização de código, coesão, etc etc…

Bom, acho que é ± isso.

[]´s

sergiotaborda

MrDataFlex:
Pessoas, não estou falando de polimorfismo, e sim em flexibilidade de código.

Essas coisas são indissociáveis. Vc tem flexibilidade porque tem polimofismo.

Se o método pede uma interface vc é livre de enviar o objeto que quiser, desde que ele implemente essa inerface.
Isso é muito flxivel porque, em tese, existem infinitas implementações de uma interface.
O exemplo mais simples são as interfaces de coleções. Se vc pede um HashMap na assinatura, eu só lhe posso passar um HashMap. Ou seja, 1 só opção de entre N. Se vc pede um Map eu posso passar qualquer Map que eu quiser. HashMap, LinkedHashMap, TreeMap ou alguns especiais devolvidos por Collections.emptyMap(), Collections.synchronizedMap ou Collections.singletonMap. Vc pode ainda criar os seus maps ou usar maps de terceiros como com Commons Collections ou do GoogleCollection. Ou seja, vc pode passar N opções de N.
Isto aumenta a utilidade do método e portanto a flexibilidade.

No conceito de testes, vc precisa muitas vezes enviar objetos que no contexto real viriam de algum framework ou alguma outra parte do sistema. então, muitas vezes, no teste, vc não pode enviar o objeto real. Vc tem então que enviar um objeto faz-de-conta ( os chamados mock) Como ele tem a mesma interface o codigo que o usa não sabe a diferença e funcionará mesmo sem estar agarrado ao resto do sistema.

Paulo_Silveira

eu nao poderia dar respostas melhores…

a ideia realmente é o polimorfismo, e com isso voce se desacopla de uma implementacao em especifico. o dia que quiser trocar, troca! flexibilidade por causa do baixo acoplamento.

MrDataFlex

Muito obrigado, por enquanto pessoal!

Bom, então vamos ver se entendi:
Fazendo assim:

List lista = new ArrayList();

Digamos que se repita durante 10 vezes no código… estou seguindo corretamente o tal pattern, mas… quando eu mudar minha lista de ArrayList para outra qualuqer, eu teria mesmo assim que mudar as 10 vezes.

Ai entraria um outro padrão, como factory?

List lista = factory.obtemLista("tal");

?

R

O ganho em usar um list como referência em vez de um ArrayList, é que se você passar pra algum método, ele vai tratar a lista da mesma forma que trataria um LinkedList por exemplo.

Quanto ao refactoring, no caso das collections eu não uso factory pois não vejo porque, pois não preciso fazer nada na criação de uma collection, mas se você precisar fazer algo em especial, como um tuning… é uma opção.

A classe Calendar utiliza o getInstance, que é outra alternativa (sem ser singleton). Calendar é abstrata e o getInstance dela retorna uma instância de uam de suas subclasses, como a GregorianCalendar por exemplo.

[]´s

sergiotaborda

MrDataFlex:
Muito obrigado, por enquanto pessoal!

Bom, então vamos ver se entendi:
Fazendo assim:

List lista = new ArrayList();

Digamos que se repita durante 10 vezes no código… estou seguindo corretamente o tal pattern, mas… quando eu mudar minha lista de ArrayList para outra qualuqer, eu teria mesmo assim que mudar as 10 vezes.

Sim. Teria que mudar. Mas isso significa que ha um problema com o uso de ArrayList. Ou seja, houve um erro de design. Então é normal fazer a alteração. A isso se chama refactoring. Contudo se vc tivesse usado

ArrayList lista = new ArrayList();

Teria muitos mais lugares onde mudar e poderia até quebrar o codigo.

Isso é outra historia. Ai vc está tentando abstrair a criação da lista real.
Isso é correto, mas nem sempre é necessário.
Por exemplo, quando vc usa um Map internamente a um objeto para acelerar um algoritmo.
Não faz sentido usar uma fabrica porque é algo interno. Mas faz sentido mudar um HashMap por um TreeMap se as chaves são Integer. Isso lhe dará mais performance com a alteração apenas da declaração do mapa.

O uso de factory só faz sentido em certos casos. Em tese vc poderia usar sempre. Mas na prática isso não é correto ( os patterns servem para resolver problemas, não para criar complicações)

Criado 20 de fevereiro de 2008
Ultima resposta 20 de fev. de 2008
Respostas 6
Participantes 4