Saltar al contenido

Patrón de diseño de arquitectura limpia

Te damos la bienvenida a proyecto online, aquí encontrarás la respuesta que estás buscando.

Solución:

La base de datos está en la capa externa, pero ¿cómo funcionaría eso en realidad?

Usted crea una interfaz independiente de la tecnología en la capa de casos de uso y la implementa en la capa de puerta de enlace. Supongo que es por eso que esa capa se llama adaptadores de interfaz, porque aquí adaptas interfaces definidas en una capa interna. P.ej

public interface OrderRepository 
    public List findByCustomer(Customer customer);

la implementación está en la capa de puerta de enlace

public class HibernateOrderRepository implements OrderRepository 
      ...

En tiempo de ejecución, pasa la instancia de implementación al constructor del caso de uso. Dado que el caso de uso solo depende de la interfaz, OrderRepository en el ejemplo anterior, no tiene una dependencia del código fuente a la implementación de la puerta de enlace.

Puede ver esto escaneando sus declaraciones de importación.

Y uno de los casos de uso sería administrar personas. Administrar personas está guardando / recuperando / .. Personas (=> operaciones CRUD), pero para hacer esto, el caso de uso necesita comunicarse con una base de datos. Pero eso sería una violación de la regla de dependencia.

No, eso no violaría la regla de dependencia, porque los casos de uso definen la interfaz que necesitan. La base de datos simplemente lo implementa.

Si administra las dependencias de su aplicación con maven, verá que el módulo db jar depende de los casos de uso y no al revés. Pero sería incluso mejor extraer la interfaz de estos casos de uso en un módulo propio.

Entonces las dependencias del módulo se verían así

+-----+      +---------------+     +-----------+
|  db | -->  | use-cases-api | <-- | use cases |
+-----+      +---------------+     +-----------+

esa es la inversión de dependencias que de otro modo se verían así

+-----+      +-----------+
|  db | <--  | use cases |
+-----+      +-----------+

Si recibo una solicitud GET / person / id, ¿deberían mis microservicios procesarla de esta manera?
ingrese la descripción de la imagen aquí

Sí, eso sería una infracción, porque la capa web accede a la capa db. Un mejor enfoque es que la capa web acceda a la capa del controlador, que accede a la capa de casos de uso y así sucesivamente.

Para mantener la inversión de dependencia, debe desacoplar las capas utilizando interfaces como las que mostré anteriormente.

Entonces, si desea pasar datos a una capa interna, debe introducir una interfaz en la capa interna que defina métodos para obtener los datos que necesita e implementarlos en la capa externa.

En la capa del controlador, especificará una interfaz como esta

public interface ControllerParams 
    public Long getPersonId();

en la capa web, puede implementar su servicio de esta manera

@Path("/person")
public PersonRestService 

    // Maybe injected using @Autowired if you are using spring
    private SomeController someController;

    @Get
    @Path("id")
    public void getPerson(PathParam("id") String id)
       try 
           Long personId = Long.valueOf(id);

           someController.someMethod(new ControllerParams()
                public Long getPersonId()
                    return personId;
                
           );
        catch (NumberFormatException e) 
           // handle it
       
    

A primera vista, parece ser un código repetitivo. Pero tenga en cuenta que puede dejar que el resto del marco deserialice la solicitud en un objeto java. Y este objeto podría implementar ControllerParams en lugar de.

Si, en consecuencia, sigue la regla de inversión de dependencias y la arquitectura limpia, nunca verá una declaración de importación de la clase de una capa externa en una capa interna.

El propósito de la arquitectura limpia es que las principales clases de negocios no dependan de ninguna tecnología o entorno. Dado que las dependencias apuntan desde las capas externas a las internas, la única razón para que cambie una capa externa es debido a cambios en la capa interna. O si cambia la tecnología de implementación de la capa externa. Por ejemplo, Descanso -> JABÓN

Entonces, ¿por qué deberíamos hacer este esfuerzo?

Robert C. Martin lo cuenta en el capítulo 5 Programación orientada a objetos. Al final de la inversión de dependencia de la sección, dice:

Con este enfoque, los arquitectos de software que trabajan en sistemas escritos en lenguajes OO tienen un control absoluto sobre la dirección de todas las dependencias del código fuente en el sistema. No están obligados a alinear esas dependencias con el flujo de control. Independientemente del módulo que realice la llamada y del módulo que se llame, el arquitecto de software puede señalar la dependencia del código fuente en cualquier dirección.

¡Eso es poder!

Supongo que los desarrolladores a menudo se confunden sobre el flujo de control y la dependencia del código fuente. El flujo de control generalmente sigue siendo el mismo, pero las dependencias del código fuente se invierten. Esto nos da la oportunidad de crear arquitecturas de complementos. Cada interfaz es un punto para enchufar. Por lo tanto, se puede cambiar, por ejemplo, por razones técnicas o de prueba.

EDITAR

gateway layer = interface OrderRepository => ¿No debería la OrderRepository-Interface estar dentro de UseCases porque necesito usar las operaciones crud en ese nivel?

Sí, la interfaz OrderRepository debe definirse en la capa de casos de uso. También considere aplicar el principio de segregación de interfaz y definir un MyCuseCaseRepository interfaz, en lugar de solo una OrderRepository que utiliza cada caso de uso.

La razón por la que debe hacer esto es para evitar que los casos de uso se acoplen a través de una interfaz común y para respetar el principio de responsabilidad única. Porque una interfaz de repositorio dedicada a un caso de uso solo tiene una razón para cambiar.

EDITAR

También es una buena idea aplicar el segregación de interfaz principio y proporcionar una interfaz de repositorio propia dedicada al caso de uso. Esto ayudará a desacoplar los casos de uso entre sí. Si todos los casos de uso usan el mismo Repositorio interfaz, esta interfaz acumula todos los métodos de todos los casos de uso. Puede romper fácilmente un caso de uso cambiando un método de esta interfaz.

Por eso, suelo aplicar el principio de segregación de interfaces y crear interfaces de repositorio con el nombre del caso de uso. P.ej

public interface PlaceOrderRepository 
     public void storeOrder(Order order);

y la interfaz de otro caso de uso podría verse así:

public interface CancelOrderRepository 
     public void removeOrder(Order order);

los key elemento es Inversión de dependencia. Ninguna de las capas internas debe tener dependencias de las capas externas. Entonces, si, por ejemplo, la capa de caso de uso necesita llamar a un repositorio de base de datos, entonces debe definir una interfaz de repositorio (solo una interfaz, sin ninguna implementación) dentro de la capa de caso de uso y poner su implementación en la capa de adaptadores de interfaz.

Sección de Reseñas y Valoraciones

Si sostienes alguna desconfianza y capacidad de prosperar nuestro escrito eres capaz de añadir un paráfrasis y con placer lo estudiaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *