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

39

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

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

  • É uma coisa ruim?
  • Você sugeriria mudar este estilo?
  • Esse estilo tem algum efeito colateral?
  • É porque não trabalhei em nenhum projeto grande?
por jineesh joseph 19.06.2011 / 18:47
fonte

11 respostas

35

Existem vários motivos pelos quais você pode querer usar interfaces:

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

link

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

    
por 19.06.2011 / 18:55
fonte
17

Tanto a herança de classes quanto 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 "eficaz c # - 50 maneiras específicas para melhorar seu c #" por Bill Wagner. Número do item 22 estados, e uma citação, "Prefiro definir e implementar interfaces para herança".

Geralmente eu 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, eu normalmente começo definindo uma interface para uma classe quando eu começo a criar uma ... mesmo que no final eu não compile a interface, eu acho que isso ajuda a começar definindo a API pública da classe do get go. Se eu descobrir que tenho várias classes implementando a interface, e a lógica de implementação é idêntica, só então me pergunto se faria ou não sentido implementar uma classe base comum entre os tipos.

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

"Classes base abstratas podem fornecer alguma implementação para tipos derivados, além de descrever o comportamento comum. Você pode especificar membros de dados, métodos concretos, implementação de métodos virtuais, propriedades, eventos e indexadores. Uma classe base pode fornecer implementação para alguns dos métodos, fornecendo reutilização de implementação comum. Qualquer um dos elementos pode ser virtual, abstrato ou não-virtual. Uma classe base abstrata pode fornecer uma implementação para qualquer comportamento concreto; interfaces não podem. Essa reutilização de implementação fornece outro benefício: Se você adicionar um método à classe base, todas as classes derivadas serão aprimoradas de maneira automática e implícita.Nesse sentido, as classes base fornecem uma maneira de estender o comportamento de vários tipos com eficiência: Adicionando e implementando a funcionalidade na classe base, todas as classes derivadas Imediatamente incorporar esse comportamento.Adicionando um membro a uma interface quebra todas as classes que implementam essa interface.Eles não c manter o novo método e não irá mais compilar. 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 melhor apoiar suas abstrações ao longo do tempo. Interfaces são corrigidas: você libera uma interface como um contrato para um conjunto de funcionalidades que qualquer tipo pode implementar. 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 misturados para reutilizar o código de implementação e, ao mesmo tempo, suportar várias interfaces. "

"Interfaces de codificação fornecem maior flexibilidade a outros desenvolvedores do que codificar para basear tipos de classes."

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

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

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

    
por 19.06.2011 / 19:36
fonte
8

Uma coisa que não foi mencionada é o teste: em todas as bibliotecas de mocking C #, bem como algumas para Java, as classes não podem ser escarnecidas, a menos que implementem uma interface. Isso leva muitos projetos seguindo o Agile / TDD pratica para dar à 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 para uma deficiência na linguagem.

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

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

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

    
por 20.06.2011 / 01:23
fonte
5

O principal resultado de não usar herança e interfaces quando elas são apropriadas é o acoplamento apertado . Isso pode ser um pouco difícil de aprender a reconhecer, mas geralmente o sintoma mais óbvio é quando você faz uma alteração, você acha que freqüentemente tem que passar por um monte de outros arquivos para fazer alterações em um efeito cascata.

    
por 19.06.2011 / 20:33
fonte
4

Não, isso não é ruim. Interfaces explícitas devem ser usadas, se e somente se, duas classes com uma interface comum precisarem ser intercambiáveis em tempo de execução. Se eles não precisam ser intercambiáveis, não os faça herdar. É 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 de tempo de compilação fracos, você pode acabar violando DRY porque não há como escrever um método que possa lidar com mais de uma classe, a menos que todas as classes herdem da mesma base. . No entanto, o dynamic do C # 4 pode lidar com isso.

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

    
por 19.06.2011 / 20:32
fonte
3

Sim, não (ou muito raramente) usando interfaces é provavelmente uma coisa ruim. Interfaces (no sentido abstrato, e a construção da linguagem C # / Java é 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 fácil de manter. Como com qualquer coisa que melhore a manutenção, torna-se mais importante quanto maior for um sistema.

    
por 19.06.2011 / 23:54
fonte
3

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

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

    
por 20.06.2011 / 01:13
fonte
2

Se você está falando sobre o uso de Java, uma razão para usar 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ê está trabalhando com um framework complexo como o Spring. Além disso, algumas funcionalidades exigem interfaces: RMI é o exemplo clássico disso, já que você deve descrever a funcionalidade que está fornecendo em termos de interfaces (herdadas de java.rmi.Remote ), mas implementar eles.

    
por 19.06.2011 / 22:29
fonte
1

As coisas estão mudando ( MS Moles ), mas o principal motivo que me parece bom codificar quase que exclusivamente para interfaces é que elas são fáceis de burlar e se encaixam naturalmente em uma arquitetura de IoC.

IMO você só deve trabalhar com interfaces, ou DAOs completamente estúpidos, sempre que possível. Depois de entrar nessa mentalidade e começar a usar uma biblioteca que não se expõe por meio de interfaces e faz tudo por meio de objetos concretos para ser honesto, tudo parece um pouco desajeitado.

    
por 19.06.2011 / 20:44
fonte
0

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

Ruim:

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

class B
{
  A* a;
}

Nada mal:

class PartOfClassB_AccessedByA
{
};

class A
{
  PartOfClassB_AccessedByA* b;
};

class B : public PartOfClassB_AccessedByA
{
  A* a;
}

Normalmente, A, B, PartOfClassB_AccessedByA implementado com arquivos separados.

    
por 20.06.2011 / 13:32
fonte
0

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

    
por 20.06.2011 / 16:18
fonte