Os nomes de interface devem começar com um prefixo "I"?

73

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?

Charles Sprayberry
fonte
3
Concordo com o seu ponto. Há um momento em que muita informação oculta não é muito útil. No entanto, mesmo se você seguir esta diretriz, ainda poderá informar o tipo usando o IDE ou um complemento.
NoChance
3
Essa questão é essencialmente conhecida como "notação húngara"; você deve encontrar muitos argumentos e a razão pela qual a maioria dos desenvolvedores não-MS a abandonou sob essa palavra-chave. A notação húngara foi predominante nas variáveis, mas é essencialmente a mesma para os tipos.
thiton
2
A edição anterior do título foi terrível. Esta questão não se refere à notação húngara em geral, simplesmente porque menciona uma convenção que pode estar associada a ela. Os méritos relativos da HN são totalmente irrelevantes aqui; a questão era especificamente sobre interfaces versus classes e se as diferenças semânticas são importantes ou interessantes o suficiente para justificar uma convenção de nomenclatura de casos especiais.
Aaronaught
Re 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 é.
David.pfx
Pelo que vale, eu prefiro muito o prefixo "I". Eu também uso um prefixo "Resumo" em classes abstratas pelo mesmo motivo. Isso não faz diferença para os consumidores da classe / interface, mas pode fazer uma grande diferença para aqueles que precisam fornecer instâncias e também simplifica muito mais os outros desenvolvedores que estão lendo seu código. Isso significa que eles podem ver rapidamente com o que estão lidando, em vez de precisar consultar o IDE caso a caso para obter mais informações. Acabei de começar a usar o Angular e acho realmente irritante que eles não sigam esta convenção!
Dan King

Respostas:

67

Se você parar para pensar sobre isso, verá que uma interface realmente não é semanticamente muito diferente de uma classe abstrata:

  • Ambos têm métodos e / ou propriedades (comportamento);
  • Nem deve ter campos não privados (dados);
  • Nenhum dos dois pode ser instanciado diretamente;
  • Derivar de um significa implementar qualquer método abstrato que ele possua, a menos que o tipo derivado também seja abstrato.

De fato, as distinções mais importantes entre classes e interfaces são:

  • As interfaces não podem ter dados particulares;
  • Os membros da interface não podem ter modificadores de acesso (todos os membros são "públicos");
  • Uma classe pode implementar várias interfaces (em vez de geralmente poder herdar de apenas uma classe base).

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 Iqualquer 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".

Aaronaught
fonte
Obrigado por esta repartição. +1 para as "distinções significativas entre classes e interfaces ..."
Charles Sprayberry
24
+1 para "Tudo isso dito, eu prefiro minhas interfaces C # com I de qualquer maneira, porque essa é a convenção .NET usada e defendida pela Microsoft". Isso é motivo suficiente para mim em c #. Seguindo esse padrão comum, é mais provável que outros programadores .NET identifiquem a interface.
Robotsushi 4/11
4
Como alguém que escreve Java e C #, a declaração "Tudo isso foi dito, eu prefiro minhas interfaces de C # com I de qualquer maneira, porque essa é a convenção .NET usada e defendida pela Microsoft" não pode ser subestimada - é uma das coisas que me ajuda a lembrar que língua que eu estou trabalhando,
Aidos
3
Outra diferença no .NET (mas não no Java) é que muitas linguagens .NET não permitem que interfaces contenham métodos estáticos; portanto, invadir Iuma interface pode dar um bom nome para uma classe manter métodos estáticos associados à interface (por exemplo, Enumerable<T>.Emptyou Comparer<T>.Default)
supercat
Eu tenho uma preocupação. No C ++, se você abre um cabeçalho e vê que class Foojá se estende class Bar, não é imediatamente óbvio se class Barestá sendo estendido ou implementado. Então agora você tem que ir e procurar no class Barcabeçalho para decidir se não há problema em modificar class Foopara estender class 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.
Jsj
14

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!

Jim Nutt
fonte
2
+1 para consistência> convenção. Em C #, você prefixaria um I e em Java, não. Diferentes tarefas exigem diferentes convenções
Bringer128
2
+1 enquanto eu pessoalmente preferir não ter Is nas minhas interfaces, ser inconsistente com as bibliotecas BCL e de terceiros usadas em projetos .Net não é uma opção imho.
jk.
13

O livro está cheio de coisas boas, mas eu ainda adicionaria "I" ao nome da interface.

Imagine que você possui public interface ILoguma implementação padrão public class Log.

Agora, se você decidir ter public interface Log, de repente, precisará alterar a classe Log para public class LogDefaultalgo 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.

CodeART
fonte
Isso também é mencionado na documentação
levininja 6/11/14
30
"Imagine que você possui interface pública ILog com uma classe pública de implementação padrão Log". - Então você tem um nome ruim para sua implementação padrão. O que Logfaz? Entrar no console? Para syslog? Para lugar nenhum? Aqueles deve ser chamado ConsoleLog, SyslogLoge NullLog, respectivamente. Lognão é um bom nome para uma classe concreta, porque não é um nome concreto.
Sebastian Redl 29/02
7
Pessoalmente, é exatamente por isso que eu odeio ver ITheClassName, você está apenas criando uma interface sem motivo, é apenas ruído em cima de TheClassName. Se sua interface tem um propósito, deve ser possível para dar-lhe um nome melhor do que ITheClassName
Richard Tingle
O nome da classe é usado uma vez (para instanciar), o nome da interface é usado em qualquer lugar. Adicionar uma letra à interface para salvar a letra no nome da classe é uma economia falsa (de caracteres).
sergut
@RichardTingle Mas acho que o uso comum existe simplesmente para que MyClasstenha 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-1 MyClasspara IMyClassmapeamentos.)
ruffin
8

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.

deadalnix
fonte
@ Mat> Sim, isso foi um erro meu e eu o editei.
Deadalnix 01/11
5

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 escrevesse public 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.

Ela782
fonte
Tem certeza de que isso responde à pergunta? Você pode ler as outras respostas e esclarecer alguns de seus pontos.
David.pfx
C ++ definitivamente possui interfaces, mesmo que não exista uma palavra-chave para isso. Como você chama uma classe em que cada função de membro é pura virtual e não há variáveis ​​de membro?
@ david.pfx: Acho que respondo com precisão à pergunta "Os nomes de interface devem começar com o prefixo" I "?": Depende da linguagem de programação. Se você acha que minha elaboração não é clara o suficiente, fico feliz em melhorá-la - que partes não estão claras para você?
perfil completo de Ela782
2
@JohnGaughan: Claro que tem interfaces! Mas todo o meu ponto é que ele é sobre a palavra-chave. O C ++ não possui um, portanto, não é visível para o IDE / usuário se ele / ela lida com uma interface ou não. Em Java, no entanto, é imediatamente visível.
precisa saber é o seguinte
11
Leia a resposta de melhor classificação e compare a sua. Você é novo no SO, e esta é uma oportunidade para aprender que tipos de respostas atraem votos. Tal como está, a sua não. Com mais trabalho, mais explicações, mais valor, é possível. Mantenha-se firme!
David.pfx 08/04
4

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 é.

Pete
fonte
+1 Siga os idiomas do idioma que você está usando. Obviamente, o autor do livro é um desenvolvedor Java. .NET / C #: ILog Java: Log Mas a desvantagem: quando eu gosto de ter uma classe Log que implementa a interface ILog .... MyLog, LogDefault, LogBase, ...? Feio, não é? Mais feio é: LogImpl ....: D
hfrmobile 11/01
0

No meu código (Java), costumo ter essa convenção nas APIs que expus aos chamadores:

  • A funcionalidade é fornecida por meio de interfaces e nunca por classes.
  • Peças não funcionais são classes.

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.)

Donal Fellows
fonte
Eu também nunca coloco Iprefixos nas interfaces. Do curso é uma interface! Está em uma API (ou SPI)!
Donal Fellows