tutorial mvc implementar framework español edicion cuarta books arquitectura accion java spring design-patterns mocking domain-driven-design

java - mvc - ¿Por qué siempre tenemos interfaces de implementación únicas en capas de servicio y dao?



spring java tutorial (2)

Es un tema muy controvertido. En resumen, no hay ninguno, al menos para ti, el desarrollador.

En el mundo EJB2, las interfaces Home y Remote eran una necesidad, y fueron exactamente por una razón que @AravindA menciona: proxies. La seguridad, la comunicación remota, la agrupación, etc., todo podría incluirse en un proxy y proporcionar los servicios solicitados estrictamente dentro de la biblioteca estándar (como en DynamicProxy ).

Ahora que tenemos javaassist y cglib , Spring (Hibernate, EJB3 si lo prefiere) es perfectamente capaz de instrumentar sus clases como le gusta al desarrollador de marcos. El problema es que lo que hacen es una cosa muy molesta: generalmente te piden que agregues un constructor sin parámetros. Espera, ¿tengo parámetros aquí? No importa, solo agrega el constructor.

Así que las interfaces están aquí para mantener su cordura. Aún así, es extraño, un constructor sin argumentos para una clase con un constructor adecuado no es algo que tenga sentido para mí, ¿verdad? Resulta (debería haber leído la especificación, lo sé) que Spring crea un equivalente funcional de una interfaz de su clase: una instancia sin estado (o ignorada) y todos los métodos reemplazados. Así que tienes una instancia "real" y una "interfaz falsa", y lo que hace la interfaz falsa es que sirve para toda la seguridad / transacción / magia remota para ti. Agradable, pero difícil de entender, y parece un error si no lo has desarmado.

Además, si implementa una interfaz en su clase, (al menos algunas versiones de) Spring de repente decide que solo va a usar la interfaz como proxy, y la aplicación simplemente no funciona sin razón aparente.

Así, hasta ahora la razón es, seguridad y cordura. Hay razones por las que es una buena práctica, pero por su publicación, veo que ya ha leído todas esas. La razón más importante que puedo ver hoy es la métrica WTH / minuto, especialmente si estamos hablando de recién llegados a su proyecto.

He trabajado / visto algunos proyectos de aplicaciones web de Spring Hibernate que tienen tantas interfaces como servicios reales y clases de Dao.

Siempre pensé que estas dos como las razones principales para tener estas interfaces de implementación únicas:

  1. Spring puede conectar la implementación real como dependencias en una clase dada (acoplamiento suelto)

    public class Person { @Autowired private Address address; @Autowired private AccountDetail accountDetail; public Person(Address address, AccountDetail accountDetail) { // constructor

  2. Mientras que la unidad de prueba, puedo crear clases simuladas y probar una clase de forma aislada.

    Address mockedAddress = mock(Address); AccountDetail mockedAccountDetail = mock(AccountDetail); Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); // unit test follows

Pero, en los últimos tiempos, me di cuenta de que:

Spring puede cablear clases de implementación concretas como dependencias:

public class Person { @Autowired private AddressImpl address; @Autowired private AccountDetailImpl accountDetail; public Person(AddressImpl address, AccountDetailImpl accountDetail) { // constructor

Los marcos simulados como EasyMock también pueden simular clases concretas

AddressImpl mockedAddress = mock(AddressImpl); AccountDetailImpl mockedAccountDetail = mock(AccountDetailImpl); Person underTestPerson = new Person(mockedAddress, mockedAccountDetail); // unit test follows

Además, de acuerdo con this discusión, creo que el resumen es que dentro de una sola aplicación, las interfaces son en su mayoría sobreutilizadas, probablemente por convención o hábito. Por lo general, tienen más sentido en los casos en los que estamos interactuando con otra aplicación, por ejemplo, slf4j que usan muchas aplicaciones en todo el mundo. Dentro de una sola aplicación, una clase es casi tanto una abstracción como lo es una interfaz.

Entonces, mi pregunta es por qué seguimos necesitando Interfaces y luego tenemos implementaciones únicas como las clases * ServiceImpl y * DaoImpl y aumentamos innecesariamente el tamaño de nuestra base de código. ¿Hay algún problema en burlar las clases concretas de las que no tengo conocimiento?

Siempre que he discutido esto con mis compañeros de equipo, la única respuesta que recibo es que implementar clases de servicio y dao basadas en interfaces es EL DISEÑO que todos siguen: mencionan las mejores prácticas de Spring, OOP, DDD, etc. Pero todavía no lo hago. Obtenga una razón pragmática detrás de tener tantas interfaces dentro de una aplicación aislada.


Hay más ventajas para las interfaces, como en el proxy. Si su clase implementa una interfaz, los proxies dinámicos JDK se utilizarán de forma predeterminada para AOP. Si usa las implementaciones directamente, se verá forzado a usar proxies CGLIB haciendo que proxy-target-class = true. Estos requieren la manipulación del código de bytes a diferencia de los proxies JDK.

Lea here para más sobre esto.

Lea otra discusión sobre qué razones hay para usar interfaces (Java EE o Spring y JPA) para obtener más información.