Mais um pouco sobre INTERFACES

Conforme compreendido em diversos posts, devemos usar e abusar da criação de Intefaces em java deixando de lado, sempre que possível, o uso/criação de sub-classes (extends). Como no próprio artigo aqui do Guj sobre intefaces diz:

Ou seja, devemos sempre enxergar como uma classe vai se comunicar com outra. TODA classe que se comunica com outra tem um getAlgumaCoisa(). Como na inteface criada no artigo…

public interface Funcionario(){
public void getNome();
... (outros gets)...

Então a questão fica. Criariamos uma interface para cada classe que possua ‘gets’ ?? :? Isso seria um bom exemplo de uma boa modelagem? Afinal, estamos usando interfaces e ‘enxergando’ como as classes se comunicam com outras classes.

Se tivessemos uma classe: Professor, Materia, Turma e Sala, por exemplo… Todas as classes possuem seus Gets… Criariamos interfaces para essas classes se comunicarem? Tipo, IProfessor (getNome, getGraduacao), IMateria (getNome), ITurma (getNome, getCod), ISala (getNum)… ?

Não sei se ficou meio confuso a forma que exemplifiquei aqui, mas é a forma que ando sempre vendo nos posts e comentários em geral. Como se o programador quando usa interfaces fosse um profissional diferenciado, melhor… até mesmo em testes de entrevistas…

Pensa comigo, como ficaria uma interface disso aqui:

public class Pessoa{ String nome; public String getNome(){ return nome; } }

Se fosse para todo get como ficaria essa interface? Usar interface, sim. Só cuidado para não abusar.
Vc também pode usar classe abstrata. Bastante útil. [=

Claro, sei que não é em todos os casos, generalizei muito. Mas digo no caso do uso abusivo/excessivo de interfaces… pois vejo muito por aí que se vc implementar interfaces “as pessoas te vêem com outros olhos.” (este ponto que quero chegar)

Muitas classes jamais vão sofrer qualquer tipo de extensão durante o sistema inteiro. Para elas, não é necessário criar interfaces.
Para as que sofrem, geralmente é melhor basear-se em interfaces do que em classes abstratas. Nada impede de ter a as duas coisas:

[code]public interface QualquerCoisa {
//Gets e qualquer coisa.
}

public class AbstractQualquerCoisa implements QualquerCoisa {
//Métodos padrão de qualquer coisa, já implementados
//A idéia aqui é facilitar a implementação de novas coisas quaisquer.
}

public class AlgumaCoisa extends AbstractQualquerCoisa {
//Uma classe concreta.
}[/code]

A vantagem é que boa parte do seu sistema dependerá apenas da interface qualquer coisa. Você fornece uma implementação padrão (com AbstractQualquerCoisa), mas que ninguém é obrigado a seguir. Isso dá flexibilidade se você descobrir no futuro algum exemplo de qualquer coisa com comportamento muito diferente dos demais.

Eu também costumo a usar interfaces para definir fronteiras entre módulos dos sistema. Ou seja, se seu substema vai fornecer informação para alguém, ou ler informação de alguém, crie interfaces para isso. Seja na forma de listeners, ou mesmo interfaces para esperar parâmetros de entrada. Isso reduz a dependência por classes concretas, o que geralmente é uma boa idéia.

[quote=adrianoseven]Conforme compreendido em diversos posts, devemos usar e abusar da criação de Intefaces em java deixando de lado, sempre que possível, o uso/criação de sub-classes (extends). Como no próprio artigo aqui do Guj sobre intefaces diz:

Ou seja, devemos sempre enxergar como uma classe vai se comunicar com outra. TODA classe que se comunica com outra tem um getAlgumaCoisa(). Como na inteface criada no artigo…

public interface Funcionario(){
public void getNome();
... (outros gets)...

Então a questão fica. Criariamos uma interface para cada classe que possua ‘gets’ ?? :? Isso seria um bom exemplo de uma boa modelagem? Afinal, estamos usando interfaces e ‘enxergando’ como as classes se comunicam com outras classes.

Se tivessemos uma classe: Professor, Materia, Turma e Sala, por exemplo… Todas as classes possuem seus Gets… Criariamos interfaces para essas classes se comunicarem? Tipo, IProfessor (getNome, getGraduacao), IMateria (getNome), ITurma (getNome, getCod), ISala (getNum)… ?

Não sei se ficou meio confuso a forma que exemplifiquei aqui, mas é a forma que ando sempre vendo nos posts e comentários em geral. Como se o programador quando usa interfaces fosse um profissional diferenciado, melhor… até mesmo em testes de entrevistas…
[/quote]

Um palpite de quem já fez interface prá tudo no passado… :oops:

Vá com calma… programe com base na interface (métodos públicos) mas não necessariamente crie interfaces. Crie interface quando você precisar de implementações diferentes agora. Se você acha que vai precisar, deixe para quando precisar. As IDEs possuem ferramentas que facilitam a Refatoração. Neste caso, quando precisar, utilize “extrair interface”. Tentar prever o futuro é herança de waterfall.

Abraços

Eu gosto de classes abstratas quando são para classes de puro conceito.

Classes com utilitários, por exemplo, formatadores. Pode-se ter métodos de formatação todos prontos e ao invés de toda hora instanciar uma classe para realizar essa formatação (lógico que existem outras funcionalidades). Utilizando a abstração vc deixa um conceito mais forte no seu código da regra que está sendo aplicada. Por exemplo uma classe de Cambio de Moeda. Ela aplicaria as taxas de conversão sem precisar ser instanciada pois as fórmulas para essa conversão são “estáticas”. Ela iria aparecer para realizar o cambio e pronto. Deixou a palavra final dela.

Utilizando o conceito de “classes abstratas: classes de conceito” vc estaria evitando o uso de interface, mas por outro lado, também evitando o uso de classe “normal”. Existem fórmulas de métricas para calcular isso. Faz um bom tempo que li isso em um livro mas se não me engano a fórmula era:
A = número de classes abstratas/número de classes do pacote.

Quanto mais próximo de um, mais os packages da sua apliação dependem de packages mais abstratos, com isso, sua aplicação pode responder mais facilmente a alguma mudança. Mas também podemos considerar a interface em si como uma “abstração”, pois ela trata por definir os padrões a serem implementados.

Recebi como indicação o livro “Agile Software Development” de Robert Martin mas ainda não tive a oportunidade de ler.

Se você está criando uma API, mesmo no caso do câmbio, eu ainda prefiro criar uma interface e deixar a classe abstrata com a implementação padrão do câmbio.

Isso porque você não sabe como seu usuário vai usar a API. Vamos supor que ele queira calcular o câmbio entre duas moedas que existiram historicamente. Como por exemplo, o cálculo entre o cruzado novo e o real. A fórmula, daí, não é tão simples.

Se você deixar na mão só de uma classe abstrata ela acabará por ser inteiramente reimplementada. Isso pode ser bem tedioso se essa classe abstrata exigir do usuário vários métodos que para o novo processo ele não irá precisar.

Se for na mão de uma interface, está tudo bem.

Calma aí. Quando se diz “Programe com base em interfaces” estamos querendo dizer interfaces mesmo, não métodos públicos.

Pensar em classes flexíveis é papel de qualquer desenvolvedor OO, mesmo aqueles que lidam com XP. A regra é “Make it simple, but not simpler” (faça algo simples, mas não simplista). Um texto que aborda bem essa questão é essa entrevista com o Erich Gamma (JUnit, Eclipse, Design Patterns), que fala sobre programar para interfaces: http://www.artima.com/lejava/articles/designprinciples.html

Programar para a interface é assumir um compromisso com o comportamento, não com a implementação. E por isso elas são tão importantes.

Além disso, seu pensamento está ok para classes de negócio ou implementações da view - já que elas quase nunca são reutilizadas. Mas é uma péssima abordagem para classes utilitárias ou APIs. Pensar no futuro não é só um conceito que vem do waterfall (embora por lá eles exagerassem com isso), mas sim, um princípio para fazer software reaproveitável. Mesmo com as ferramentas de refactoring, alterar a assinatura de um método público pode ser uma dor de cabeça incrível. Se seu .jar é compartilhado em mais de um projeto, maior ainda. Se os outros projetos são de seus usuários e não seus, vai te gerar um número enorme de reclamações.

O desafio está mesmo em saber quando utilizar as interfaces. Como você ressaltou o uso prematuro (como propôs o autor do tópico) também é prejudicial. Mas o não uso também é, mesmo que você considere uma refatoração no futuro. O negócio é mesmo pensar bem em como os módulos de seu sistema se relacionam, e criar boas interfaces entre eles. Identificar os pontos passíveis de mudança, e criar interfaces por lá também.

E, realmente, é bom contar que alguma coisa ou outra vai faltar e você terá que refatorar no futuro. É melhor trabalhar com essa margem de erro, do que voltar a ter a paranóia dos nossos amigos do waterfall.

Ou seja, teria uma interface e uma classe abstrata. Não vejo muito motivo para se ter a interface (nesse caso onde seria necessária apenas a implementação de uma classe).

[quote=ViniGodoy]
Isso porque você não sabe como seu usuário vai usar a API. Vamos supor que ele queira calcular o câmbio entre duas moedas que existiram historicamente. Como por exemplo, o cálculo entre o cruzado novo e o real. A fórmula, daí, não é tão simples. [/quote]
Não vejo que seria tão complicado assim não. Uma vez que o usuário teria que informar o rating da moeda na época e pronto, a fórmula continuaria a mesma. O método iria receber a proporção de uma moeda para com a outra. Bem, pelo menos quando fiz parte da construção de um módulo assim ocorreu sem problemas.

[quote=ViniGodoy]
Se você deixar na mão só de uma classe abstrata ela acabará por ser inteiramente reimplementada. Isso pode ser bem tedioso se essa classe abstrata exigir do usuário vários métodos que para o novo processo ele não irá precisar. [/quote]
Por isso mesmo que a classe abstrata aceita métodos não abstratos. O “usuário” da classe não será obrigado a implementar tals métodos. E deixar tudo em uma classe só é loucura e sai fora totalmente do padrão OO. Por isso disse, que classe abstrata por conceito. Ela vai, realiza o que ela é especializada e pronto. Sai de cena. Imagina se vc precisa fazer operações com datas. Vc poderia ter um DataUtilities que já declara parser,formater e etc. Não haveria a necessidade de sempre se uma Interface para esse cara. Talvez uma interface por exemplo de Utils e a classe abstrata poderia extender. Mas se seu sistema só necessita de uma classe util que no caso fosse essa de data não vejo qual seria a necessidade dessa Interface.

[quote=ViniGodoy]
Se for na mão de uma interface, está tudo bem. [/quote]
Concordo que realmente com interface ela também gera desacoplamento mas continuo com a opinião de que classe abstratas são uma mão na roda! [=

[quote=jakefrog]Ou seja, teria uma interface e uma classe abstrata. Não vejo muito motivo para se ter a interface (nesse caso onde seria necessária apenas a implementação de uma classe).

Não vejo que seria tão complicado assim não. Uma vez que o usuário teria que informar o rating da moeda na época e pronto, a fórmula continuaria a mesma. O método iria receber a proporção de uma moeda para com a outra. Bem, pelo menos quando fiz parte da construção de um módulo assim ocorreu sem problemas.[/quote]

O que eu quis dizer é que seu usuário pode ter uma necessidade de conversão de câmbio que vá além de calcular através de um rating. Uma conversão entre anos, por exemplo, geralmente leva em consideração diversos ratings, e muitas vezes não tem um comportamento linear. A classe abstrata impõe uma forma de calculo, que pode não ser adequada sempre.

Não estou criticando o seu modelo. O seu modelo foi feito para sua aplicação. Estou falando o que ocorre quando fazemos APIs para terceiros usarem, e é aí que as interfaces se tornam especialmente importantes.

Quando você está desenhando APIs para terceiros, você tem pouco conhecimento em como é o negócio do usuário da API. Ele pode ter necessidades que você não imagina, ou realizar o cálculo de uma maneira inesperada. Por isso, é bom não fazer qualquer tipo de pressuposição sobre como o usuário realizará, nesse caso, o calculo de câmbio. A interface é um compromisso com contratos, não com implementação.

Sim, classes abstratas são mesmo uma mão na roda, por isso geralmente faço a interface e sua implementação abstrata padrão. Se você sabe que a conversão por rating vai resolver 90% dos usuários, então, por que não fornece-la de cara na sua API? Você pode não só fornecer uma classe abstrata que facilite a implementação desse caso, como também uma classe Default, se uma forma de cálculo padrão for possível.

Aliás, isso é muito comum na API do java também.
Temos o TableModel, o AbstractTableModel e o DefaultTableModel.
Temos a classe WindowListener e a WindowAdapter;
Temos a classe Document, AbstractDocument e DefaultDocument.
Temos a classe Calendar e a GregorianCalendar
Entre outras.

Cara, acho que me passou desapercebido esse detalhe. Pensei que estavamos a falar em Interfaces/Abstratas para uso próprio! My bad! [=

Para terceiros, Interface go go go! :twisted:

[quote=ViniGodoy]Calma aí. Quando se diz “Programe com base em interfaces” estamos querendo dizer interfaces mesmo, não métodos públicos.
[/quote]

Conceitualmente, a interface de uma classe é sua lista de métodos públicos. “Interface” é um recurso da linguagem java.

Tem razão.

Alterar a assinatura de um método público pode ser uma dor de cabeça incrível, tendo ou não você escrito uma “Interface”

é… na verdade minha resposta era para o autor do tópico. Mas não tenho experiência em foruns e não deixei claro… :oops:

[quote]
E, realmente, é bom contar que alguma coisa ou outra vai faltar e você terá que refatorar no futuro. É melhor trabalhar com essa margem de erro, do que voltar a ter a paranóia dos nossos amigos do waterfall.[/quote]
Esse é o ponto. É melhor encampar a mudança.

Abraços