É mau hábito não usar interfaces? [fechadas]


40

Uso interfaces raramente e as acho comuns em outros códigos.

Também crio sub e super classes (ao criar minhas próprias classes) raramente no meu código.

  • Isso é uma coisa ruim?
  • Você sugeriria mudar esse estilo?
  • Esse estilo tem algum efeito colateral?
  • Isso é porque não trabalhei em nenhum grande projeto?

10
Que idioma é esse?

2
Além de qual linguagem, que paradigma é esse?
Armando

11
O conceito de uma "interface" não transcende a linguagem? Java possui o tipo de interface interno, mas os desenvolvedores de C ++ geralmente também criam interfaces (prefixando-os com I) e todos eles servem ao mesmo objetivo.
Ricket

4
@Ricket: Não, na verdade não. O problema é que o C ++ oferece herança de várias classes. Em C um "interface" ++ é muito mais conceitual e, na realidade, principalmente usar o que eles definem como uma classe base abstrata #.
DeadMG

2
@Ricket não, especialmente se você estiver trabalhando em uma linguagem funcional, em vez de uma linguagem processual ou OOP.
alternativa

Respostas:


36

Há várias razões pelas quais você pode querer usar interfaces:

  1. As interfaces são adequadas para situações em que seus aplicativos requerem muitos tipos de objetos possivelmente não relacionados para fornecer determinadas funcionalidades.
  2. As interfaces são mais flexíveis que as classes base, porque você pode definir uma única implementação que pode implementar várias interfaces.
  3. As interfaces são melhores em situações nas quais você não precisa herdar a implementação de uma classe base.
  4. As interfaces são úteis nos casos em que você não pode usar a herança de classe. Por exemplo, estruturas não podem herdar de classes, mas podem implementar interfaces.

http://msdn.microsoft.com/en-us/library/3b5b8ezk(v=vs.80).aspx

As interfaces são como qualquer outra coisa na programação. Se você não precisar deles, não os use. Já os vi usados ​​extensivamente por uma questão de estilo, mas se você não precisa das propriedades e dos recursos especiais que uma interface fornece, não vejo o benefício de usá-los "apenas porque".


13
A linguagem dele não é especificada e a sua é muito específica - por exemplo, em C ++, uma estrutura pode realmente herdar de uma classe e você pode multiplicar a herança de bases não abstratas.
DeadMG

2
Essa resposta parece ser C #, mas também se refere ao Java se você tirar o número 4 e só se aplica ao C ++, porque é claro que a herança múltipla é permitida no C ++.
21311 Ricket

2
Além disso, eu discordo da última declaração. Eu acho que existem muitas boas práticas que os programadores devem fazer, mas não porque sentem que não precisam delas. Eu acho que o autor é muito sábio ao olhar em volta, ver todo mundo fazendo isso e pensar que talvez ele deva estar fazendo isso também, mas perguntando "por que" primeiro.
Ricket

3
@Ricket: O porquê está nos quatro pontos da minha resposta. Se nenhum desses motivos se aplicar, você não precisará de uma interface.
Robert Harvey

17

A herança de classe e as interfaces têm seu lugar. Herança significa "é um", enquanto uma interface fornece um contrato que define como algo "se comporta".

Eu diria que usar interfaces com mais frequência não é uma prática ruim. Atualmente, estou lendo "C # eficaz - 50 maneiras específicas de melhorar seu c #", de Bill Wagner. O item número 22 declara e cito "Prefiro definir e implementar interfaces à herança".

Geralmente, uso classes base quando preciso definir uma implementação específica de comportamento comum entre tipos conceitualmente relacionados. Mais frequentemente eu uso interfaces. Na verdade, normalmente começo definindo uma interface para uma classe quando começo a criar uma ... mesmo que no final não compile a interface, acho que ajuda começar definindo a API pública do classe desde o início. Se eu achar que tenho várias classes implementando a interface e a lógica de implementação é idêntica, só então me perguntarei se faria sentido ou não implementar uma classe base comum entre os tipos.

Algumas citações do livro de Bill Wagners ...

todas as classes derivadas incorporam imediatamente esse comportamento. Adicionar um membro a uma interface quebra todas as classes que implementam essa interface. Eles não conterão o novo método e não serão mais compilados. Cada implementador deve atualizar esse tipo para incluir o novo membro. Escolher entre uma classe base abstrata e uma interface é uma questão de como apoiar melhor suas abstrações ao longo do tempo. As interfaces são corrigidas: você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. As classes base podem ser estendidas ao longo do tempo. Essas extensões se tornam parte de todas as classes derivadas. Os dois modelos podem ser combinados para reutilizar o código de implementação enquanto suportam várias interfaces ". Eles não conterão o novo método e não serão mais compilados. Cada implementador deve atualizar esse tipo para incluir o novo membro. Escolher entre uma classe base abstrata e uma interface é uma questão de como apoiar melhor suas abstrações ao longo do tempo. As interfaces são corrigidas: você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. As classes base podem ser estendidas ao longo do tempo. Essas extensões se tornam parte de todas as classes derivadas. Os dois modelos podem ser combinados para reutilizar o código de implementação enquanto suportam várias interfaces ". Eles não conterão o novo método e não serão mais compilados. Cada implementador deve atualizar esse tipo para incluir o novo membro. Escolher entre uma classe base abstrata e uma interface é uma questão de como apoiar melhor suas abstrações ao longo do tempo. As interfaces são corrigidas: você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. As classes base podem ser estendidas ao longo do tempo. Essas extensões se tornam parte de todas as classes derivadas. Os dois modelos podem ser combinados para reutilizar o código de implementação enquanto suportam várias interfaces ". Você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. As classes base podem ser estendidas ao longo do tempo. Essas extensões se tornam parte de todas as classes derivadas. Os dois modelos podem ser combinados para reutilizar o código de implementação enquanto suportam várias interfaces ". Você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. As classes base podem ser estendidas ao longo do tempo. Essas extensões se tornam parte de todas as classes derivadas. Os dois modelos podem ser combinados para reutilizar o código de implementação enquanto suportam várias interfaces ".

"As interfaces de codificação fornecem maior flexibilidade a outros desenvolvedores do que a codificação para tipos de classe base".

"O uso de interfaces para definir APIs para uma classe fornece maior flexibilidade."

"Quando seu tipo expõe propriedades como tipos de classe, expõe toda a interface a essa classe. Usando interfaces, você pode optar por expor apenas os métodos e propriedades que deseja que os clientes usem."

"As classes base descrevem e implementam comportamentos comuns entre tipos de concreto relacionados. As interfaces descrevem peças atômicas de funcionalidade que tipos de concreto não relacionados podem implementar. Ambas têm seu lugar. As classes definem os tipos que você cria. As interfaces descrevem o comportamento desses tipos como peças de funcionalidade. Se você entender as diferenças, criará designs mais expressivos e mais resilientes diante da mudança. Use hierarquias de classes para definir tipos relacionados. Exponha a funcionalidade usando interfaces implementadas nesses tipos ".


2
Bem, eu li e achei que era uma boa resposta.
Eric King

11
@ mc10 Não tenho certeza qual é o problema. Ele referenciou um livro e a metade inferior de sua resposta são apenas citações desse livro que ele claramente deixa você saber caso não queira perder seu tempo.
Pete

@ Peter Não disse que a resposta é ruim, mas apenas que foi um pouco longa demais. Duvido que você precise da cotação inteira algumas vezes.
kevinji

3
haha, se isso é dr; eu não tenho certeza se você vai gostar de toda essa coisa de StackExchange - respostas de alta qualidade.
Nic

haha, obrigado pessoal. Sim, ocorreu-me que a resposta foi um pouco demorada, mas pensei em qualificar minha resposta incluindo citações relevantes do Sr. Wagner que expõem as vantagens e desvantagens de interfaces versus herança, bem como os cenários em que cada um é mais apropriado. Talvez citar o livro diretamente não tenha agregado muito valor à minha resposta.
John Connelly

8

Uma coisa que não foi mencionada é o teste: em todas as bibliotecas de simulação do C #, bem como em Java, as classes não podem ser ridicularizadas, a menos que implementem uma interface. Isso leva muitos projetos a seguir as práticas Agile / TDD para dar a cada classe sua própria interface.

Algumas pessoas consideram essa prática recomendada, porque "reduz o acoplamento", mas eu discordo - acho que é apenas uma solução alternativa para uma deficiência no idioma.


Eu acho que as interfaces são melhor usadas quando você tem duas ou mais classes que, abstratamente, fazem a "mesma coisa", mas de maneiras diferentes.

Por exemplo, a estrutura .Net possui várias classes que armazenam listas de coisas , mas todas elas armazenam essas coisas de maneiras diferentes. Portanto, faz sentido ter uma IList<T>interface abstrata , que pode ser implementada usando métodos diferentes.

Você também deve usá-lo quando quiser que duas ou mais classes sejam intercambiáveis ​​ou substituíveis no futuro. Se uma nova maneira de armazenar listas for lançada no futuro, AwesomeList<T>supondo que você tenha usado IList<T>todo o seu código, alterá-lo para uso AwesomeList<T>significaria apenas alterar algumas dezenas de linhas, em vez de algumas centenas / mil.


5

O principal resultado de não usar herança e interfaces quando elas são apropriadas é o acoplamento rígido . Isso pode ser um pouco difícil de aprender a reconhecer, mas geralmente o sintoma mais óbvio é que quando você faz uma alteração, muitas vezes precisa passar por vários outros arquivos para fazer alterações em um efeito cascata.


4

Não, isso não é ruim. Interfaces explícitas devem ser usadas, se e somente se, duas classes com uma interface comum precisam ser intercambiáveis ​​em tempo de execução. Se eles não precisam ser intercambiáveis, não os herdam. É simples assim. A herança é frágil e deve ser evitada sempre que possível. Se você puder evitá-lo ou usar genéricos, faça isso.

O problema é que, em linguagens como C # e Java com genéricos fracos em tempo de compilação, você pode acabar violando o DRY porque não há como escrever um método que possa lidar com mais de uma classe, a menos que todas as classes sejam herdadas da mesma base. C # 4 dynamic pode lidar com isso, no entanto.

O problema é que a herança é como variáveis ​​globais - uma vez que você o adiciona e seu código depende, Deus o ajude a removê-lo. No entanto, você pode adicioná-lo a qualquer momento e até mesmo sem alterar a classe base usando um tipo de wrapper.


11
Motivo para voto negativo?
DeadMG

Não tenho certeza, tenha um voto positivo. Foi uma boa resposta.
11788 Bryan Boettcher #

3

Sim, não (ou muito raramente) o uso de interfaces é provavelmente uma coisa ruim. As interfaces (no sentido abstrato e a construção da linguagem C # / Java são uma boa aproximação desse sentido abstrato) definem pontos de interação explícitos entre sistemas e subsistemas. Isso ajuda a reduzir o acoplamento e torna o sistema mais sustentável. Como qualquer coisa que melhore a capacidade de manutenção, torna-se mais importante quanto maior o sistema.


3

Eu não uso uma interface há anos. Claro que isso é porque eu tenho programado quase exclusivamente em Erlang há anos e todo o conceito de interface simplesmente não existe. (O mais próximo que você chega é de um "comportamento" e isso não é a mesma coisa, a menos que você olhe com força e olhe para eles pelo canto do olho.)

Então, realmente, sua pergunta depende do paradigma (OOP neste caso) e, além disso, é realmente muito dependente da linguagem (existem linguagens OOP sem interfaces).


2

Se você está falando sobre o uso de Java, uma razão para o uso de interfaces é que elas permitem o uso de objetos proxy sem bibliotecas de geração de código. Isso pode ser uma vantagem substancial quando você estiver trabalhando com uma estrutura complexa como o Spring. Além disso, algumas funcionalidades requerem interfaces: o RMI é o exemplo clássico disso, pois é necessário descrever a funcionalidade que você está fornecendo em termos de interfaces (que são herdadas java.rmi.Remote), independentemente da implementação.


1

As coisas estão mudando ( MS Moles ), mas a principal razão pela qual acho bom codificar quase exclusivamente para interfaces é que elas são fáceis de zombar e se encaixam naturalmente em uma arquitetura de IoC.

Na IMO, você só deve trabalhar com interfaces ou DAOs completamente burros, sempre que possível. Quando você entra nessa mentalidade e começa a usar uma biblioteca que não se expõe por meio de interfaces e faz tudo por meio de objetos concretos, eu tenho que ser honesto, tudo parece um pouco desajeitado.


0

Para projetos de moda antiga, utiliza-se interfaces para evitar referências circulares, porque as referências circulares podem se tornar um grande problema de manutenção a longo prazo.

Ruim:

class B; // forward declaration
class A
{
  B* b;
};

class B
{
  A* a;
}

Não é ruim:

class PartOfClassB_AccessedByA
{
};

class A
{
  PartOfClassB_AccessedByA* b;
};

class B : public PartOfClassB_AccessedByA
{
  A* a;
}

Geralmente A, B, PartOfClassB_AccessedByA implementado com arquivos separados.


0

A programação baseada em interface ajuda a tornar o código mais flexível e fácil de testar. As classes de implementação podem ser alteradas sem tocar no código do cliente [Flexibilidade]. Ao testar o código, pode-se substituir a programação baseada na interface real, ajudando a tornar o código mais flexível e fácil de testar. As classes de implementação podem ser alteradas sem tocar no código do cliente [Flexibilidade]. Durante o teste do código, é possível substituir o objeto real por objetos simulados [Testability] .bject por objetos simulados [Testability].

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.