¿Por qué siempre tener interfaces de implementación únicas en capas de servicio y dao?


He trabajado/visto algunos proyectos de aplicación web spring-hibernate que tienen tantas interfaces como hay clases reales de servicio y dao.

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

  1. El resorte puede cablear 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. Durante las pruebas unitarias, puedo crear clases simuladas y probar una clase en aislamiento.

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

Pero, últimamente, me di cuenta de que:

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

public class Person { 

@Autowired 
private AddressImpl address;

@Autowired 
private AccountDetailImpl accountDetail;

public Person(AddressImpl address, AccountDetailImpl accountDetail) { 
// constructor

Marcos simulados como EasyMock también pueden simular clases de concreto

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

También, según esta 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 mejor sentido en los casos en que estamos interactuando con otra aplicación por ejemplo slf4j utilizado por muchas aplicaciones en todo el mundo. Dentro de una sola aplicación, una clase es casi tanto una abstracción como una interfaz.

Entonces, mi pregunta es por qué todavía necesitamos 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 burlarse de clases concretas que no soy consciente.

Cada vez que he discutido esto con mis compañeros de equipo, la única respuesta que obtengo es que el servicio de implementación y las clases de dao basadas en interfaces es EL DISEÑO que todo el mundo sigue: mencionan las mejores prácticas de primavera, OOP, DDD, etc. Pero todavía no entiendo una razón pragmática detrás de tener tantas interfaces dentro de una aplicación aislada.

Author: Cœur, 2012-01-19

2 answers

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

Lee aquí para más sobre esto .

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

 15
Author: Aravind A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:54

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 eran exactamente por una razón que @AravindA menciona: proxies. Seguridad, remoting, pooling, etc. todos podrían estar envueltos 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) son perfectamente capaces de instrumentando tus clases como le gusta al desarrollador de framework. El problema es que lo que hacen es algo muy molesto: por lo general te piden que agregues un constructor sin parámetros.- Espera, ¿tenía 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 argumento para una clase con constructor adecuado no es algo que tenga sentido para mí, ¿verdad? Resulta (debería haber leído la especificación, lo sé) que la primavera crea un equivalente funcional de una interfaz fuera de su clase: una instancia sin estado (o ignorada) y todos los métodos anulados. Así que tienes una instancia "real" y una "interfaz falsa", y lo que hace fake interface es que sirve toda la magia de seguridad/transaccional/remota para ti. Agradable, pero difícil de entender, y parece un error si no lo has desarmado.

Además, si implementas una interfaz en tu clase, (al menos algunas versiones de) Spring de repente decide que vamos a proxy esta interfaz solo, y la aplicación simplemente no funciona por ninguna 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 ellas. La razón más importante que puedo ver hoy es la métrica WTH/minute, especialmente si estamos hablando de recién llegados a su proyecto.

 15
Author: alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-20 10:43:05