¿Los nombres de interfaz deben comenzar con un prefijo "I"?

67

He estado leyendo " Clean Code " de Robert Martin para, con suerte, convertirse en un mejor programador. Aunque hasta ahora nada de eso ha sido realmente innovador, me ha hecho pensar de manera diferente sobre la forma en que diseño aplicaciones y escribo códigos.

Hay una parte del libro con la que no solo no estoy de acuerdo, sino que no tiene sentido para mí, específicamente en lo que respecta a las convenciones de nombres de interfaces. Aquí está el texto, tomado directamente del libro. Me he negado al aspecto de esto que me parece confuso y me gustaría aclararlo.

  

Prefiero dejar las interfaces sin adornos. El I anterior, tan común en los fajos heredados de hoy, es una distracción en el mejor de los casos y demasiada información en el peor. No quiero que mis usuarios sepan que les estoy entregando una interfaz .

Tal vez sea porque soy solo un estudiante, o tal vez porque nunca he hecho ninguna programación profesional o en equipo, pero quisiera que el usuario supiera que es una interfaz. Hay una gran diferencia entre implementar una interfaz y extender una clase.

Por lo tanto, mi pregunta se reduce a, "¿Por qué debemos ocultar el hecho de que alguna parte del código está esperando una interfaz?"

Editar

En respuesta a una respuesta:

  

Si su tipo es una interfaz o una clase es su negocio, no el negocio de alguien que usa su código. Por lo tanto, no debe filtrar detalles de su código en este código de terceros.

¿Por qué no debo "filtrar" los detalles de si un tipo dado es una interfaz o una clase a un código de terceros? ¿No es importante para el desarrollador externo que use mi código saber si implementarán una interfaz o ampliarán una clase? ¿Las diferencias simplemente no son tan importantes como lo estoy haciendo para que estén en mi mente?

    
pregunta Charles Sprayberry 01.11.2011 - 22:50

7 respuestas

64

Si te paras a pensar en ello, verás que una interfaz realmente no es semánticamente muy diferente de una clase abstracta:

  • Ambos tienen métodos y / o propiedades (comportamiento);
  • Ninguno debe tener campos no privados (datos);
  • Ninguno puede ser instanciado directamente;
  • Derivar de uno significa implementar cualquier método abstracto que tenga, a menos que el tipo derivado también sea abstracto.

De hecho, las distinciones más importantes entre clases e interfaces son:

  • Las interfaces no pueden tener datos privados;
  • Los miembros de la interfaz no pueden tener modificadores de acceso (todos los miembros son "públicos");
  • Una clase puede implementar múltiples interfaces (en lugar de poder generalmente heredar de una sola clase base).

Dado que las únicas distinciones particularmente significativas entre clases e interfaces giran en torno a (a) datos privados y (b) jerarquía de tipos, ninguna de las cuales hace la menor diferencia con respecto a la persona que llama, generalmente no es necesario saber si un tipo es una interfaz o una clase. Ciertamente no necesita la indicación visual .

Sin embargo, hay ciertos casos de esquina a tener en cuenta. En particular, si está utilizando reflexión, intercepción, proxies / mixins dinámicos, entramado de código de bytes, generación de código, o cualquier cosa que involucre manipular directamente con el sistema de escritura del entorno o el código en sí, es muy útil y a veces es necesario saber de inmediato si se trata de una interfaz o una clase. Claramente, no quieres que tu código falle misteriosamente porque intentaste agregar una clase, en lugar de una interfaz, como una mezcla.

Sin embargo, para el código lógico de negocios típico de Vanilla, run-of-the-mill, las distinciones entre clases abstractas e interfaces no necesitan publicitarse porque nunca entrarán en juego.

Dicho todo esto, tiendo a prefijar mis interfaces C # con I de todas formas porque esa es la convención .NET utilizada y recomendada por Microsoft. Y cuando explico las convenciones de codificación a un nuevo desarrollador, es mucho menos complicado simplemente usar las reglas de Microsoft que explicar por qué tenemos nuestras propias reglas "especiales".

    
respondido por el Aaronaught 02.11.2011 - 02:20
13

En muchos sentidos, la consistencia es más importante que la convención. Siempre que sea consistente con sus esquemas de nombres, no será difícil trabajar con ellos. Si prefieres, el prefijo se interconecta con una I, o simplemente deja el nombre sin adornos, no me importa, siempre que elijas un estilo y te mantengas en él.

    
respondido por el Jim Nutt 02.11.2011 - 15:13
11

El libro está lleno de cosas buenas, pero igual agregaría "I" al nombre de la interfaz.

Imagina que tienes public interface ILog con una implementación predeterminada public class Log .

Ahora, si decides tener public interface Log , de repente tienes que cambiar la clase de registro a public class LogDefault o algo en esas líneas. Pasaste de tener un personaje adicional a siete, seguramente eso es un desperdicio.

A menudo hay una delgada línea entre la teoría y la práctica. En teoría, esta es una muy buena idea, pero en la práctica no es tan buena.

    
respondido por el CodeART 08.04.2014 - 11:55
8

Bueno, no se trata de implementar la interfaz o extender una clase. En estos casos, ya sabes lo que estás haciendo.

Sin embargo, cuando el código de terceros (otro módulo de la aplicación, por ejemplo) manipula sus datos, este código no debería preocuparse si presenta una interfaz o una clase.

Este es el punto entero de la abstracción. Usted está presentando a este código de terceros un objeto de un tipo determinado. Este tipo dado tiene alguna función miembro a la que puedes llamar. Eso es suficiente.

Si su tipo es una interfaz o una clase es su negocio, no el negocio de alguien que usa su código. Por lo tanto, no debe filtrar detalles de su código a este código de terceros.

Por cierto, las interfaces y las clases son tipos de referencia al final. Y esto es lo que importa. Así que esto es lo que debe resaltar su convención de nomenclatura.

    
respondido por el deadalnix 01.11.2011 - 22:58
5

La mayoría de las respuestas parecen asumir que el lenguaje de programación es Java o C # donde hay un concepto (o palabra clave) para interfaces / clases abstractas. En estos casos, en un IDE decente, es inmediatamente visible con qué tipo de clase uno trata y la escritura public interface IMyClass es una duplicación innecesaria. Es como si no escribieras public final FinalMyClass - imagina poner cada palabra clave en el nombre de la clase.

Sin embargo, en mi opinión en C ++, la situación es un poco diferente, ya que uno tiene que sumergirse en el archivo de cabecera y ver si la clase tiene algún método virtual para averiguar si es una clase abstracta. En ese caso, puedo ver claramente un argumento para escribir class AbstractMyClass .

Entonces mi respuesta sería: depende del lenguaje de programación.

Actualizado en 2016: 2 años de experiencia en C ++ más tarde ahora probablemente consideraría una mala práctica prefijar los nombres de clase con Abstract , aunque diría que probablemente hay bases de código que son tan complejas para que tenga sentido.

    
respondido por el Ela782 08.04.2014 - 11:49
3

Siga las expresiones idiomáticas del idioma que está utilizando.

Cada idioma tiene sus propios modismos y pautas de codificación. Por ejemplo, en C #, es idiomático prefijar las interfaces con I. En Go, no lo es.

    
respondido por el Pete 29.02.2016 - 11:03
0

En mi código (Java), tiendo a tener esta convención en las API que expongo a las personas que llaman:

  • La funcionalidad se proporciona a través de interfaces, y nunca por clases.
  • Las partes no funcionales son clases.

Por no funcional, me refiero a cosas como estructuras de datos puros (como clases que actúan como puentes para la serialización XML o el ORM), enumeraciones y excepciones, todas las cuales no pueden ser interfaces (bueno, puede hacerlo para las clases de datos puros, pero es mucho trabajo para muy poca ganancia ya que no hay nada que esas clases excepto contengan datos).

En términos de convenciones de nomenclatura, las interfaces tienden a asignarse a los nombres de los actores (por ejemplo, FooBarWatcher ) o a los adjetivos (por ejemplo, FooBarWatchable ) y tanto las clases de datos puros como las enumeraciones se asignan a los nombres no activos (por ejemplo,% código%); El IDE puede guiar al consumidor de API sin convenciones de nomenclatura especiales. Las excepciones siguen las convenciones habituales de Java ( FooBarStatus , FooBarException , FooBarError ), por supuesto.

También a menudo pondré las interfaces en su propio paquete o incluso en su propia biblioteca, solo para garantizar que no esté tentado de romper mis propias reglas. (Esto también me ayuda a administrar la compilación cuando estoy derivando el código de fuentes externas, como documentos WSDL).

    
respondido por el Donal Fellows 02.11.2011 - 12:42

Lea otras preguntas en las etiquetas