Nomenclatura de interfaz en Java [cerrado]

324

La mayoría de los lenguajes OO prefieren 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 = Interfaz de usuario
  2. Clase = UserImpl, Interfaz = Usuario

Donde en la mayoría de los idiomas:

Clase = Usuario, Interfaz = IUser

Ahora, podría argumentar que siempre puede elegir un nombre más descriptivo para la implementación del usuario y el problema desaparece, pero Java está presionando un enfoque POJO para las cosas y la mayoría de los contenedores IOC usan DynamicProxies ampliamente. Estas dos cosas juntas significan que tendrás 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 hacia dónde se dirigen Java Frameworks?"

Allain Lalonde
fuente
61
"¿Dónde en la mayoría de los idiomas"? ¿Qué idiomas además de los .Net?
wds
2
Las diferentes comunidades lingüísticas tienen diferentes convenciones de nomenclatura, y esto ha sido así durante mucho, mucho tiempo. Descubrir cómo se originaron las convenciones de nomenclatura es a veces esencialmente una investigación folclórica.
David Thornley
44
Eclipse es un valor atípico significativo que utiliza Java con nombres de estilo IFoo. wiki.eclipse.org/Naming_Conventions
David Leonard
2
Si se echa un vistazo a los nombres de interfaces de Android SDK (Java también), verá que utilizan la convención de tener la palabra de interfaz en el extremo de un nombre de interfaz, como NetworkInterface, DialogInterface, etc.
sandalone
21
¿Cómo puede esta pregunta "cerrarse como no constructiva" cuando es tan popular e interesante para tanta gente?
enor

Respuestas:

329

Prefiero no usar un prefijo en las interfaces:

  • El prefijo perjudica la legibilidad.

  • El uso de interfaces en clientes es la mejor forma estándar de programar, por lo que los nombres de las interfaces deben ser lo más cortos y agradables posible. La implementación de clases debería ser más fea para desalentar su uso.

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

starblue
fuente
12
Totalmente de acuerdo. Una tecla más para escribir si usa la función de autocompletar. Muchos archivos que comienzan con una I.
Kalecser
85
Cualquier IDE decente hace que cambiar el código de la manera que describas sea fácil. Además, al cambiar de una clase abstracta a una interfaz, estoy bastante seguro de que sus clientes deberán volver a compilar de todos modos.
Allain Lalonde
63
Súper tarde aquí, pero: no importa en absoluto si un IDE hace que cambiar el nombre de algo sea fácil. El código que usa una instancia de algún tipo nunca debería importarle si ese tipo es una interfaz o una clase o qué. Como tal, exponer ese detalle en el nombre del tipo no tiene sentido y es perjudicial para la comprensión. ¡El tipo y el contrato que expone son lo que importa!
ColinD
11
Además, si va por la ruta de IFoo, ¿no debería ser CFoo para la implementación y, por supuesto, en caso de falla, un método arrojaría un EFoo?
Robin
57
"El prefijo perjudica la legibilidad" es puramente subjetivo. Como son la mayoría de las convenciones de nombres. Es más importante que su equipo llegue a un acuerdo sobre qué hacer para que el código base sea coherente.
dreadwail
121

¿Existe realmente una diferencia entre:

class User implements IUser

y

class UserImpl implements User

si de lo que estamos hablando es de convenciones de nombres?

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

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

class DbBasedAccountDAO implements AccountDAO
class InMemoryAccountDAO implements AccountDAO
tddmonkey
fuente
Creo que le gustaría saber que es un DAO ya que eso describe la funcionalidad general sin necesidad de abrir la clase. Si estoy mirando los archivos de clase en un proyecto, es fácil ver todos los DAO buscando * DAO
Patrick
66
DAO es un patrón bien conocido para el acceso a la base de datos, por lo que tener el patrón en el nombre hace que sea fácil saber qué hace la clase con solo mirar su nombre. PD: Sería mejor seguir estrictamente la notación de camello ("AccountDao") como en mina.apache.org/changes-between-2x-and-1x.html
Esko Luontola
44
@marker, no es como tener una I para indicar una interfaz. DAO le dice que la clase o interfaz es un objeto para acceder a los datos de la cuenta, que es lo que hace el objeto. Tiene un número I le dice su interfaz, que no tiene nada que ver con el objeto en sí, sino semántica del lenguaje
tddmonkey
Como lo presentas, su prefijo vs sufijo.
Andrei Rînea
3
@Andrei: No, es la semántica ("DAO") frente a la decoración innecesaria de un artefacto de lenguaje ("I" como en la interfaz; un hecho, que de todos modos se menciona en el código "interfaz IFoo ...")
Dirk
75

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, se les puede pasar un método 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 nombres más largos con significados reales que los prefijos de estilo húngaro. Para que el código sea lo más legible posible: una Lista representa una lista, y un Usuario representa un usuario, no un IUser.

Avi
fuente
72

También hay otra convención, utilizada por muchos proyectos de código abierto, incluida 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 no siempre se siguen las convenciones, y vigilarlas creará más trabajo que la convención en sí.

ng.
fuente
Me gusta esto, ya que también te ayuda a utilizar interfaces para dependencias externas en lugar de acoplar las clases.
Matt Briggs
47

Como dijo otro cartel, generalmente es preferible que las interfaces definan capacidades, no tipos. Yo tendería a no "implementar" algo como un "Usuario", y es por eso que "IUser" a menudo no es realmente necesario en la forma descrita aquí. A menudo veo 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 en general todavía uso interfaces para modelar comportamientos, acciones, capacidades, propiedades, etc., no tipos.

Además, si realmente solo iba a hacer un Usuario y llamarlo Usuario, ¿cuál es el punto de tener también una interfaz IUser? Y si va a tener algunos tipos diferentes de usuarios que necesitan implementar una interfaz común, ¿qué le ahorra agregar una "I" a la interfaz al elegir los nombres de las implementaciones?

Creo que un ejemplo más realista sería que algunos tipos de usuarios necesitan poder iniciar sesión en una API en particular. Podríamos definir una interfaz de inicio de sesión, y luego tener una clase padre "Usuario" con SuperUser, DefaultUser, AdminUser, AdministrativeContact, etc.

nairbv
fuente
Creo que los ejemplos que proporciona para admitir "interfaces como adjetivos" están sesgados, ya que esas interfaces están destinadas a parecerse más a los mix-ins (o rasgos). Por lo tanto, las interfaces son buenas tanto para adjetivos como para sustantivos, pero probablemente no para indefinite transitive verbs 8 ^ P
Stevel
Esto podría cambiar en los últimos años. El oráculo docu. permite interfaces como tipos: [link] docs.oracle.com/javase/tutorial/java/IandI/interfaceAsType.html
karlihnos
38

Bob Lee dijo una vez en una presentación:

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

entonces, comienza con una implementación, es decir, sin una interfaz. más adelante usted decide, bueno, aquí se necesita una interfaz, por lo que convierte su clase en una interfaz.

entonces se vuelve obvio: su clase original se llamaba Usuario. su interfaz ahora se llama Usuario. tal vez tenga un UserProdImpl y un UserTestImpl. Si diseñaste bien tu aplicación, todas las clases (excepto las que crean una instancia de Usuario) no cambiarán y no notarán que de repente se les pasa una interfaz.

para que quede claro -> Interfaz Implementación del usuario UserImpl.

Andreas Petersson
fuente
18
El uso de interfaces ayuda a probar el desarrollo impulsado. Nos hemos encontrado con numerosos problemas con el Modelo de Dominio y las pruebas porque decidimos NO usar interfaces. Un amigo mío una vez citó: "Todo es una interfaz, te salvará a la larga".
hooknc
44
Burlón y fácil soporte de proxy. Estoy seguro de que también hay otras razones para proporcionar interfaces.
MetroidFan2002
3
Como le dije recientemente a un colega, no cuesta nada introducir una interfaz ahora, pero puede ahorrarle mucho tiempo más adelante.
tddmonkey
2
Si pudiera tener otras implementaciones en un futuro próximo, una interfaz sería una ventaja.
Stef
3
No me gusta el argumento "Podría necesitar otra implicación en el futuro". Prefiero un enfoque YAGNI: no planifiques cosas que aún no han sucedido.
David Lavender
24

En C # es

public class AdminForumUser : UserBase, IUser

Java diría

public class AdminForumUser extends User implements ForumUserInterface

Debido a 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 solo elija cualquier convención de nomenclatura que desee, siempre que sea constante y use algo para mostrar a las personas que estas son interfaces. No he hecho Java en unos años, pero todas las interfaces estarían en su propio directorio, y esa era la convención. Realmente nunca tuve problemas con eso.

Matt Briggs
fuente
22
Tal vez soy un mal programador de Java, pero prefiero el estilo C #, significa que todas las interfaces comienzan con el prefijo 'I' :)
davs
77
No estoy seguro de dónde tú y otros están obteniendo esta supuesta convención. No es evidente en las bibliotecas de Java ...
ChiefTwoPencils
6

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

Por ejemplo, en su caso, solo esperaría ver IUsersi el único usuario que tiene la intención de tener es User. Si usted planea tener diferentes tipos de usuarios - NoviceUser, ExpertUser, etc. - Yo esperaría ver una Userinterfaz (y, tal vez, una AbstractUserclase que implementa algunas funciones comunes, comoget/setName() ).

También esperaría interfaces que definen capacidades - Comparable, Iterable, etc - para ser nombrado como esa, y no como IComparableo IIterable.

David Koelle
fuente
Si el único usuario que tiene la intención de tener es Usuario, ¿por qué no usar Usuario en lugar de la interfaz?
Carighan
3
En algunas arquitecturas cliente / servidor, el lado del cliente necesita conocer las interfaces sin necesidad de implementaciones de servidores pesados.
David Koelle
5

Siguiendo buenos principios de 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 "BankAccount" (por ejemplo), en lugar de "IUser", "UserInterface" u otras variaciones.

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

Si hace esto, los nombres de clase concretos "feos" como "UserImpl" deberían ocultarse de forma segura del resto del código, lo que puede continuar utilizando los nombres de interfaz "agradables".

KarstenF
fuente
Pero, ¿por qué molestarse en hacer una interfaz coincidente para cada clase en su programa cuando solo necesita interfaces para una o dos cosas?
LegendLength
3

= v = El prefijo "I" también se usa en el marco de Wicket, donde me acostumbré rápidamente. En general, agradezco cualquier convención que acorte los engorrosos nombres de clase de Java. Sin embargo, es una molestia que todo esté alfabetizado bajo "I" en los directorios y en el Javadoc.

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

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

Jym Dyer
fuente
0

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

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

David Thornley
fuente