¿Cuál es el razonamiento detrás de la convención de nomenclatura de prefijo "I" para las interfaces en .NET?

10

Sé que la convención "I" ha existido desde COM, pero nunca he entendido por qué no se ha reconsiderado como cualquier otra convención de nombres antes .NET.

En cuanto al consumo, lo único que separa una interfaz de, por ejemplo, una clase abstracta, es que pueden heredarse de forma múltiple. Pero todo después de Visual Studio 2003 ha mostrado firmas de tipo en la información sobre herramientas, por lo que es tan inútil como todas las otras anotaciones húngaras que se han descartado.

También pensé que podría ser para que pueda tener una implementación básica de la interfaz con el mismo nombre, por ejemplo , Messageheredando IMessage, pero la mayoría de las bibliotecas .NET han optado por agregar la palabra "Base" al final (por ejemplo System.Collections.ReadOnlyCollectionBase). y esto tiene más sentido semántico.

La interoperabilidad COM parece ser otra razón posible, pero no es como si las clases de contenedor que genera son .NET perfectamente idiomáticas, por lo que dudo que haya sido una consideración estética.

En uno de mis proyectos más nuevos, he renunciado a la convención por completo, y se siente muy bien. ¿Se me escapa algo?

Rei Miyasaka
fuente
1
No heredas las interfaces para cumplirlas, gran diferencia.
Daniel Little
También parece una preferencia como IList y List en lugar de List y ArrayList. Probablemente lo hicieron porque IList no es una ListBase pero realmente es una ListInterface (no una lista de interfaz de tipo), si entiendes lo que quiero decir.
Daniel Little
@Lavinski In .NET IListes un término general para una colección secuenciada, contigua, acceso aleatorio, mientras que Listes una colección secuenciada, contigua, aleatoria, en crecimiento . Creo F # tenía la razón en aliasing Lista ResizeArray; ese es definitivamente un nombre mucho más descriptivo. IListentonces podría haber sido List, así que tampoco parece ser una razón.
Rei Miyasaka
2
IBaseBall e IBaseBallBase tiene más sentido para mí que BaseBallBase y BaseBallBaseBase (ejemplo tonto, lo sé: D)
e-MEE
@ e-MEE igualmente tonto sería IIRC, que podría ser una interfaz para el protocolo de chat IRC, o el acrónimo de "si no recuerdo mal".
Rei Miyasaka

Respuestas:

12

Creo que este puede ser el único caso cuando los prefijos son útiles.

Las clases y las interfaces realmente tienen una semántica diferente, y debido a que ambos son tipos, son fáciles de mezclar.
Cuando veo una declaración de clase, puedo decir instantáneamente de qué se deriva y qué implementa :

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

Sería más difícil de entender si la definición se pareciera a

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

¿Y cómo llamarías ListClass? Claramente, no es solo ListBaseporque se puede usar por sí solo.
Entonces, tenemos que resolver un problema que acabamos de inventar o adaptar un prefijo que separe las clases de las interfaces, que es lo que hicieron los diseñadores de .NET Framework.

Además, personalmente me parece útil cuando puedo decir por la firma del método que funciona con interfaces.

public void PrintLines (IEnumerable<string> source)

Es como una señal para mi cabeza: ¡hey, puedo implementar esto! Puedo alimentar el método lo que coincida con el contrato.

Por supuesto, uno puede argumentar que no es tan importante, pero esta es una de esas pequeñas cosas que hacen que el prefijo valga la pena para mí. Es especialmente útil cuando se escribe mucho código con contenedores IoC cuando trabajas constantemente con interfaces y necesitas diferenciar fácilmente entre los dos.

Por cierto, no solo las interfaces tienen prefijos en el sistema de tipo .NET. No te olvides de los parámetros de tipo genérico:

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

Esta es otra situación en la que es extremadamente útil poder diferenciar entre clases y otro tipo de tipos.

Dan
fuente
2
Puede comprender fácilmente que al saber que "la primera clase es herencia, la segunda clase y las demás son interfaces".
Saeed Neamati
3
Esto parece una razón plausible. Java parece haber resuelto un poco más bien por el simple uso de palabras clave para aclarar la lista: class Dog extends Mammal implements MailmanChaser. @Saeed puede tener una clase que no herede de nada, por lo que el primer tipo de la lista es en realidad una interfaz en lugar de una clase base.
Rei Miyasaka
+1 para la parte en negrita, aunque puedo pensar en otro lugar donde una convención basada en prefijo hubiera sido útil: distinguir entre un campo que encapsula la propiedad exclusiva de un int[](u otro objeto de tipo mutable) que puede mutar pero no compartir, y uno que encapsula la propiedad compartida de un int[]que, a pesar de que su tipo permitiría la mutación, a nadie se le permite mutar.
supercat
6

No creo que te pierdas nada, es solo un hábito histórico.

También estoy de acuerdo con usted y también he dejado caer el 'yo' en un par de proyectos pequeños a medianos sin ningún efecto perjudicial.

Chris Lee
fuente
2
Sin embargo, lo extraño es que descartaron prácticamente cualquier otra convención obsoleta, excepto esta. La historia tampoco lo explica del todo. Todavía siento que debe haber una razón, a menos que realmente se tratara solo de política interna, pero aun así, realmente no puedo ver una razón por la que alguien se enojaría por el hecho de que me dejaran caer.
Rei Miyasaka
2

Creo que la única razón, de acuerdo con las Pautas de nomenclatura de Microsoft sobre interfaces y clases , es que, a veces, hay conflictos entre el nombre de la interfaz y la clase que lo implementa. Esto se remonta al hecho de que las interfaces son, de hecho, el esqueleto, no la carne, y la clase implementadora es, de hecho, la carne (darse cuenta del plano). Por lo tanto, IAnimal solo describe lo que debe tener un animal , mientras que Animal puede decirle lo que tiene .

Sin embargo, personalmente estoy completamente de acuerdo con usted en el punto de que simplemente podríamos usar Animal Base para la interfaz y Animal para la clase.

Por otro lado, a veces dos cosas son tan conflictivas que un equipo decide proporcionar una convención para evitar más conflictos, a pesar de las decisiones ya tomadas. Por ejemplo, en ASP.NET MVC, tanto las Vistas parciales como los Diseños (páginas maestras) son como una Vista normal , a la vez que ofrecen una funcionalidad diferente. Por lo tanto, Microsoft, a pesar de enfatizar no utilizar guiones bajos en los nombres, sugiere subrayar los diseños y las vistas parciales con un guión bajo.

Saeed Neamati
fuente
¿Qué tiene de malo en AnimalInterfacelugar de AnimalBase? No es una clase base, es una interfaz.
Scott Whitlock
3
Pero, ¿qué hay de malo con IAnimal en lugar de AnimalInterface? seguro que hemos recorrido todo el camino hasta donde comenzamos, lo que demuestra que algunas de las anotaciones 'húngaras' fueron útiles. Tirarlos a todos (a excepción de I y T) fue más picante en lugar de un intento reflexivo de encontrar un sistema mejor.
gbjbaanb
2
@ScottWhitlock: Para mí, IAnimales mucho más legible que AnimalInterface. Los nombres detallados son preferibles, excepto en los casos en que una simple convención corta se puede utilizar para algo que ocurre con la frecuencia suficiente. Y las interfaces son un caso así.
maaartinus