Qual é o raciocínio por trás da convenção de nomenclatura de prefixo "I" para interfaces no .NET?

10

Eu sei que a convenção "I" existe desde COM, mas nunca entendi por que ela não foi reconsiderada como todas as outras convenções de nomenclatura anteriores ao .NET.

Em termos de consumo, a única coisa que separa uma interface de, digamos, uma classe abstrata, é que elas podem ser multiplicadas por herança. Mas tudo depois do Visual Studio 2003 mostrou assinaturas de tipo nas dicas de ferramentas, por isso é tão inútil quanto todas as outras notações húngaras que foram descartadas.

Eu também pensei que poderia ser para que você pudesse ter uma implementação básica da interface com o mesmo nome, por exemplo , Messageherdar IMessage, mas a maioria das bibliotecas do .NET optou por adicionar a palavra "Base" no final (por exemplo System.Collections.ReadOnlyCollectionBase) - e isso faz mais sentido semântico.

A interoperabilidade COM parece ser outro motivo possível - mas não é como se as classes de wrapper que ele gerasse fossem .NET perfeitamente idiomáticas, então duvido que essa tenha sido uma consideração estética.

Em um dos meus projetos mais recentes, perdi completamente a convenção e ela parece bem. Tem algo que estou perdendo?

Rei Miyasaka
fonte
11
Você não herda interfaces para cumpri-las, grande diferença.
Daniel Little
Também parece preferência como IList e List em oposição a List e ArrayList. Eles provavelmente fizeram isso porque IList não é um ListBase, mas realmente é um ListInterface (não uma lista do tipo interface), se você entende o que quero dizer.
Daniel Little
@Lavinski No .NET IListé um termo geral para uma coleção seqüencial e contígua, de acesso aleatório, enquanto que Listé uma coleção sequencial, contínua e contígua de acesso aleatório e crescente . Eu acho que o F # tinha razão em usar alias Listpara ResizeArray; esse é definitivamente um nome muito mais descritivo. IListentão poderia ter sido List, de modo que não parece que seria uma razão também.
Rei Miyasaka
2
IBaseBall e IBaseBallBase faz mais sentido para mim do que BaseBallBase e BaseBallBaseBase (exemplo bobo, eu sei: D)
e-MEE
@ e-MEE igualmente tolo seria o IIRC, que poderia ser uma interface para o protocolo de bate-papo do IRC ou o acrônimo de "se bem me lembro".
Rei Miyasaka

Respostas:

12

Eu acho que esse pode ser o único caso em que prefixos são úteis.

Classes e interfaces realmente têm semânticas diferentes e, como ambos são tipos, são fáceis de misturar.
Quando vejo uma declaração de classe, posso dizer instantaneamente do que deriva e do que implementa :

public sealed class ActivityCollection : List<Activity>, 
    IList<Activity>, ICollection<Activity>, IEnumerable<Activity>, 
    IList, ICollection, IEnumerable

Seria mais difícil entender se a definição parecesse

public sealed class ActivityCollection : ListClass<Activity>, 
    List<Activity>, Collection<Activity>, Enumerable<Activity>, 
    List, Collection, Enumerable

E como você ligaria ListClass? Claramente, não é apenas ListBaseporque é utilizável por si só.
Portanto, precisamos resolver um problema que acabamos de inventar ou adaptar um prefixo que separa as classes das interfaces, o que os designers do .NET Framework fizeram.

Além disso, pessoalmente acho útil quando posso dizer pela assinatura do método que ele funciona com interfaces.

public void PrintLines (IEnumerable<string> source)

É como um sinal para minha cabeça: ei, eu posso implementar isso! Eu posso alimentar o método conforme o contrato.

É claro que se pode argumentar que não é tão importante, mas essa é uma daquelas pequenas coisas que fazem o prefixo valer a pena para mim. É especialmente útil ao escrever muito código com contêineres IoC quando você trabalha constantemente com interfaces e precisa diferenciar facilmente entre os dois.

A propósito, não apenas as interfaces têm prefixos no sistema de tipos .NET. Não se esqueça dos parâmetros de tipo genérico:

public delegate TResult Func<in T, out TResult>(
    T arg
)

Essa é outra situação em que é extremamente útil poder diferenciar classes e outro tipo de tipos.

Dan
fonte
2
Você pode entender facilmente que, sabendo que "a primeira classe é herança, a segunda classe e adiante são interfaces".
Saeed Neamati 15/09/11
3
Esta parece ser uma razão plausível. Java parece ter resolvido um pouco mais bem simplesmente usando palavras-chave para esclarecer a lista: class Dog extends Mammal implements MailmanChaser. @Saeed, você pode ter uma classe que não herda de nada; portanto, o primeiro tipo da lista é na verdade uma interface, e não uma classe base.
Rei Miyasaka
+1 para a parte em negrito, embora eu possa pensar em outro lugar onde uma convenção baseada em prefixos teria sido útil: distinguir entre um campo que encapsula a propriedade exclusiva de um int[](ou outro objeto de tipo mutável) que ele pode sofrer mutação, mas não share, e um que encapsule a propriedade compartilhada de um int[]que, mesmo que seu tipo permita mutação, ninguém pode sofrer mutação.
Supercat 8/15
6

Não acho que você esteja perdendo nada, é apenas um hábito histórico.

Também concordo com você e também reduzi o 'eu' em alguns projetos de pequeno a médio porte, sem efeito prejudicial.

Chris Lee
fonte
2
O que é estranho, porém, é que eles jogaram praticamente todas as outras convenções obsoletas, exceto esta. A história também não explica isso. Eu ainda sinto que deve ter havido uma razão, a menos que realmente fosse apenas política interna - mas, mesmo assim, eu realmente não consigo ver uma razão pela qual alguém ficaria chateado com o fato de eu ser descartada.
Rei Miyasaka
2

Penso que o único motivo, de acordo com as Diretrizes de Nomenclatura da Microsoft sobre Interfaces e Classes , é que, às vezes, há conflitos entre o nome da interface e a classe que a implementa. Isso remonta ao fato de que as interfaces são, de fato, o esqueleto, não a carne, e a classe implementadora é de fato a carne (percebendo o modelo). Assim, o IAnimal está apenas descrevendo o que um animal deve ter , enquanto o Animal pode lhe dizer o que possui .

No entanto, eu pessoalmente concordo totalmente com você no ponto em que poderíamos simplesmente usar o Animal Base para a interface e o Animal para a classe.

Por outro lado, às vezes duas coisas são tão conflitantes que uma equipe decide oferecer uma convenção para evitar conflitos adicionais, apesar das decisões já tomadas. Por exemplo, no ASP.NET MVC, exibições parciais e layouts (páginas mestras), são exatamente como uma exibição normal , enquanto servem funcionalidades diferentes. Assim, apesar de enfatizar a não utilização de sublinhado na nomeação, a Microsoft sugere sublinhar layouts e vistas parciais com um sublinhado.

Saeed Neamati
fonte
O que há de errado em AnimalInterfacevez de AnimalBase? Não é uma classe base, é uma interface.
Scott Whitlock
3
mas o que há de errado com IAnimal em vez de AnimalInterface? Certamente, fomos até onde começamos - o que apenas mostra que algumas das notações 'húngaras' foram úteis. Jogá-los todos fora (exceto I e T) foi mais desagradável do que uma tentativa cuidadosa de encontrar um sistema melhor.
gbjbaanb
2
@ Scott Whitlock: Para mim, IAnimalé muito mais legível do que AnimalInterface. Nomes detalhados são preferíveis, exceto nos casos em que uma simples convenção curta pode ser usada para algo que ocorre com freqüência suficiente. E interfaces são esse caso.
Maaartinus