Repositorio de Productos Orientado al Dominio en Java
Resumen
¿Cómo orientar el repositorio de productos al dominio?
Para desarrollar software sólido y flexible, es fundamental orientar los repositorios al dominio. Esta práctica desvincula la lógica de negocio de la infraestructura de almacenamiento, adaptándose a cambios futuros, como migraciones a distintas bases de datos. En este caso, reemplazamos una estructura rígida y dependiente de una tabla SQL particular por una forma más abstracta y orientada al dominio. Empecemos paso a paso.
¿Qué es la implementación de interfaces en repositorios?
Para comenzar, debemos asegurarnos de que nuestro productRepositorio implemente la interfaz que diseñamos previamente. Esta interfaz define los métodos necesarios que nuestro dominio requiere, como recuperar todos los productos o salvar un nuevo producto.
publicclassProductRepositorioImplimplementsProductRepositorio{// Mensaje de advertencia debido a métodos no implementados// Implementación pendiente de métodos obligatorios de la interfaz}
¿Cómo usar un mapper para transformar entidades?
El siguiente paso es la utilización de un ProductMapper que facilite la conversión de producto a Product. Esta clase actúa como intermediario, simplificando la transformación de las entidades de la base de datos al objeto del dominio.
Uso del método getAll: Aquí obtenemos productos de un repositorio y los transformamos a través del mapper.
@OverridepublicList<Product>getAll(){List<Producto> productos = cruRepositorioy.findAll();return maper.toProducts(productos);// Transformamos la lista}
¿Cómo trabajar con Optional para consultas específicas?
La clase Optional de Java nos ayuda a manejar valores que podrían ser nulos de manera segura y eficiente. Implementamos métodos como getByCategory y getProductosEscasos haciendo uso de esta característica.
Consulta por categoría:
@OverridepublicOptional<List<Product>>getByCategory(int categoriaId){List<Producto> productos = productRepositorio.findByIdCategoriaOrderByNombreAsc(categoriaId);returnOptional.of(maper.toProducts(productos));// Conversión y empaque en Optional}
¿Cómo manejar el guardado y eliminación de productos?
Los procesos de guardar y eliminar productos también se simplifican al orientarnos al dominio. Aquí, el mapeo inverso se hace de Product a producto antes de persistir los cambios.
La eliminación es directa dado que no requiere una conversión previa al no retornar un resultado.
¿Por qué es esencial orientar el repositorio al dominio?
Adaptar un repositorio al dominio aporta gran flexibilidad al proyecto. Flexibilidad significa poder cambiar la base de datos subyacente sin modificar la lógica ni el comportamiento de la aplicación. Por ejemplo, si migramos de SQL a MongoDB, el diseño ya anticipará tal cambio, permitiendo una transición suave con mínimos ajustes.
La orientación al dominio es clave en el desarrollo de software moderno y escalable. Aprender a integrar conceptos como mapeo y uso de Optional fortalece las habilidades de diseño, proporcionando un código más limpio y adaptable. Continúa explorando y desarrollando tus habilidades de programación, ¡el mundo del desarrollo siempre ofrece algo nuevo por descubrir!
cuando se maneja todo el proyecto en ingles se puede usar el siguiente estándar de nombrado. Usando como ejemplo la entidad Product:
ProductDTO para objetos de dominio
Product para las entidades
Es verdad, el curso es muy bueno pero esos nombres que da o por ejemplo el "ProductoRepository implements ProductRepository" y demás cosas deberían mejorar
Estuve pensando acerca de esto cuando diseñé el curso y aunque es mejor hacer todo en ingles, usé español a propósito en los entities para que la función de MapStruct se viera más clara y útil.
Siempre se puede mejorar; gracias por sus comentarios y recomendaciones Fernando y Ronnie!
Una de las clases quizás mas densas en cuestion de la cantidad de clases, metodos y funciones a las que toca echarles una repasada. Pero es cuestion de ver una y otra vez el video y aprovechar esta explicacion magnifica para retomar el hilo del proyecto y aprender cosas importantes
Me parece que el profe debió hacer un repaso por el flujo de datos entre las diferentes capas, pues se vuelve un poco confuso seguirle el paso sin entender como interactuanentre si.
Completamente de acuerdo con tu opinión, además de que hasta ahora no ha mostrado una manera de poder correr un endpoint por ejemplo y ver que si este funcionando el código que escribimos, sin eso no hay retroalimentación de si lo hacemos bien o no y se vuelve muy complicado comprender el flujo
estoy deacuerdo...
yo ya se programar con java , python , javascript. he hecho aplicaciones con nodejs express ,pero ver este curso me hace sentir un principiante. asi que a esto se referia mi profe de la universidad de que con java se hace ingeniera de software de verdad.
"ingeniería de software de verdad" no está determinada por el lenguaje de programación utilizado, sino por la metodología, las buenas prácticas, el diseño sólido, la calidad del código, la arquitectura adecuada y otras consideraciones que se aplican en el proceso de desarrollo de software, independientemente del lenguaje utilizado.
En mi opinión la estrategia de nombrar a las clases en español e ingles estuvo bien, porque de esa manera puede entender la forma como se utiliza MapStruct y conocer el potencial de la misma, para evitar el acoplamiento del código a una base de datos puntual y enfocar el código al dominio. Excelente explicación
Por ejemplo, en el caso del código de barras, como no tenemos acceso a este desde la API, si queremos agregarlo programáticamente, sería algo como:
@OverridepublicProductsave(Product product){Producto producto = mapper.toProducto(product); producto.setCodigoBarras("uncodigo");// Aqui se guarda el producto con el codigo de barras// pero luego del hacer el mapping el Product que se retorna ya no tiene el atributo codigoBarras (barCode)return mapper.toProduct(productoCrudRepository.save(producto));}
Sería algo así?
¡Exacto David! De esa manera podrías guardar el código de barras en la BD a pesar de que no esté mapeado en la clase Product.
Resumen de que se intenta hacer:
Al orientar nuestro repositorio a términos del dominio, lo que se quiere conseguir es conectar los métodos que tenemos en el repositorio, a el dominio para que así todo funcione en términos del dominio y no de la base que está conectada directamente con la DB.
En mi opinión es importante escribir el proyecto en cualquier otro idioma diferente al que estamos acostumbrado, como lo hace el profesor porque en la vida real te encuentras con una sopa de código y esto que nos enseña nos hace ser mas ágiles para codificar o o corregir a futuro.
Felicito al 1000% al profesor, es otro de los que han explicado super bien los cursos que he tomado aqui en Platzi ;)
Un aporte en el uso de la lambda:
Mientras lo que reciba algún método coincide en el orden y tipos de los argumentos de la lambda, el método se puede pasar a referencia.
Esta clase ya roza lo confuso, porque es muy necesaria una explicación gráfica para representar este punto del flujo de la arquitectura, y evitar confusiones con las estructuras mentales que forzamos para entender esta clase.
Como se explica la diferencia entre DataMapper, DTO y DAO?
Un DAO es un objeto que esta cerca de la BD, un DTO es un objeto que esta cerca de la capa de servicio y el DataMapper es el del medio que sabe como el servicio entiende (con DTOs) y sabe como la BD entiende (con DAOs), es el objeto traductor.
Recién empiezo con JAVA y este curso está brutal, el entender como concepto la arquitectua por capas orientadas al dominio quitó muchas confusiones que hasta esta clase tenía. Por ello una buena clase con sus comentarios es la siguiente: https://platzi.com/clases/1248-pro-arquitectura/10419-patrones-diseno-orientado-al-dominio/
Sólo la punta del iceberg, a seguirle dando!!!
"En la clase anterior, observamos como funciona Mapper Struct". Yo la verdad ni idea de lo que estoy haciendo, parece mas un tutorial que un curso!!
Lo unico que he visto que funciona es la url.
Ahora cuando ejecute el programa, una velita y encomendacion a Diosito.
Está genial el curso, uno de los mejores que he hecho. Aunque el ejemplo quizás no sea tan preciso y redunda mucho el código.
Que confuso se volvio este curso
Es el primer curso que hago en Platzi, creo que era adecuado graficar correctamente la arquitectura en diagramas, explicar el flujo.
Si a alguno de ustedes les está dando problemas al hacer build al proyecto con un error como
No property named “<attribute>” exists in source parameter(s)
asegúrense de tener construidos en la clases los getters para todos los atributos. Si no es así, el MapStruct no puede realizar el mapeo de forma adecuada.
Más información en la documentación de MapStruct
Amigos gracias me soluciono el problema!,
pero tengo una duda, estaba usando lombok y utilze las anotaciones correspondientes y no me funcionaba, genere automaticamente los Get&Set y funciono
si funciona con Lombok pero hay que hacer unos ajustes en el archivo de configuración de gradle (build.gradle) para que procese las anotaciones de Lombok de manera que mapstruct pueda ver los getters y setters@Getter
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
implementation 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
```Mi objeto product en el domain quedo asi
```js
@Getter@Setter@NoArgsConstructorpublicclassProduct{privateint productId;privateString name;privateint categoryId;privatedouble price;privateint stock;privateboolean active;privateCategory category;}
Ya me perdí, empezaré de nuevo el proyecto porque aqui tiene código que no vi donde lo agregó en la clase ProductRepository.java de la carpeta persistence :(
1.- Cual es la diferencia entre una lista normal y una lista optional?
2.- si la bd esta en ingles y todo esta en ingles... ya no es necesario usar MapStruct ?
3.- Porque Optional.of?
Gracias de antemano
Para que refuerces todas estas características de programación funcional (como el Optional) te recomiendo que veas el gran Curso de Programación Funcional con Java SE que tenemos aquí en Platzi.
Como respuesta a tus preguntas:
1. Uno es una lista "normal" como las que siempre hemos visto en Java y el otro es un concepto que fue introducido en Java 8 y que me permite tener componentes opcionales (que pueden o no estar) con un montón de funcionalidades. Puedo tener un Optional ó un List o de lo que sea gracias a los Generics y El Diamond operator.
2. Sí vas orientar tu aplicación en términos de dominio, si es necesario usar MapStruct.
Sí el entity y la clase de dominio tienen los mismos nombres de atributos solo basta con crear la interface Mapper pero sin definirle ningún mapeo porque se harán automáticamente.
La idea es que el objeto de dominio solo lleve lo que sea estrictamente necesario, por lo cual debería tener menos campos que el entity y en ese sentido el Mapper tendrá uno que otro ignore.
3. El Optional.ofpermite convertir cualquier objeto en un Optional.
En nuestro caso puntual lo usamos porque el método findByIdCategoriaOrderByNombreAsc de la interface ProductoCrudRepository retornamos una List<Producto> y según nuestra interface ProductRepository debemos retornar un Optional<List<Product>>. Para no usarlo simplemente retorna un Optional desde este método en ProductoCrudRepository.
Profesor, muy claro estas explicaciones en la respuesta a Junior. Pero recomiendo que esto se haga en la grabación de la clase y no en la respuesta a una duda particular.