Con suerte, he estado leyendo " Clean Code " de Robert Martin para convertirme en un mejor programador. Si bien nada de esto hasta ahora ha sido realmente innovador, me ha hecho pensar de manera diferente sobre la forma en que diseño aplicaciones y escribo código.
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 interfaz. Aquí está el texto, tomado directamente del libro. He resaltado el aspecto de esto que encuentro confuso y quisiera aclaraciones.
Prefiero dejar las interfaces sin adornos. El I anterior, tan común en los tacos 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 solo soy un estudiante, o tal vez porque nunca he hecho ninguna programación profesional o en equipo, pero me gustaría que el usuario supiera que es una interfaz. Hay una gran diferencia entre implementar una interfaz y extender una clase.
Entonces, mi pregunta se reduce a: "¿Por qué debemos ocultar el hecho de que alguna parte del código espera 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 debería "filtrar" los detalles de si un tipo dado es una interfaz o una clase de código de terceros? ¿No es importante que el desarrollador externo use mi código para saber si implementarán una interfaz o extenderán una clase? ¿Las diferencias simplemente no son tan importantes como las imagino?
fuente
to know whether they will be implementing an interface or extending a class
: sí, pero la mayoría de los usuarios de su código lo llamarán, no lo implementarán o lo extenderán, y realmente no les importaría cuál es.Respuestas:
Si te detienes a pensarlo, verás que una interfaz realmente no es semánticamente muy diferente de una clase abstracta:
De hecho, las distinciones más importantes entre clases e interfaces son:
Dado que las únicas distinciones particularmente significativas entre clases e interfaces giran en torno a (a) datos privados y (b) jerarquía de tipos, ninguno de los cuales hace la menor diferencia para una persona que llama, generalmente no es necesario saber si un tipo es una interfaz o una clase. Ciertamente no necesitas la indicación visual .
Sin embargo, hay ciertos casos de esquina a tener en cuenta. En particular, si está usando reflexión, intercepción, proxies / mixins dinámicos, tejido de bytecode, generación de código o cualquier cosa que implique meterse directamente con el sistema de mecanografía o el código del entorno, entonces es muy útil y, a veces, es necesario saberlo de inmediato. Bate si estás tratando con una interfaz o una clase. Claramente, no desea que su código falle misteriosamente porque trató de agregar una clase, en lugar de una interfaz, como un mixin.
Sin embargo, para el código de lógica de negocios típico, común y corriente, las distinciones entre clases abstractas e interfaces no necesitan anunciarse porque nunca entrarán en juego.
Dicho todo esto, tiendo a prefijar mis interfaces C # de
I
todos modos porque esa es la convención .NET utilizada y defendida por Microsoft. Y cuando estoy explicando las convenciones de codificación a un nuevo desarrollador, es mucho menos complicado usar las reglas de Microsoft que explicar por qué tenemos nuestras propias reglas "especiales".fuente
I
una interfaz puede dar un buen nombre para que una clase contenga métodos estáticos asociados con la interfaz (p. Ej.Enumerable<T>.Empty
oComparer<T>.Default
)class Foo
ya se extiendeclass Bar
, no es inmediatamente obvio siclass Bar
se está extendiendo o implementando. Así que ahora tiene que ir y mirar en elclass Bar
encabezado para decidir si está bien modificarclass Foo
para extenderclass Baz
. Además, el prefijo I da una pista visual obvia si la "clase base única" se está violando o no, por lo que obtiene un control de cordura cada vez que abre un encabezado.En muchos sentidos, la coherencia es más importante que la convención. Mientras sea coherente en sus esquemas de nombres, no será difícil trabajar con ellos. Prefije las interfaces con un yo si lo desea, o simplemente deje el nombre sin adornos, ¡no me importa siempre que elija un estilo y se quede con él!
fuente
El libro está lleno de cosas buenas, pero aún agregaría "I" al nombre de la interfaz.
Imagina que tienes
public interface ILog
una implementación predeterminadapublic class Log
.Ahora, si decides tenerlo
public interface Log
, de repente tienes que cambiar la clase de Log apublic class LogDefault
algo en esas líneas. Pasaste de tener un personaje extra 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.
fuente
Log
hacer? ¿Iniciar sesión en la consola? ¿A syslog? ¿Hacia la nada? Esos deberían llamarseConsoleLog
,SyslogLog
yNullLog
, respectivamente.Log
no es un buen nombre para una clase concreta, porque no es un nombre concreto.MyClass
tiene una variación burlona , ¿verdad? Es decir, a menudo usamos interfaces para hacer que los métodos públicos sean realmente públicos de una manera que permita las pruebas. (No digo que eso es bueno o malo, pero la comprensión de que la motivación para las interfaces es a menudo simplemente para hacer que las clases que son dependencias fácilmente mockable explica la 1-a-1MyClass
aIMyClass
las asignaciones.)Bueno, esto no se trata de implementar la interfaz o extender una clase. En estos casos, usted sabe de todos modos lo que está haciendo.
Sin embargo, cuando el código de un tercero (otro módulo de la aplicación, por ejemplo) manipula sus datos, este código no debería importarle si presenta una interfaz o una clase.
Este es todo el punto de abstracción. Está presentando a este código de terceros un objeto de un tipo dado. Este tipo dado tiene alguna función miembro a la que puede 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. Entonces, esto es lo que su convención de nomenclatura debe enfatizar.
fuente
La mayoría de las respuestas parecen suponer 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 escribierapublic final FinalMyClass
: imagine 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 encabezado 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 2016: 2 años de experiencia en C ++ más adelante Probablemente ahora consideraría una mala práctica prefijar los nombres de clase
Abstract
, aunque diría que probablemente hay bases de código que son tan complejas que podría tener sentido.fuente
Sigue los modismos del idioma que estás utilizando.
Cada idioma tiene sus propios modismos y pautas de codificación. Por ejemplo, en C #, es idiomático prefijar interfaces con I. En Go, no lo es.
fuente
En mi código (Java), tiendo a tener esta convención en las API que expongo a las personas que llaman:
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 hagan esas clases excepto mantener datos).
En términos de convenciones de nomenclatura, las interfaces tienden a correlacionarse con nombres de actores (por ejemplo,
FooBarWatcher
) o adjetivos (por ejemplo,FooBarWatchable
) y tanto las clases de datos puros como las enumeraciones se asignan a nombres no activos (por ejemplo,FooBarStatus
); El IDE puede guiar al consumidor de API sin convenciones de nomenclatura especiales. Excepciones siguen las convenciones habituales (JavaFooBarException
,FooBarError
,FooBarFault
), por supuesto.A menudo también pongo las interfaces en su propio paquete o incluso en su propia biblioteca, solo para asegurarme de que no tengo la tentación de romper mis propias reglas. (Esto también me ayuda a administrar la compilación cuando obtengo el código de fuentes externas como documentos WSDL).
fuente
I
prefijos en las interfaces. ¡Por supuesto que es una interfaz! ¡Está en una API (o SPI)!