Soy nuevo en un equipo que trabaja en un proyecto bastante grande, con muchos componentes y dependencias. Para cada componente, hay un interfaces
paquete donde se colocan las interfaces expuestas para ese componente. ¿Es esta una buena practica?
Mi práctica habitual siempre ha sido que las interfaces y las implementaciones vayan en el mismo paquete.
Respuestas:
Colocar tanto la interfaz como la implementación es un lugar común y no parece ser un problema.
Tomemos, por ejemplo, la API de Java: la mayoría de las clases tienen ambas interfaces y sus implementaciones incluidas en el mismo paquete.
Tomemos, por ejemplo, el
java.util
paquete:Contiene los interfaces como
Set
,Map
,List
, mientras que también tiene las implementaciones tales comoHashSet
,HashMap
yArrayList
.Además, los Javadocs están diseñados para funcionar bien en esas condiciones, ya que separa la documentación en las vistas Interfaces y Clases al mostrar el contenido del paquete.
Tener paquetes solo para interfaces puede ser un poco excesivo, a menos que haya una gran cantidad de interfaces. Pero separar las interfaces en sus propios paquetes por el simple hecho de hacerlo parece una mala práctica.
Si es necesario diferenciar el nombre de una interfaz de una implementación, se podría tener una convención de nomenclatura para facilitar la identificación de las interfaces:
Prefije el nombre de la interfaz con un
I
. Este enfoque se toma con las interfaces en el marco .NET. Sería bastante fácil decir queIList
es una interfaz para una lista.Utilice el
able
sufijo - . Este enfoque se ve a menudo en la API de Java, como por ejemploComparable
,Iterable
ySerializable
para nombrar unos pocos.fuente
Para cualquier idioma, juntarlos en el mismo paquete está bien. Lo importante es lo que está expuesto al mundo exterior y cómo se ve desde fuera. A nadie sabrá ni le importará si la implementación está en el mismo paquete o no.
Veamos este caso en particular.
Si tiene todos los elementos públicos en un paquete y los elementos privados en otro paquete que no está expuesto públicamente, el cliente de la biblioteca ve un paquete. Si mueve las cosas privadas al paquete con las cosas expuestas públicamente, pero no las expone dentro del paquete, el cliente ve exactamente lo mismo.
Por lo tanto, esto tiene el olor de una regla sin una buena razón: es tomar una decisión basada en algo que es públicamente visible sin que esa decisión tenga ningún efecto en lo que es públicamente visible.
Dicho esto, si en algún caso particular le parece una buena idea dividir la interfaz y la implementación en paquetes separados, siga adelante y hágalo. Las razones para hacer esto que me vienen a la mente son que el paquete es enorme o que tiene una implementación alternativa a la que podría querer vincular en lugar de la estándar.
fuente
friend
(C ++) ointernal
(C #) en Java.En muchos marcos, como OSGi, casi es necesario. Creo que esto promueve un acoplamiento más flojo, en el paquete en lugar del nivel del tarro.
fuente
Un argumento para poner interfaces en diferentes paquetes es que es más fácil crear frascos 'api' que se pueden distribuir a los consumidores de su producto o servicio. Es perfectamente posible hacer esto con interfaces e implementaciones juntas, pero es más sencillo crear un script si están en paquetes diferentes.
fuente
El libro Practical Software Engineering: A Case-Study Approach aboga por poner interfaces en proyectos / paquetes separados.
La arquitectura PCMEF + de la que habla el libro tiene los siguientes principios:
La descripción de los principios n. ° 3 y n. ° 7 explica por qué es una buena idea:
Vea este enlace: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf
fuente
Sí, es una muy buena práctica, porque te permite publicar la interfaz sin publicar tu implementación específica. Dicho esto, si no tiene necesidad de publicar interfaces externas, no hay problema en poner las definiciones de interfaz en el mismo paquete que la implementación.
fuente
Hacemos esto donde yo trabajo (es decir: poner la interfaz en un paquete y la implementación en otro) y la principal ventaja que obtenemos de esto es que podemos intercambiar fácilmente entre implementaciones.
fuente
No tengo mucha experiencia en Java, pero me gusta hacer esto como una buena práctica en C # /. NET porque permite una expansión futura donde los ensamblados con las clases concretas que implementan las interfaces pueden no distribuirse hasta el cliente porque son proxy de una fábrica de intermediarios o por cable en un escenario de servicio web.
fuente
Normalmente pongo interfaces con la implementación, sin embargo, puedo ver por qué es posible que desee mantenerlas separadas. Digamos, por ejemplo, que alguien quisiera volver a implementar clases en función de sus interfaces, necesitaría un jar / lib / etc con su implementación en lugar de solo las interfaces. Con ellos separados, podría simplemente decir "Aquí está mi implementación de esa interfaz" y terminar con ella. Como dije, no es lo que hago, pero puedo ver por qué algunos querrían hacerlo.
fuente
Estoy haciendo esto en un proyecto y me está funcionando bien por estas razones:
Las interfaces e implementaciones empaquetadas por separado son para un caso de uso diferente al de los diversos tipos de mapas o conjuntos. No hay ninguna razón para tener un paquete solo para árboles (java.util.tree.Map, java.util.tree.Set). Es solo una estructura de datos estándar, así que júntela con las otras estructuras de datos. Sin embargo, si se trata de un juego de rompecabezas que tiene una interfaz de depuración realmente simple y una interfaz de producción bonita, como parte de su interfaz, es posible que tenga un com.your.app.skin.debug y un com.your.app .piel.muy. No los pondría en el mismo paquete, porque hacen cosas diferentes y sé que recurriría a SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurface, etc.) para crear un espacio de nombres informal para los dos si estuvieran en el mismo paquete.
Mi solución para el problema de encontrar interfaces e implementaciones relacionadas que se encuentran en paquetes separados es adoptar una configuración de nombres para mis paquetes. Por ejemplo, puedo tener todas mis interfaces en com.your.app.skin.framework y saber que otros paquetes en el mismo nivel del árbol de paquetes son implementaciones. La desventaja es que se trata de una convención poco convencional. Honestamente, veré lo buena que es esta convención en 6 meses :)
No uso esta técnica religiosamente. Hay interfaces que solo tienen sentido en una implementación particular. No los pego en el paquete del marco. Hay algunos paquetes en los que no parece que vaya a crear 40 clases de implementación diferentes, así que no me molesto.
Mi aplicación usa guice y tiene muchas interfaces.
Las preguntas sobre el diseño de programas generalmente involucran beneficios e inconvenientes y no existe una respuesta única para todos. ¿Por qué alguna vez usarías esta técnica en un pequeño programa de 200 líneas? Tiene sentido para mí, dadas mis otras opciones arquitectónicas, para mi problema específico. :)
fuente
Los prefiero en el mismo paquete. No tiene sentido crear un paquete específicamente para interfaces. Esto es especialmente redundante para los equipos que simplemente aman los prefijos y sufijos de su interfaz (por ejemplo, "I" e "Impl" para Java).
Si es necesario publicar un conjunto de interfaces como API pública, tiene más sentido mantenerlas en un proyecto completamente separado y crear dependencias del proyecto en su lugar. Pero supongo que todo se reduce a la preferencia y conveniencia de la situación.
fuente
Colóquelos en paquetes que reflejen sus proyectos. Está bien y es común juntar interfaces e implementaciones si son parte del mismo proyecto, pero si está escribiendo una API, es probable que alguien más elija un nombre de paquete relevante para su proyecto.
En general, si es para el mismo proyecto, no veo ningún beneficio en mantener las interfaces en un paquete separado de sus impls. Si está abarrotado, puede haber otros problemas de nombres de paquetes, independientemente de la disposición de la interfaz.
fuente
Creo que es importante tener en cuenta que para el marco OSGi, es mejor que estén en diferentes paquetes para que pueda exportar fácilmente un paquete completo mientras oculta los paquetes de implementación.
fuente
Hay muchas buenas razones para colocar las interfaces en un paquete separado de la implementación. Por ejemplo, es posible que desee utilizar un contenedor que admita Dependency Injection para conectar las implementaciones necesarias en el tiempo de ejecución, en cuyo caso solo la interfaz debe estar presente en el momento de la compilación y la implementación se puede proporcionar en el tiempo de ejecución. Alternativamente, es posible que desee proporcionar múltiples implementaciones (por ejemplo, usando implementaciones simuladas para pruebas) o múltiples versiones de una implementación particular en tiempo de ejecución (por ejemplo, para pruebas A / B, etc.). Para este tipo de casos de uso, es más conveniente empaquetar la interfaz y la implementación por separado.
fuente