Todas as aulas que escrevo devem aderir a uma interface?

10

Estou escrevendo um jogo no Typescript e decidi que tentaria aderir à idéia de " programação baseada em interface ", na qual você escreve código com base em uma interface, em vez da implementação, de um objeto.

Eu escrevi um bom número de interfaces e classes que as implementam. Depois, dei um passo para trás e percebi que as classes eram simples o suficiente para que eu provavelmente nunca precisasse alterar a implementação, pois há realmente apenas uma maneira de fazer o que o classe faz (mover um de Phaser.Spritemaneira restrita para agir como um tanque).

Então, lembro-me de ler alguns anos atrás sobre a idéia do YAGNI , que é basicamente que você não deve exagerar na engenharia do seu código para incluir coisas que você nunca pode usar.

Seguindo as práticas recomendadas, todas as classes devem implementar uma interface ou você deve limitá-las às classes que você espera que sejam potencialmente trocadas no futuro?

Carcinigenicado
fonte
Lembre-se, quando você usa uma classe real como parâmetro, também está codificando para uma interface, para a interface desta classe. Ninguém o obriga a usar essa classe específica; você também pode herdá-la e fornecer uma funcionalidade completamente nova, mas isso não parece certo. Existem interfaces para facilitar as pessoas a entender a idéia. Com isso triste, não, você realmente não precisa de interfaces para tudo.
187 Andy Andy

Respostas:

6

A razão para ter interfaces é porque simplifica o polimorfismo. Isso significa que você pode enviar instâncias por contrato, em vez de conhecer sua implementação real. Por exemplo, você pode enviar um "Reader" para um método, para que esse método chamado possa usá-lo "read ()". Ao declarar uma interface "Leitor", você pode fazer com que qualquer objeto esteja em conformidade com este contrato, implementando os métodos especificados. Dessa forma, qualquer chamador pode assumir que certos métodos existirão, mesmo que os objetos subjacentes ao contrato possam ser completamente diferentes.

Isso desacopla o polimorfismo de uma classe base e torna possível também entre as fronteiras da cadeia de classes, implicando um contrato.

Agora ... Isso só é útil se você precisar de várias cadeias de herança para agir da mesma maneira ou se tiver muitas classes base com comportamento comum que deseja passar para outros usuários.

Se você tiver apenas UMA cadeia de herança (baseclass-> subclasse) ou apenas a base, ou não tiver realmente necessidade de PASSAR os objetos relacionados para outra pessoa ou usá-los genericamente, não incluirá implementações de interface, pois essa noção é então sem utilidade.

Richard Tyregrim
fonte
Eu também acrescentaria que as interfaces devem modelar abstrações, portanto não as crie simplesmente içando todos os membros públicos de uma classe. Pense no que essa classe representa e apenas coloque essas coisas na interface que qualquer objeto desse tipo deve ter. Você também pode criar várias interfaces (por exemplo, Movese Shootspara o seu exemplo de tanque) para uma única classe.
TMN
7

Se você não tem certeza se realmente precisa das interfaces, provavelmente não precisa. Este é o núcleo do princípio YAGNI. Quando você precisar trocar a implementação, introduza uma interface.

JacquesB
fonte
6

Criar uma interface para cada classe é um pouco exagerado. De uma perspectiva puramente orientada a objetos, toda classe já possui uma interface . Uma interface nada mais é do que os métodos voltados para o público e os membros de dados de uma classe.

Normalmente, usamos "interface" para significar "uma classe Java definida usando a interfacepalavra - chave" ou "uma classe C ++ com apenas funções virtuais puras e públicas". Essas são abstrações úteis, porque separam a interface de uma classe de sua implementação.

Com isso em mente, use interfaces quando apropriado.

  • Haverá várias implementações para uma interface? Nesse caso, essa situação pode ser candidata à extração de métodos comuns voltados para o público em uma interface.

  • Entregarei implementações de uma interface em potencial a outros módulos que não devem conhecer o funcionamento interno do meu módulo? Uma interface pode ser útil aqui, porque reduz o tamanho do ponto de contato entre os módulos.

Observe as palavras da doninha acima: "pode" ser um candidato ", pode ser" útil. Não existe uma regra rígida que diga "sim" ou "não" para uma determinada situação.

Dito isto, ter uma interface para tudo provavelmente é um exagero. Se você vir esse padrão, está indo longe:

interface I {
  int getA()
  int getB()
  ...
  int getY()
  int getZ()
}

class C : I {
  int getA() { ... }
  int getB() { ... }
  ...
  int getY() { ... }
  int getZ() { ... }
}

fonte
Mais um motivo para as interfaces é se o seu sistema de teste o torna necessário, o que pode depender do seu idioma e estrutura de teste. Espero que você não precise fazer isso, é claro.
Darien
@ Darien: A razão pela qual um sistema de teste pode exigir interfaces é porque o teste está realmente usando uma implementação diferente (zombada), levando você de volta ao primeiro marcador de quando uma interface é apropriada.
Bart van Ingen Schenau
Algumas ótimas coisas aqui. Apenas refletindo sobre isso: uma interface nada mais é do que os métodos voltados ao público e os membros de dados de uma classe . Embora isso seja verdade para uma implementação de interface , certamente não é válido para uma interface que nunca é implementada, embora concedida - isso seria uma espécie de cheiro de código.
Robbie Dee
@RobbieDee é verdade, por exemplo, para um Java interface, acontece que tudo no Java interfacetambém é sua interface pública (conceito OO).
Todos! Anote as 2ª e 3ª frases da resposta. Laminado. Coloque na sua carteira. Referência frequentemente.
Radarbob
5

Pode ser muito tentador para os desenvolvedores mais novos pensarem nas interfaces como um inconveniente que você simplesmente adiciona apenas porque lhe dizem que é uma "prática recomendada". Se você está fazendo isso às cegas, isso cheira a programação de cultos de carga .

Há várias razões muito boas para considerar interfaces para desenvolvimentos maiores, em vez de reunir um conjunto de classes.

Estruturas de zombaria

Se você deseja testar um aplicativo de várias camadas sem precisar criar objetos para as várias camadas, sem dúvida deseja usar estruturas de zombaria para zombar das camadas. As interfaces são usadas extensivamente aqui.

Injeção de dependência

Embora tenham caído em desuso um pouco devido ao inchaço que acrescentam, a idéia é sólida - a capacidade de simplesmente trocar concreções com base em uma interface. O princípio também pode ser encontrado em muitos padrões de design, como o padrão de fábrica.


Essas abordagens estão resumidas no D dos princípios do SOLID . O problema disso é - use abstrações, não concreções.

Como os próprios padrões de design, quando usá-los é uma decisão de julgamento. O ponto principal é entender como as interfaces são úteis e não apenas colocá-las em suas aulas, porque você sente que precisa. Há uma boa discussão dos vários méritos do DIP e do YAGNI aqui .

Robbie Dee
fonte
Observe que os contêineres de injeção de dependência e IoC são duas coisas completamente diferentes (uma é um princípio de design e a outra é uma maneira de colocar concretamente esse princípio em prática usando várias estruturas). Você pode usar o DI sem usar um contêiner de IoC.
Sara
@kai "Você pode usar o DI sem usar um contêiner de IoC" . Eu acho que lojas de desenvolvimento mais maduras podem (e fazem). Simplesmente não há necessidade de poluir o código para o que é aparentemente um conceito simples. Joel tem uma visão semelhante.
Robbie Dee #
YAGNI é muito complicado. Qualquer que seja a filosofia, na maioria dos casos, na realidade, o YAGNI é usado como desculpa para cortar custos. Evitar que o acoplamento deva ser levado mais a sério. É frustrante ver, em muitas reuniões do scrum, que um desenvolvedor se considera bloqueado porque outra pessoa não terminou seu trabalho. Como bloquear outro desenvolvedor está economizando tempo para alguém? Minha sugestão é usar uma interface para evitar o acoplamento. Obviamente, não é necessário usar uma interface para as classes Model.
Ripal Barot 01/06/19