2008-09-30 20 views
23

Acepto, que la programación en contra de interfaces es una buena práctica. En la mayoría de los casos, en Java, la "interfaz" en este sentido significa la interfaz de construcción del lenguaje, de modo que usted escribe una interfaz y una clase de implementación, y que utiliza la interfaz en lugar de la clase de implementación la mayor parte del tiempo.Programación contra interfaces: ¿Escribes interfaces para todas tus clases de dominio?

Me pregunto si esta es una buena práctica para escribir modelos de dominio también. Entonces, por ejemplo, si tiene un cliente de clase de dominio y cada cliente puede tener una lista de pedidos, ¿podría generalmente escribir también interfaces ICustomer y IOrder? ¿Y también tendría el Cliente una lista de IOrders en lugar de Orders? ¿O usaría interfaces en el modelo de dominio, solo si está realmente dirigido por el dominio, p. tienes al menos dos tipos diferentes de pedidos? En otras palabras, ¿usaría interfaces solo por necesidades técnicas en el modelo de dominio, o solo cuando sea realmente apropiado con respecto al dominio real?

+0

¿Qué pasa con este prefijo sobre nombres de interfaz? ¿Desde cuándo estaba bien utilizar la notación húngara? – grom

+0

@grom - Odio ver eso en el código Java también. Es una convención de la programación COM de Microsoft. –

+3

¿Le molesta verlo en Java, pero le gusta en otros idiomas, como C#? Eso no tiene sentido ... De hecho, lo encuentro útil cuando veo código desconocido. Puedo decir de un vistazo qué es una interfaz y qué es una implementación concreta (especialmente si agregan Impl al final, que es la convención donde trabajo) – hhafez

Respuesta

26

Escribir interfaces "solo porque" me parece una pérdida de tiempo y energía, sin mencionar una violación del principio KISS.

Los escribo cuando son realmente útiles para representar el comportamiento común de las clases relacionadas, no solo como un archivo de encabezado de fantasía.

12

No sobrediseñe su sistema. Si descubre que tiene varios tipos de pedidos y cree que es apropiado declarar una interfaz para pedidos, refactorícelos cuando sea necesario. Para los modelos de dominio, la probabilidad es alta de que la interfaz específica cambie mucho durante la vida útil del desarrollo, por lo que rara vez es útil escribir una interfaz con anticipación.

1

Normalmente solo uso interfaces donde tiene sentido en proyectos más pequeños. Sin embargo, mi último trabajo tiene un gran proyecto en el que casi todos los objetos de dominio tienen una interfaz. Probablemente sea exagerado y definitivamente molesto, pero la forma en que hacemos las pruebas y usamos Spring para la inyección de dependencia lo requiere.

1

Principalmente escribimos aplicaciones web con Wicket, Spring e Hibernate y utilizamos interfaces para Spring Beans, p. Servicios y DAOs. Para estas clases, las interfaces tienen mucho sentido. Pero también usamos interfaces para cada clase de dominio y creo que esto es simplemente exagerado.

1

Incluso si está seguro de que solo habrá un tipo concreto de un objeto modelo, el uso de interfaces hace que las burlas y las pruebas sean más fáciles (pero en estos días hay estructuras que pueden ayudarle a generar clases simuladas automáticamente, incluso clases concretas de Java: Mockito, JTestR, Spring, Groovy ...)

Pero con mucha frecuencia uso las interfaces para los servicios, ya que es aún más importante burlarse de ellas durante las pruebas, y la programación en las interfaces te ayuda a pensar cosas como la encapsulación.

8

Las interfaces son una forma excelente de aislar componentes para pruebas de unidades y administración general de dependencias. Al decir eso, a menudo prefiero las clases abstractas, por lo que al menos parte del comportamiento común se descarga allí en lugar de forzar parte de la duplicación que traen las interfaces. Los IDEs modernos hacen que sea fácil y rápido generar interfaces para que no sean que mucho trabajo :-)

4

Yo recomendaría mantenerme delgado y ágil: no haga nada hasta que tenga que hacerlo, luego deje su IDE hace la refactorización para usted cuando la necesita.

Es bastante trivial en IDEA/eclipse convertir una clase concreta en una interfaz cuando usted decide que la necesita.

A continuación, utilice la inyección de dependencias con Spring o Guice si tiene muchas implementaciones de la interfaz para inyectar en los lugares en su código que está utilizando 'nuevos'

1

interfaces de escritura para clases de dominio puede tener sentido si' reutilizándolo para pruebas unitarias. Usamos objetos simulados en pruebas unitarias. Entonces, si tiene una interfaz para un objeto de dominio y su objeto de dominio en sí no está listo, su cliente puede probar su uso de la interfaz con la ayuda de objetos simulados.

Intefaces también prueban múltiples implementaciones de sus interfaces para su modelo de dominio. Entonces, no creo que siempre sea excesivo.

1

Creo que la razón principal para programar contra interfaces es la capacidad de prueba. Por lo tanto, para los objetos de dominio, solo adhiérase a POJO o POC# Os :) etc., es decir, evite que sus clases agreguen un marco específico para evitar que tengan diferentes dependencias de compilación y tiempo de ejecución, y eso es todo. Crear interfaces para DAO es una buena idea.

2

La interfaz de escritura antes de que se necesite (ya sea para pruebas o arquitectura) es una exageración.

Además, escribir una interfaz manualmente es una pérdida de tiempo. Puede usar la refactorización de Resharper "Pull Members" para dejar que cree una nueva interfaz fuera de la clase específica en cuestión de segundos. Otras herramientas de refactorización que se integran con IDE también deberían tener una funcionalidad similar.

5

No, solo uso interfaces en Objetos del Dominio para mantenerlos ligeramente acoplados. Para mí, el principal objetivo de desarrollar mi propio código con interfaces es que puedo crear simulaciones fácilmente al hacer pruebas unitarias. No veo el sentido de burlarse de los objetos de dominio ya que no tienen las mismas dependencias que una capa de servicio o una clase de capa DAO.

Esto ciertamente no significa desviarse del uso de interfaces en objetos de dominio. Usar cuando sea apropiado. Por ejemplo, últimamente he estado trabajando en una aplicación web donde diferentes tipos de objetos de dominio corresponden a páginas de enlace permanente en las que los usuarios pueden dejar comentarios. Entonces, cada uno de estos objetos de dominio ahora implementa la interfaz "Commentable". Todo el código basado en comentarios se programa luego en la interfaz Commentable en lugar de los Objetos del Dominio.

+1

Me gusta este enfoque pragmático. –

+0

Disculpe, pero ¿qué quiere decir con "Todo el código basado en comentarios se programa entonces en la interfaz Commentable"? Dado que no puede tener ningún detalle de implementación dentro de la interfaz. – Wuaner

+0

@Wuaner Escribí esta respuesta hace 8 años y apenas he tocado Java desde entonces, ni idea de lo que quise decir. – bpapa

0

Esa es otra cosa a tener en cuenta que me he encontrado, especialmente con los objetos generados de dominio y DAO. Muchas de las interfaces son demasiado específicas. Digamos que muchos objetos de dominio tienen una ID y un campo de estado. ¿Por qué no comparten una interfaz común? Esto me ha causado frustración, un modelo de dominio innecesariamente plano (basado en la herencia).

1

Extraemos interfaces de todo solo porque ayuda a probar (burlarse) y cosas como AOP. Eclipse puede hacer esto automáticamente: Refactor-> Extraer interfaz.

Y si necesita modificar la clase más adelante, puede usar Refactor-> Levantar ... para desplegar los métodos que necesita en la interfaz.

1

* Lo hago porque lo necesito para crear proxies de mis objetos de dominio.

4

En realidad, esta pregunta es un ejemplo del malentendido común sobre "programación contra interfaces".

Ves, esto es un muy buen principio, pero sí no quiere decir lo que muchos piensan que significa!

"Programar a una interfaz, no a una implementación" (del libro GoF) significa exactamente eso, no es que deba salir de su camino a crear interfaces separadas para todo. Si tiene un objeto ArrayList, declare la variable/campo/parámetro/tipo de retorno como del tipo List. El código del cliente solo tratará con el tipo de interfaz.

En el libro "Java efectivo" de Joshua Bloch, el principio se expresa más claramente, en el "Artículo 52: Refiérase a los objetos por sus interfaces". Incluso se dice, en letras en negrita:

es totalmente apropiado para referirse a un objeto por una clase en lugar de una interfaz si no existe una interfaz apropiada.

Para las pruebas unitarias, la situación depende totalmente de las capacidades de la herramienta de burla utilizada. Con mi propia herramienta, JMockit, puedo escribir pruebas unitarias con la misma facilidad para código que usa interfaces e Inyección de Dependencia que para código que usa clases finales creadas desde el código bajo prueba.

Así que, para mí, la respuesta es: siempre use interfaces que ya existen, pero evite crear nuevas si no hay una buena razón para hacerlo (y testabilidad, por sí mismo, no debería ser uno).

Cuestiones relacionadas