Eu tenho lido " Código Limpo ", de Robert Martin, para se tornar um programador melhor. Embora nada até agora tenha sido realmente inovador, isso me fez pensar de maneira diferente sobre a maneira como desenvolvo aplicativos e escrevo código.
Há uma parte do livro com a qual eu não apenas não concordo, mas não faz sentido para mim, especificamente em relação às convenções de nomenclatura de interfaces. Aqui está o texto, extraído diretamente do livro. Eu atrevi o aspecto disso, acho confuso e gostaria de esclarecimentos.
Eu prefiro deixar as interfaces sem adornos. O eu precedente, tão comum nos maquinários herdados de hoje, é uma distração na melhor das hipóteses e muita informação na pior das hipóteses. Não quero que meus usuários saibam que estou entregando uma interface a eles .
Talvez seja porque sou apenas um estudante ou talvez nunca tenha feito nenhuma programação profissional ou em equipe, mas gostaria que o usuário soubesse que é uma interface. Há uma grande diferença entre implementar uma interface e estender uma classe.
Portanto, minha pergunta se resume a: "Por que devemos esconder o fato de que parte do código está esperando uma interface?"
Editar
Em resposta a uma resposta:
Se o seu tipo é uma interface ou uma classe é da sua conta, não da conta de alguém usando seu código. Portanto, você não deve vazar detalhes do seu código neste código de terceiros.
Por que não devo "vazar" os detalhes sobre se um determinado tipo é uma interface ou uma classe para código de terceiros? Não é importante para o desenvolvedor de terceiros usar meu código saber se eles estão implementando uma interface ou estendendo uma classe? As diferenças simplesmente não são tão importantes quanto as estou pensando?
fonte
to know whether they will be implementing an interface or extending a class
: sim, mas a maioria dos usuários do seu código irá chamá-lo, não implementá-lo ou estendê-lo, e eles realmente não poderiam se importar com o que é.Respostas:
Se você parar para pensar sobre isso, verá que uma interface realmente não é semanticamente muito diferente de uma classe abstrata:
De fato, as distinções mais importantes entre classes e interfaces são:
Como as únicas distinções particularmente significativas entre classes e interfaces giram em torno de (a) dados privados e (b) hierarquia de tipos - nenhuma das quais faz a menor diferença para um chamador - geralmente não é necessário saber se um tipo é uma interface ou uma aula. Você certamente não precisa da indicação visual .
No entanto, existem certos casos de canto a serem observados. Em particular, se você estiver usando reflexão, interceptação, proxies / mixins dinâmicos, tecelagem de bytecode, geração de código ou qualquer coisa que envolva mexer diretamente com o sistema de digitação do ambiente ou com o próprio código - é muito útil e às vezes necessário saber imediatamente o se você está lidando com uma interface ou uma classe. Você claramente não quer que seu código falhe misteriosamente porque tentou adicionar uma classe, em vez de uma interface, como um mixin.
No entanto, para códigos de lógica de negócios comuns, comuns, comuns, as distinções entre classes abstratas e interfaces não precisam ser anunciadas, porque nunca entrarão em jogo.
Tudo isso dito, eu tendem a prefixar minhas interfaces C # de
I
qualquer maneira, porque essa é a convenção .NET usada e defendida pela Microsoft. E quando estou explicando as convenções de codificação para um novo desenvolvedor, é muito menos complicado usar as regras da Microsoft do que explicar por que temos nossas próprias regras "especiais".fonte
I
uma interface pode dar um bom nome para uma classe manter métodos estáticos associados à interface (por exemplo,Enumerable<T>.Empty
ouComparer<T>.Default
)class Foo
já se estendeclass Bar
, não é imediatamente óbvio seclass Bar
está sendo estendido ou implementado. Então agora você tem que ir e procurar noclass Bar
cabeçalho para decidir se não há problema em modificarclass Foo
para estenderclass Baz
. Além disso, o prefixo I fornece uma pista visual óbvia se a "classe base única" está sendo violada ou não - para que você faça uma verificação de sanidade toda vez que abrir um cabeçalho.De muitas maneiras, a consistência é mais importante que a convenção. Desde que você seja consistente em seus esquemas de nomeação, eles não serão difíceis de trabalhar. O prefixo faz interface com um I, se você preferir, ou apenas deixe o nome sem adornos, isso não importa para mim, desde que você escolha um estilo e continue com ele!
fonte
O livro está cheio de coisas boas, mas eu ainda adicionaria "I" ao nome da interface.
Imagine que você possui
public interface ILog
uma implementação padrãopublic class Log
.Agora, se você decidir ter
public interface Log
, de repente, precisará alterar a classe Log parapublic class LogDefault
algo assim. Você passou de um personagem extra para sete - certamente é um desperdício.Muitas vezes há uma linha tênue entre teoria e prática. Em teoria, essa é uma ideia muito boa, mas na prática não é tão boa.
fonte
Log
faz? Entrar no console? Para syslog? Para lugar nenhum? Aqueles deve ser chamadoConsoleLog
,SyslogLog
eNullLog
, respectivamente.Log
não é um bom nome para uma classe concreta, porque não é um nome concreto.MyClass
tenha uma variação zombeteira , certo? Ou seja, geralmente usamos interfaces para essencialmente tornar os métodos públicos realmente públicos de uma maneira que permita o teste. (Não estou dizendo que é bom ou ruim, mas a compreensão de que a motivação para interfaces é muitas vezes simplesmente para fazer classes que são dependências facilmente mockable não explica os 1-to-1MyClass
paraIMyClass
mapeamentos.)Bem, não se trata de implementar a interface ou estender uma classe. Nesses casos, você sabe de qualquer maneira o que está fazendo.
No entanto, quando código de terceiros (outro módulo do aplicativo, por exemplo) manipula seus dados, esse código não deve importar se você está apresentando uma interface ou uma classe.
Este é o ponto principal da abstração. Você está apresentando a esse código de terceiros um objeto de um determinado tipo. Esse tipo de dado tem alguma função de membro que você pode chamar. É o bastante.
Se o seu tipo é uma interface ou uma classe é da sua conta, não da conta de alguém usando seu código. Portanto, você não deve vazar detalhes do seu código para esse código de terceiros.
A propósito, interfaces e classes são tipos de referência no final. E é isso que importa. Portanto, é isso que sua convenção de nomenclatura deve enfatizar.
fonte
A maioria das respostas parece assumir que a linguagem de programação é Java ou C #, onde existe um conceito (ou palavra-chave) para interfaces / classes abstratas. Nesses casos, em um IDE decente, é imediatamente visível com qual tipo de classe um lida e a gravação
public interface IMyClass
é duplicação desnecessária. É como se você não escrevessepublic final FinalMyClass
- imagine colocar todas as palavras-chave no nome da classe.No entanto, na minha opinião em C ++, a situação é um pouco diferente, pois é preciso mergulhar no arquivo de cabeçalho e ver se a classe possui algum método virtual para descobrir se é uma classe abstrata. Nesse caso, eu posso ver claramente um argumento para escrever
class AbstractMyClass
.Então, minha resposta seria: Depende da linguagem de programação.
Atualizado em 2016: 2 anos de experiência em C ++ mais tarde, agora eu provavelmente consideraria uma prática inadequada prefixar nomes de classe
Abstract
, embora eu diria que provavelmente existem bases de código tão complexas que podem fazer sentido.fonte
Siga os idiomas do idioma que você está usando.
Cada idioma possui seus próprios idiomas e diretrizes de codificação. Por exemplo, em C #, é idiomático prefixar interfaces com I. No Go, não é.
fonte
No meu código (Java), costumo ter essa convenção nas APIs que expus aos chamadores:
Por não funcional, quero dizer coisas como estruturas de dados puras (como classes que agem como pontes para serialização XML ou ORM), enumerações e exceções, todas as quais não podem ser interfaces (bem, você pode usar as classes de dados puras , mas dá muito trabalho com muito pouco ganho, pois não há nada que essas classes realizem, exceto que mantêm dados).
Em termos de convenções de nomenclatura, as interfaces tendem a ser mapeadas para nomes de atores (por exemplo,
FooBarWatcher
) ou adjetivos (por exemplo,FooBarWatchable
) e ambas as classes de dados e enumerações puras são mapeadas para substantivos não ativos (por exemplo,FooBarStatus
); o IDE pode orientar o consumidor da API sem convenções de nomenclatura especiais. Exceções seguir convenções Java habituais (FooBarException
,FooBarError
,FooBarFault
), é claro.Também colocarei as interfaces em seu próprio pacote ou em sua própria biblioteca, apenas para garantir que eu não seja tentado a violar minhas próprias regras. (Isso também me ajuda a gerenciar a compilação quando estou derivando o código de fontes externas, como documentos WSDL.)
fonte
I
prefixos nas interfaces. Do curso é uma interface! Está em uma API (ou SPI)!