Programación Spring Responsive - Notas de lectura

preámbulo

Hola a todos, soy Bittao. Este artículo son las notas de lectura de "Programación receptiva de Spring". La pila de tecnología receptiva puede crear puntos finales extremadamente eficientes, fáciles de adquirir y resistentes. Al mismo tiempo, la capacidad de respuesta puede tolerar demoras en la red y manejar fallas con menos impacto. Los microservicios reactivos también aíslan las transacciones lentas y aceleran las más rápidas. A través de este libro usted puede aprender lo siguiente:

  • Principios básicos de programación reactiva y especificación de flujo reactivo;
  • Use el marco de desarrollo receptivo de Project Reactor integrado con Spring 5;
  • Utilice Spring Webflux para crear servicios RESTful con capacidad de respuesta;
  • Use Spring Data Reactive para crear componentes de acceso a datos receptivos;
  • Utilice Spring Cloud Stream Reactive para crear componentes de comunicación de mensajes receptivos.

Capítulo 1 Resorte reactivo

Primero, comprendamos los términos relacionados con la programación receptiva:

  • Elasticidad: se puede expandir horizontalmente;
  • Rebote: aislamiento de fallas, lograr la independencia;
  • Impulsado por mensajes: no debe ser un bloqueo, respuesta instantánea.

En el estilo reactivo, la clave es la contrapresión : se utiliza principalmente para respaldar la resiliencia y realizar el complejo mecanismo de gestión de la carga de trabajo entre las etapas de procesamiento, lo que puede garantizar que una etapa de procesamiento no abrume a la otra.

En el campo de JVM, hay dos marcos más conocidos para construir sistemas receptivos: Akka y Vert.x. En Java tradicional, la forma receptiva:

  1. Función de devolución de llamada, pero traerá un problema infernal de devolución de llamada;
  2. Etapa de finalización de JDK 8.

Para ser compatible con el antiguo JDK, Spring 4 no era compatible con CompletionStage y este método solo era compatible con Spring 5. Al mismo tiempo, Servlet 3.0 introdujo la comunicación cliente-servidor asíncrona, y 3.1 admite escrituras sin bloqueo de E/S. Pero Spring MVC no proporciona un cliente asíncrono sin bloqueo listo para usar. Pérdida total del soporte receptivo para equipaje obsoleto. También hizo que Spring abriera una pila de tecnología separada para la capacidad de respuesta.

Capítulo 2 Conceptos básicos de la programación receptiva de Spring

El patrón de publicación-suscripción, que puede verse como una variante del patrón de observador. En la implementación basada en RxJava, el sensor de temperatura no detecta datos de temperatura cuando nadie está escuchando. Este comportamiento es una consecuencia natural del hecho de que la programación reactiva tiene el concepto de suscripciones activas. Las implementaciones basadas en temas de publicación no tienen esa propiedad y, por lo tanto, son más restrictivas.

[Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo de enlace antirrobo, se recomienda guardar la imagen y cargarla directamente (img-Qzu0Aua4-1678244967432)(%E3%80%8ASpring%20%E5%93 %8D%E5%BA% 94%E5%BC%8F%E7%BC%96%E7%A8%8B%E3%80%8B%20f33ef9259404475ab7d53d8b4b03f718/Sin título.jpeg)]
La biblioteca RxJava es una implementación de máquina virtual Java de Reactive Extensions (extensiones reactivas, también conocidas como ReactiveX). Reactive Extensions es un conjunto de herramientas para procesar flujos de datos, ya sean síncronos o asíncronos, en un lenguaje imperativo. ReactiveX se define generalmente como una combinación de patrón de observador, patrón de iterador y programación funcional.

RxJava se suscribe a un flujo observable a través de un suscriptor, que a su vez desencadena un proceso asíncrono de generación de eventos. Adoptar este enfoque es perjudicial para los objetos mutables y la única estrategia razonable es emplear la inmutabilidad. La inmutabilidad es uno de los principios básicos de la programación funcional. Una vez que se crea un objeto, no se puede cambiar. Una regla tan simple evita posibles problemas en sistemas paralelos.

Sin programación funcional, habría que crear muchas clases internas o anónimas que contaminarían la aplicación. Y crean más código repetitivo que código efectivo. Debido a su inmutabilidad, es muy adecuado para la programación concurrente.

historia

La historia de la programación asincrónica se remonta a lo que hizo Microsoft en 2005: un modelo de programación para una arquitectura de servicios de Internet asíncrona a gran escala con uso intensivo de datos . En 2009, Rx.NET era de código abierto. Posteriormente, Netflix se enfrentaba al complejo problema del tráfico masivo de Internet, por lo que abrió RxJava como código abierto. Y en base a ello se desarrollaron librerías conocidas como: Hystrix, Ribbon, Zuul, RxNetty. Pero, de hecho, es Node.js el que se ha implementado completamente y ha realizado con éxito grandes contribuciones en la dirección de la programación receptiva.

RxJava no es la única solución en Java, Vert.x también puede lograr funciones similares. Vert.x es un marco de desarrollo basado en eventos, similar en diseño a Node.js. Proporciona un modelo de concurrencia simple y una semántica primitiva para la programación asíncrona.

Con el éxito de RxJava, muchas empresas y proyectos de código abierto han iniciado una competencia feroz. Dado que el comportamiento de las distintas bibliotecas es muy similar en general, existen ligeras diferencias en la implementación. Entonces, si comparte algunas bibliotecas receptivas, pueden aparecer errores ocultos. Para solucionar estos problemas de compatibilidad surgió un estándar: Reactive Streams.

Capítulo 3 Flujos reactivos: el nuevo estándar

Para usar varias bibliotecas receptivas, debe escribir adaptadores para compatibilidad. No hay integración directa entre ListenableFuture y CompletionStage en Spring 4. En Spring 5, la API de ListenableFuture se amplió a un método llamado Comple-table para resolver la incompatibilidad. pregunta . El problema principal es que no hay forma de que los proveedores de bibliotecas proporcionen API alineadas. Vert.x, Ratpack y Retrofit prestan más atención a RxJava y brindan soporte.

En las primeras etapas de la evolución de todo el entorno reactivo, todas las bibliotecas se diseñaron con la idea de enviar datos desde las fuentes a los suscriptores. La principal razón para adoptar el modelo push es que optimiza el tiempo de procesamiento general al reducir al mínimo el volumen de solicitudes.

Esta es la razón por la cual RxJava1.x y bibliotecas de desarrollo similares están diseñadas con el propósito de enviar datos, y es por eso que la tecnología de transmisión puede considerarse una tecnología de comunicación importante entre componentes en un sistema distribuido. Sin embargo, si el productor no presta atención a la capacidad de producción del consumidor, existen las siguientes posibilidades:

  • productor lento y consumidor rápido
  • Productor rápido y consumidor lento

La solución para esta situación es recopilar elementos sin procesar en una cola.

  • Cola ilimitada: una cola de tamaño ilimitado;
  • Cola de caída limitada: para evitar el desbordamiento de memoria;
  • Cola de bloqueo limitada: bloqueo de órdenes de pago;

En general, la semántica descontrolada en los modelos push puros puede dar lugar a muchas situaciones no deseadas. El Manifiesto Reactivo menciona la importancia de los mecanismos que permiten que un sistema responda de manera inteligente a la carga y la importancia de la contrapresión.

La especificación Reactive Streams define 4 interfaces principales: publicador, suscriptor, suscripción y procesador.

Entre ellos, Publisher y Observable, Subscriber y Observer son básicamente lo mismo;

En el método onSubscribe en Subscriber, se hace referencia a Subscription, que proporciona la base para la producción de elementos de control. La especificación Reactive Streams introduce el método de solicitud para ampliar la interacción entre el publicador y el suscriptor. Para informar al Editor cuántos datos debe enviar, el Suscriptor debe indicar a través del método de solicitud la cantidad deseada y asegurarse de que la cantidad de elementos entrantes no exceda el límite.
inserte la descripción de la imagen aquí

A diferencia de un modelo de empuje puro, esta especificación nos brinda un modelo híbrido de empujar y tirar con un control razonable sobre la contrapresión.

Procesador es una combinación de publicador y suscriptor. Su objetivo es agregar algunas etapas de procesamiento entre el publicador y el suscriptor.

Capítulo 4 Fundamentos de la aplicación reactiva del proyecto Reactor

La especificación de flujos reactivos (reactivestreams) hace que las bibliotecas reactivas sean compatibles entre sí y resuelve el problema de la contrapresión mediante la introducción de un modelo de intercambio de datos pull-push. Pero solo define la especificación y no proporciona el uso diario Spring implementa Project Reactor (Reactor para abreviar).

La especificación de flujos reactivos (reactivestreams) hace que las bibliotecas reactivas sean compatibles entre sí y resuelve el problema de la contrapresión mediante la introducción de un modelo de intercambio de datos pull-push. Pero solo define la especificación y no proporciona el uso diario Spring implementa Project Reactor (Reactor para abreviar). La versión Reactor1.x incluye las mejores prácticas para el procesamiento de mensajes, como el Patrón Reactor (Reactor Pattern), así como estilos de programación funcional y reactiva.
El patrón Reactor es un patrón de comportamiento que facilita la respuesta de eventos asíncronos y el procesamiento síncrono. Esto significa que todos los eventos deben ponerse en cola y el procesamiento real de los eventos se realiza más tarde en un contenedor separado. Un evento se envía a todas las partes involucradas (controladores de eventos) y se procesa de forma síncrona.
Reactor 1.x está bien integrado con Spring Framework. Reactor 1.x proporciona muchos componentes adicionales junto con la biblioteca de procesamiento de mensajes, como un componente adicional para Netty. Reactor 2 fue pionero en la transmisión reactiva. Extraer el bus de eventos y la funcionalidad de transmisión en módulos separados hace que la biblioteca de Reactor Streams cumpla totalmente con la especificación de Reactive Streams. Reactor API tiene una mejor integración con Java Collections API. La API Streams de Reactor es más similar a la API RxJava, con soporte adicional para la gestión de la contrapresión, la programación de subprocesos y la resiliencia. El objeto Reactor que envía el mensaje se renombra a EventBus.

Las ideas de RxJava y ProjectReactor se condensaron en una biblioteca de flujo reactivo común, que luego se convirtió en Reactor3.x. Al mismo tiempo, Reactor3.x dio forma a la variante receptiva del marco Spring 5 (metamorfosis reactiva)

La biblioteca Reactor está diseñada para evitar el infierno de devolución de llamada y el código profundamente anidado al construir canalizaciones asíncronas. Podemos pensar en los datos procesados ​​de una aplicación reactiva como si se movieran en una línea de montaje. El Reactor es a la vez una cinta transportadora y una estación de trabajo. La API de Reactor solo activa el flujo de datos reales cuando se suscribe. Patrones de propagación de contrapresión comunes para esta biblioteca:

inserte la descripción de la imagen aquí

  • Push only: cuando un suscriptor solicita un elemento de monto inalámbrico válido a través de subscribe.request (Long.MAX_VALUE).
  • Pull-only: cuando un suscriptor solicita el siguiente elemento solo después de recibir el anterior a través de subscribe.request(1).
  • Pull-push (a veces llamado híbrido): cuando los suscriptores tienen necesidades de control en tiempo real y los editores pueden adaptarse a la tasa propuesta de consumo de datos.

Project Reactor se basa en la especificación Reactive Streams y org.reactivestreams:reactive-streams es la única dependencia obligatoria de Project Reactor. La especificación Reactive Stream define cuatro interfaces, a saber, Publisher, Subscriber, Subscription y Processor<T, R>.

ProjectReactor proporciona dos implementaciones de la interfaz de Publisher, Flux y Mono.

Mono es uno de los dos tipos de núcleo de Reactor, el otro es Flux. Ambos implementan la interfaz Publisher de Reactive Streams. Un flujo representa una canalización con cero, uno o muchos elementos de datos (posiblemente infinitos). Su fórmula es: onNext x 0…N [onError | onComplete]. Por ejemplo: Flux.range(1, 5).repeat();

Mono es un tipo reactivo especial optimizado para escenarios donde no hay más de un elemento de datos. La fórmula se expresa como: onNext x 0…1 [onError | onComplete]. Mono es útil cuando la API de la aplicación devuelve como máximo un elemento. Por lo tanto, puede reemplazar comple-tableFuture y proporcionar una semántica similar. CompletableFuture comienza a procesarse inmediatamente, mientras que Mono no hace nada hasta que llega un suscriptor. El beneficio del tipo Mono es que no solo proporciona una gran cantidad de operadores reactivos, sino que también puede integrarse perfectamente en un flujo de trabajo reactivo más grande. Ejemplo: cuando se completa la operación y es necesario notificar al cliente, Mono también se puede usar para enviar la señal onComplete() cuando se completa el procesamiento y devolver onError() cuando ocurre una falla. En este escenario, no se devuelven datos, pero se emite una señal de notificación que, a su vez, se puede utilizar como disparador para cálculos posteriores.

Flux y Mono son los bloques de construcción más básicos proporcionados por Reactor, y los operadores proporcionados por estos dos tipos de reactivos son el pegamento que los combina para construir canalizaciones de flujo de datos. Flux y Mono tienen un total de más de 500 operaciones, que se pueden clasificar aproximadamente en:
operaciones de creación,
operaciones de combinación,
operaciones de conversión,
operaciones lógicas.

Capítulo 5 Capacidad de respuesta con Spring Boot 2

Project Reactor puede ejecutarse sin el marco Spring, y será aún mejor cuando se combine con la inyección de dependencias de Spring.

En 2009, el equipo de Spring utilizó el método de Convención sobre configuración para desarrollar aplicaciones rápidamente. Spring Boot se lanzó en 2012, adoptando el concepto de aplicaciones web sin contenedores y la tecnología ejecutable fat JAR (Fat JAR). Las dos anotaciones más críticas: @SpringBootApplication, que se usa para ejecutar el contenedor IoC; @spring-boot-autoconfigure, configura automáticamente algunos componentes con el sufijo "-starter-".

Spring 5.x presenta soporte nativo para flujos reactivos y bibliotecas reactivas, incluidos RxJava 1/2 y Project Reactor3.

Los adaptadores para Servlet API 3.1 proporcionan una integración puramente asíncrona y sin bloqueos, a diferencia de los adaptadores WebMVC. Por supuesto, el módulo Spring WebMVC también admite Servlet API4.0, que admite HTTP/2.

inserte la descripción de la imagen aquí

En los primeros días, Spring Data proporcionaba principalmente acceso de bloqueo síncrono al área de almacenamiento subyacente. Afortunadamente, la quinta generación de Spring Data proporciona la interfaz ReactiveCrudRepository, que expone el tipo receptivo de ProjectReactor para facilitar la integración perfecta de los flujos de trabajo reactivos.

El módulo Spring Sessiong puede usar una abstracción eficiente para la gestión de sesiones. Spring Sessiong presenta ReactiveSessionRepository, que puede usar el tipo Mono de Reactor para realizar un acceso asíncrono sin bloqueo a las sesiones almacenadas.

El antiguo Spring Security usa ThreadLocal como método de almacenamiento de la instancia de SecurityContext, el cual es muy efectivo cuando se ejecuta en un solo Thread, en cualquier momento podemos acceder al SecurityContext almacenado en el ThreadLocal. Pero en la comunicación asíncrona, necesitamos transferir el contenido de ThreadLocal a otro Thread. La nueva generación actual de Spring Security adopta la función de contexto Reactor para transmitir contexto de seguridad en flujos Flux o Mono.

Netflix Zuul se basa en una API de Servlet que utiliza el enrutamiento de solicitudes sincrónicas de bloqueo, y la única forma de invalidar el procesamiento de solicitudes y obtener un mejor rendimiento es ajustar el grupo de subprocesos del servidor subyacente. Afortunadamente, Spring Cloud ha presentado el nuevo módulo Spring Cloud Gateway, que se basa en Spring WebFlux y proporciona enrutamiento asíncrono y sin bloqueo con el soporte de Project Reactor 3. Además de las puertas de enlace, Spring Cloud Streams también obtuvo el apoyo de Project Reactor e introdujo un modelo de flujo más detallado. También están Spring Cloud Function y Spring Cloud Data Flow, que pueden crear su propia FaaS (Función como servicio).

Spring Actuator proporciona una integración completa con WebFlux y utiliza su modelo de programación asíncrono y sin bloqueo para exponer de manera eficiente los puntos finales de las métricas. El módulo Spring Cloud Sleuth también es compatible con la programación receptiva y el rastreo distribuido listo para usar de Project Reactor.

Capítulo 6 Comunicación asincrónica sin bloqueo de WebFlux

La decisión de integrar el módulo Spring Web con la API Servlet de Java EE comenzó cuando el marco Spring comenzó a evolucionar en el espacio de las aplicaciones web. La infraestructura general del marco Spring se construye alrededor de la API de Servet y están estrechamente acoplados. Por ejemplo, Spring Web MVC en su conjunto se basa en el patrón Front Controller. Este modo está implementado por la clase org.springframework.web.servlet.DispatcherServlet en Spring Web MVC, y la introducción de esta clase amplía la clase javax.servlet.http.HttpServlet.

El diseño general se basa en el contenedor de Servlet subyacente, que es responsable de manejar todos los Servlets mapeados dentro del contenedor. DispatchServlet sirve como un punto de integración para integrar la infraestructura Spring Web flexible y altamente configurable con la pesada y compleja API de Servlet. La abstracción configurable de HandlerMapping ayuda a separar la lógica empresarial final (como controladores y beans) de la API de Servlet.

Aunque la API de Servlet admite comunicación asíncrona y sin bloqueo (a partir de la versión 3.1), la implementación del módulo SpringMVC no solo tiene muchos defectos, sino que tampoco permite operaciones sin bloqueo durante todo el ciclo de vida de la solicitud. Por ejemplo, no tiene un cliente HTTP sin bloqueo listo para usar, cualquier interacción externa puede resultar en el bloqueo de llamadas de E/S. Otra desventaja de la abstracción web en versiones anteriores de Spring es que no hay flexibilidad para que un servidor que no sea Servlet (como Netty) reutilice la funcionalidad Spring Web o el modelo de programación.

inserte la descripción de la imagen aquí

WebFlux brinda la capacidad de desarrollar aplicaciones livianas a través del mapeo de rutas funcionales y una API integrada donde podemos escribir una lógica de enrutamiento de solicitud compleja. La combinación de enrutamiento puramente funcional es suficiente para los nuevos enfoques de programación reactiva. Además, se proporciona un reemplazo reactivo para el antiguo RestTemplate para WebClient. Aunque WeboSocket se introdujo en Spring en 2013, todavía hay algunas operaciones de bloqueo, como escribir datos en E/S o leer datos de E/S que siguen siendo operaciones de bloqueo. El módulo WebFlux presenta una versión mejorada de la infraestructura para WebSocket y brinda soporte al cliente.

Comparando WebFlux y WebMVC

En el pasado, las computadoras eran secuenciales, y todos estaban acostumbrados a navegar por contenido simple y estático, y la carga general del sistema siempre era baja. Pero ahora la cantidad de usuarios de la Web ha alcanzado más de una docena de niveles, y el contenido ha comenzado a ser dinámico o incluso en tiempo real, y los requisitos de rendimiento y demora han cambiado mucho. Para calcular cómo la cantidad de unidades de trabajo paralelas cambia la latencia o el rendimiento, puede usar la Ley de Little: N = X x R. El número promedio de solicitudes (o solicitudes procesadas simultáneamente) (N) residentes en un sistema o cola es igual al rendimiento (o número de usuarios por segundo) (X) multiplicado por el tiempo de respuesta o latencia promedio (R); por ejemplo : Respuesta promedio del sistema El tiempo R es 0.2S, y el rendimiento X es 100 solicitudes por segundo, entonces debería poder manejar 20 solicitudes al mismo tiempo, o 20 usuarios en paralelo.

Los frameworks web tradicionales basados ​​en Servlet, como Spring MVC, son de naturaleza bloqueante y de subprocesos múltiples, y cada conexión utiliza un subproceso. Cuando se procesa la solicitud, se extraerá un subproceso de trabajo del grupo de subprocesos para procesar la solicitud. Mientras tanto, el subproceso de solicitud se bloquea hasta que el subproceso de trabajo indica que se ha completado.
La consecuencia de esto es que el bloqueo de marcos web no puede escalar de manera efectiva bajo una gran cantidad de solicitudes. El retraso introducido por un subproceso de trabajo lento empeorará la situación, ya que llevará más tiempo enviar el subproceso de trabajo de regreso al grupo, listo para manejar otra solicitud. En algunos escenarios, este diseño es perfectamente aceptable. De hecho, así es como se han desarrollado la mayoría de las aplicaciones web durante más de una década, pero los tiempos están cambiando.
Los clientes de estas aplicaciones web solían ser personas que navegaban ocasionalmente por el sitio, pero ahora estas personas consumen contenido con frecuencia y usan aplicaciones que funcionan con API HTTP. Hoy en día, el Internet de las cosas (que ni siquiera necesita humanos) ha generado automóviles, motores a reacción y otros clientes no tradicionales que intercambian datos constantemente con las API web. Con más y más clientes que consumen aplicaciones web, la escalabilidad es más importante que nunca.
Los marcos web asincrónicos pueden lograr una mayor escalabilidad con menos subprocesos, por lo general, solo necesitan la misma cantidad de subprocesos que núcleos de CPU. Al usar el llamado mecanismo de bucle de eventos (que se muestra en la Figura 11.1), estos marcos pueden manejar muchas solicitudes con un hilo, por lo que el costo por conexión será menor.

El cuadro en la parte superior derecha representa un modelo de programación alternativo que usa un paradigma de programación funcional para definir controladores en lugar de usar anotaciones.

inserte la descripción de la imagen aquí

Aunque los controladores Spring WebFlux generalmente devuelven Mono y Flux, eso no significa que Spring MVC no pueda experimentar las alegrías de la escritura reactiva. Spring MVC también puede devolver Mono y Flux si lo desea.
La diferencia aquí es cómo se utilizan estos tipos. Spring WebFlux es un verdadero marco web reactivo que permite que las solicitudes se procesen en bucles de eventos, mientras que Spring MVC está basado en Servlet y se basa en subprocesos múltiples para manejar múltiples solicitudes.

Web MVC se basa en el bloqueo de E/S, lo que significa que el subproceso que procesa cada solicitud entrante puede bloquearse al leer los mensajes entrantes de E/S.

inserte la descripción de la imagen aquí

Por el contrario, WebFlux se basa en una API sin bloqueo, lo que significa que no es necesario que las operaciones interactúen con subprocesos de bloqueo de E/S. WebFlux puede utilizar un subproceso de manera más eficiente que Web MVC.

inserte la descripción de la imagen aquí

Escenarios para aplicaciones WebFlux:

  1. Sistema de microservicio: la característica más notable de un sistema de microservicio típico es una gran cantidad de comunicaciones de E / S. La existencia de E / S, especialmente el bloqueo de E / S, reducirá la demora y el rendimiento de todo el sistema.
  2. Sistemas que manejan conexiones de clientes lentas: si la cantidad de clientes es alta, las posibilidades de que el sistema se bloquee son altas. Por ejemplo, los piratas informáticos pueden hacer que nuestros servidores no estén disponibles fácilmente mediante ataques de denegación de servicio (DoS). Por el contrario, WebFlux nos permite aceptar conexiones sin bloquear los hilos de trabajo.
  3. Sistemas de transmisión o en tiempo real: estos sistemas se caracterizan por una baja latencia y un alto rendimiento, lo que se puede lograr mediante una comunicación sin bloqueo. Sin embargo, este marco reactivo tiene sus propios inconvenientes, a saber, modelos de interacción complejos que utilizan canales y devoluciones de llamada. Pero podemos construir un flujo asíncrono sin bloqueo con una biblioteca reactiva y aun así requerir muy poca sobrecarga.

WebFlux está disponible con un servidor web receptivo (Netty) y funcionalidad Undertow sin bloqueo

Capítulo 7 Acceso reactivo a la base de datos

Siempre se desaconseja el bloqueo de E/S en aplicaciones reactivas. Los módulos Spring Data acceden a los datos de manera reactiva. Incluso si la base de datos seleccionada no proporciona un controlador reactivo o asíncrono, aún podemos usar un grupo de subprocesos dedicado para construir un marco a su alrededor. Aplicación responsiva.

"Domain-Driven Design: The Way to Cope with the Complexity of Software Core" de Eric Evans define y da forma a la importante base teórica para la exitosa arquitectura de microservicios. El diseño controlado por dominio (DDD) establece un vocabulario común (es decir, contexto, dominio, modelo y lenguaje unificado) y un solo contexto acotado (contexto acotado) definido de acuerdo con DDD generalmente se asigna a un micro en servicio separado.

inserte la descripción de la imagen aquí

Dado que DDD está muy preocupado por el dominio central del negocio (dominio central), especialmente los artefactos utilizados para expresar, crear y recuperar modelos de dominio, entidades (Entidad), objetos de valor (Objeto de valor), agregación (Agregado), repositorio (Repositorio), etc. Los objetos se mencionarán con frecuencia en este capítulo.

Durante la implementación de una aplicación considerando DDD, los objetos anteriores deben asignarse a la capa de persistencia de la aplicación. Este modelo de dominio forma la base para el modelo de datos lógico y físico.

Continuará...

Supongo que te gusta

Origin blog.csdn.net/u012558210/article/details/129399429
Recomendado
Clasificación