Nomenclatura de interfaz en Java

La mayoría de los lenguajes OO anteponen sus nombres de interfaz con una I mayúscula, ¿por qué Java no hace esto? ¿Cuál fue la razón para no seguir esta convención?

Para demostrar lo que quiero decir, si quisiera tener una interfaz de usuario y una implementación de usuario, tendría dos opciones en Java:

  1. Clase = Usuario, Interfaz = UserInterface
  2. Clase = UserImpl, Interfaz = Usuario

Donde en la mayoría de los idiomas:

Clase = Usuario, Interfaz = Usuario

Ahora, podría argumentar que siempre podría elegir un nombre más descriptivo para la implementación del usuario y que el problema desaparece, pero Java está impulsando un enfoque POJO a las cosas y la mayoría de los contenedores IOC usan DynamicProxies extensamente. Estas dos cosas juntas significan que tendrá muchas interfaces con una sola implementación de POJO.

Entonces, supongo que mi pregunta se reduce a: “¿Vale la pena seguir la convención de nomenclatura de interfaz más amplia, especialmente a la luz de a dónde parece dirigirse Java Frameworks?”

Prefiero no usar un prefijo en las interfaces:

  • El prefijo daña la legibilidad.

  • El uso de interfaces en los clientes es la mejor manera estándar de progtwigr, por lo que los nombres de las interfaces deben ser lo más cortos y agradables posible. Las clases de implementación deberían ser más feas para desalentar su uso.

  • Al cambiar de una clase abstracta a una interfaz, una convención de encoding con prefijo I implica renombrar todas las ocurrencias de la clase — ¡no es bueno!

¿Hay realmente una diferencia entre:

 class User implements IUser 

y

 class UserImpl implements User 

si todo lo que estamos hablando es nombrar convenciones?

Personalmente, prefiero NO preceder a la interfaz con I porque quiero codificar la interfaz y considero que es más importante en términos de la convención de nomenclatura. Si llama a la interfaz IUser entonces cada consumidor de esa clase necesita saber que es un IUser . Si llama a la clase UserImpl entonces solo la clase y su contenedor DI saben sobre la parte Impl y los consumidores solo saben que están trabajando con un User .

Por otra parte, las veces que me he visto obligado a utilizar Impl porque un nombre mejor no se presenta han sido pocas y distantes entre sí porque la implementación se nombra de acuerdo con la implementación porque es allí donde es importante, por ejemplo

 class DbBasedAccountDAO implements AccountDAO class InMemoryAccountDAO implements AccountDAO 

Puede haber varias razones por las que Java generalmente no usa la convención IUser.

  1. Parte del enfoque Orientado a Objetos es que no debería tener que saber si el cliente está utilizando una interfaz o una clase de implementación. Entonces, incluso List es una interfaz y String es una clase real, un método podría pasarse a ambos: no tiene sentido distinguir visualmente las interfaces.

  2. En general, preferiremos el uso de interfaces en el código del cliente (por ejemplo, preferir List a ArrayList). Por lo tanto, no tiene sentido hacer que las interfaces se destaquen como excepciones.

  3. La convención de nomenclatura de Java prefiere los nombres más largos con significados reales a los prefijos de estilo húngaro. Entonces, ese código será lo más legible posible: una Lista representa una lista y un Usuario representa un usuario, no un Usuario IU.

También hay otra convención, utilizada por muchos proyectos de código abierto, incluido Spring.

 interface User { } class DefaultUser implements User { } class AnotherClassOfUser implements User { } 

Personalmente, no me gusta el prefijo “I” por la simple razón de que es una convención opcional. Entonces, si adopto esto ¿IIOPConnection significa una interfaz para IOPConnection? ¿Qué pasa si la clase no tiene el prefijo “I”, entonces sé que no es una interfaz … la respuesta aquí es no, porque las convenciones no siempre se siguen, y su vigilancia creará más trabajo que la propia convención guarda.

Como dijo otro afiche, generalmente es preferible que las interfaces definan capacidades, no tipos. Tiendo a no “implementar” algo así como un “Usuario”, y esta es la razón por la que “IUser” a menudo no es realmente necesario en la forma descrita aquí. A menudo veo las clases como sustantivos e interfaces como adjetivos:

 class Number implements Comparable{...} class MyThread implements Runnable{...} class SessionData implements Serializable{....} 

A veces, un Adjetivo no tiene sentido, pero aún así generalmente usaría interfaces para modelar comportamiento, acciones, capacidades, propiedades, etc., … no tipos.

Además, si realmente solo hiciera un Usuario y lo llamara Usuario, ¿qué sentido tiene tener también una interfaz IUser? Y si va a tener algunos tipos diferentes de usuarios que necesiten implementar una interfaz común, ¿qué significa que agregar una “I” a la interfaz lo salve al elegir los nombres de las implementaciones?

Creo que un ejemplo más realista sería que algunos tipos de usuarios deben poder iniciar sesión en una API en particular. Podríamos definir una interfaz de inicio de sesión y luego tener una clase principal “Usuario” con SuperUser, DefaultUser, AdminUser, AdministrativeContact, etc. suclasses, algunos de los cuales implementarán o no la interfaz de inicio de sesión (¿Se puede iniciar sesión?) Según sea necesario.

Bob Lee dijo una vez en una presentación:

cuál es el objective de una interfaz si solo tiene una implementación.

entonces, comienzas con una implementación, es decir, sin una interfaz. más tarde, usted decide, bueno, aquí hay una necesidad de una interfaz, de modo que convierta su clase a una interfaz.

entonces se vuelve obvio: tu clase original se llamaba Usuario. su interfaz ahora se llama Usuario. tal vez tengas un UserProdImpl y un UserTestImpl. si diseñó bien su aplicación, todas las clases (excepto las que instancian al Usuario) permanecerán sin cambios y no notarán que de repente pasan una interfaz.

para que quede claro -> Interface User implementation UserImpl.

En C # es

 public class AdminForumUser : UserBase, IUser 

Java diría

 public class AdminForumUser extends User implements ForumUserInterface 

Por eso, no creo que las convenciones sean tan importantes en Java para las interfaces, ya que existe una diferencia explícita entre la herencia y la implementación de la interfaz. Yo diría que simplemente elija cualquier convención de nomenclatura que desee, siempre y cuando sea constante y use algo para mostrarle a la gente que estas son interfaces. No han hecho Java en unos años, pero todas las interfaces estarían en su propio directorio, y esa era la convención. Nunca tuve ningún problema con eso.

En mi experiencia, la convención “I” se aplica a las interfaces que pretenden proporcionar un contrato a una clase, particularmente cuando la interfaz en sí misma no es una noción abstracta de la clase.

Por ejemplo, en su caso, solo esperaría ver a IUser si el único usuario que alguna vez pretende tener es el User . Si planea tener diferentes tipos de usuarios: usuario NoviceUser , ExpertUser , etc., esperaría ver una interfaz de User (y, tal vez, una clase de User AbstractUser que implemente alguna funcionalidad común, como get/setName() ).

También esperaría que las interfaces que definen capacidades ( Comparable , Iterable , etc.) se denominen así, y no como IComparable o IIterable .

Siguiendo los buenos principios OO, su código debería (en la medida de lo posible / práctico) depender de abstracciones en lugar de clases concretas. Por ejemplo, generalmente es mejor escribir un método como este:

 public void doSomething(Collection someStuff) { ... } 

que esto:

 public void doSomething(Vector someStuff) { ... } 

Si sigues esta idea, entonces mantengo que tu código será más legible si le das nombres de interfaces como “Usuario” y “Cuenta bancaria” (por ejemplo), en lugar de “UsuarioI”, “Interfaz de usuario” u otras variaciones.

Los únicos trozos de código que deberían preocuparse por las clases de hormigón reales son los lugares donde se construyen las clases concretas. Todo lo demás debe escribirse usando las interfaces.

Si haces esto, entonces los nombres de clase concretos “feos” como “UserImpl” deberían estar ocultos de forma segura del rest del código, que alegremente puede continuar usando los nombres de interfaz “agradables”.

= v = El prefijo “I” también se usa en el marco de Wicket, donde me acostumbré rápidamente. En general, doy la bienvenida a cualquier convención que acorte los engorrosos nombres de clase de Java. Sin embargo, es una molestia que todo esté ordenado alfabéticamente en “I” en los directorios y en el Javadoc.

La práctica de encoding Wicket es similar a Swing, ya que muchas instancias de control / widgets se construyen como clases internas anónimas con declaraciones de métodos en línea. Curiosamente, difiere 180 ° de Swing en que Swing usa un prefijo (“J”) para las clases de implementación.

El sufijo “Impl” es una abreviatura mangly y no se internacionaliza bien. Si al menos hubiéramos ido con “Imp” sería más lindo (y más corto). “Impl” se usa para IOC, especialmente Spring, por lo que estamos más o menos atrapados por el momento. Sin embargo, se vuelve un poco esquizo siguiendo 3 convenciones diferentes en tres partes diferentes de una base de código.

¿Es esta una convención de nomenclatura más amplia en algún sentido real? Estoy más en el lado de C ++, y no realmente en Java y descendientes. ¿Cuántas comunidades lingüísticas usan la I convención?

Si tiene una convención de nomenclatura estándar de tienda independiente del idioma aquí, úselo. Si no, vaya con la convención de nomenclatura del idioma.

Intereting Posts