Dios cuanto tiempo, que alegría mas grande volverte a ver por aquí. Por favor Carlos, continua compartiendo contenido!! Un abrazo y mucha suerte en tu nuevo proyecto :)
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias! Alegría la mía al ver vuestras reacciones. Seguimos!
@jammaj5 Жыл бұрын
Gracias Carlos, he visto los de hace 8 años los de 5 años y que gran valor nos has dado. Alegría ver este video de 6 meses.
@ciltocruz Жыл бұрын
Hostia, el caso 3 es rizar el rizo. Chapeau. Brillante.
@SamuDeep132 жыл бұрын
Me he sentido feliz al ver en el feed un video de nuevo! Enhorabuena y espero que siga durante mucho tiempo!
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Samuel!
@andrescristancho3851 Жыл бұрын
Muy feliz de encontrar nuevo contenido tuyo Carlos. 🎉🎉🎉🎉
@javiermadueno2 жыл бұрын
Que bueno verte de nuevo por aqui! May the rigor be with you!
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Javier! Yo también tenía ganas de compartir algunas cositas :)
@r.amilcarrivasmarquez2892 Жыл бұрын
Saludos de México, en un principio pensé que estabas acoplándote a abstracciones y que las implementaciones estarían mas gordas. Pero me doy cuenta que lo que propones es discretizar los objetos que participan en un caso de uso, es como radicalizar el principio de substitution liskov, lo que llamarías desde una abstracción lo discretizas en objetos y con esos objetos si lo requieres podrías componer la entidad original. Creo que es un tema para analizar mas. Donde me recomiendas buscar mas información. gracias!!!
@anaguerravega66032 жыл бұрын
Buenísimo Carlos, qué alegría volver a disfrutar de tus videos. Gracias!
@dodo118582 жыл бұрын
Grande Carlos! Se te echaba de menos por aquí
@elmerdavidentenzamadrigal63 Жыл бұрын
Muchas gracias por toda esta enseñanaza!
@danielvaqueiro91782 жыл бұрын
Antes de nada me sumo a las felicitaciones y alegría de los comentarios por la vuelta de las Rigor Talks. Estoy de acuerdo que en la práctica llegar el estado 2 ya sería un buen compromiso en la mayoría de los casos y entiendo perfectamente el matiz introducido en el estado 3 aunque el ejemplo tenía algún problema como se ha indicado en algún comentario. Tengo una duda que quizás no es el centro del video pero me genera dudas. Porqué el command handler no persiste de nuevo el Product? se trata de una simplificación? se esperaría lanzar el evento y guardarlo al estilo CQRS? Muchas gracias de antemano Carlos, he asistido recientemente en la pulpocon al taller de CQRS y la verdad un placer haber compartido contigo y el resto de asistente ese momento.
@CarlosBuenosvinosZamora2 жыл бұрын
Lo de persistirlo al final del Command Handler depende principalmente de la configuración del contexto transaccional de ejecución del Command Handler, que es lo mismo que decir que si antes de ejecutar el Command Handler, alguien ha hecho un "beginTransaction" y después un "commit". En mi caso, como los CH los ejecuto a través de un Command Bus al que le configuro un Middleware Transaccional (que hace lo de abrir y cerrar transaction antes y después de ejecutar el Command Handler), no hace falta volver a persistir la entidad (que es la forma más DDD si el ORM y el Command Bus te acompañan ya que en la vida útil de una entidad, se crea y se agrega al repositorio sólo una vez en la vida, luego puedes modificarla pero al estar ya en el dominio no hace falta volverla a persistir, de la misma forma que no hace falta volverla a crear). Si te falta alguna de esas piezas, pues vuelves a persistirla y tampoco me tiro de los pelos.
@minayaserrano2 жыл бұрын
¡Notición del día, el regreso de las rigor talks! Mil gracias por compartir estas "perlitas" :)
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias a ti!
@DiegoGarcia-ln3sz2 жыл бұрын
Siempre he llegado hasta el paso 2. Y claro que los agregados quedan gorditos. No había considerado la opción 3. Es interesante, aunque como todo, tiene sus propios retos. Gracias Carlos. Sigue subiendo contenido. ¡Enhorabuena!
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Diego, te animo a pensar qué cambios tienes que introducir para llegar al tercer paso con tu stack actual.
@kmiiloberrio-dev Жыл бұрын
@@CarlosBuenosvinosZamora Esta bueno, llegue a pensar, de que las entidades o modelo de dominio pasarían a ser las clases base, en este caso Product, y los agregados para cada caso de uso seria DisabledProduct y EnabledProduct, claro si nuestra arquitectura la combinamos con vertical slicing, nos quedaría un dominio en la capa de shared, de tal forma que cada caso de uso tenga su propio agregado mas semántico. Claro que esto a nivel de clases crecería mucho, pero creo que a nivel de mantenibilidad y SOLID quedaría mas churro.
@jonmaurolagoitia77022 жыл бұрын
Qué buena noticia que vuelvan los rigor talks! A la espera que del vídeo que comentas de tell-dont-ask cuando la entidad necesita info externa, por ejemplo de otros agregados
@CarlosBuenosvinosZamora2 жыл бұрын
Mírate el que acabo de publicar sobre Agregados y Domain Services y coméntame si necesitas alguna cosa más. Puedo hacer quizá uno donde hagan falta múltiples Agregados.
@FernandoPalacios262 жыл бұрын
Hace tiempo esperaba una actualización de la serie. Supongo que por ahi has notado nuevos casos y/o problemas comunes, seria bueno tambien verlos actualizados en la serie. Excelente video!
@CarlosBuenosvinosZamora2 жыл бұрын
Me revisaré los vídeos anteriores, pero te diría que la gran mayoría, por no decir todos, son bastante atemporales. Los reviso!
@algiru2 жыл бұрын
Grande! Retomando las charlas técnicas.
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias!
@gerarduab99602 жыл бұрын
Tu vídeos siempre son ricos en conocimiento
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Gerard! Me alegro que sean útiles!
@LucasMancini2 жыл бұрын
Excelente charla amigo!! Felicidades por tan buena calidad de los contenidos.
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Lucas!
@micanal70532 жыл бұрын
¡Qué Grande Carlos! Que bien lo explicas, no pares. Una pregunta en el caso 3, entiendo que el DisabledCommandHandler y su EnbaledRepository no encontraran un producto que este disabled, pero como podemos diferenciar si es que no lo encuentra porque esta disabled o porque el ID no existe, si es que necesitamos hacer cosas distintas en cada caso? Por ejemplo si esta ya disable, simplemente no hacer nada, y si el Id no existe lanzar una excepción, es algo que puede hacer el propio repo? Gracias Carlos.
@CarlosBuenosvinosZamora2 жыл бұрын
Correcto, podrías hacerlo con un método en el repo
@juanpablocanepaalvarez9607 Жыл бұрын
Buenas tardes, muy iteresante el contenido sobre como separar la lógica enriqueciendo el dominio, pero quisiera entender cual sería la diferencia entre un CommandHandler y un Service (yo uso Spring) y tengo una clase tipo Service, pero me parece que el Handler cumple una función similar, xfa una aclaración. Gracias.
@RafaDG882 жыл бұрын
Que alegría Carlos volverte a ver por aquí. Una duda que me ha surgido al ver el código es: El método que tienen los CommandHandler para lanzar una excepción si no se encuentra el producto, ¿se podría mover dentro del propio repositorio a un método algo así como ofIdOrFail? Creo que así delegas esa responsabilidad al respositorio y el caso de uso quedaría más limpio. ¿Cómo lo ves? ¿Crees que una buena opción? Un saludo, grande!!
@CarlosBuenosvinosZamora2 жыл бұрын
Sí, esto lo hacía en otros vídeos. Sin problemas. Cuidado que asegurar en PHP que la interfaz del repo lanza una exception en caso de que no exista el producto, no es posible (el típico @throw es indicativo pero no es garantía). Así que depende de que la implementación lo haga. Pero es opción válida, fácil de testear, así que go!
@RafaDG882 жыл бұрын
@@CarlosBuenosvinosZamora perfecto, muchas gracias Carlos :)
@suntzutk2 жыл бұрын
Excelente Carlos, un placer q hayas vuelto por el canal, normalmente llego al 2, el 3 por ahora se me hace algo confuso creo o sobre todo verlo haciendolo con el ORM de turno, supongo q queda ver los trade off un poco del caso, o las imple en doctrine en caso de php, y en caso de existir mas estados y demas como dividir todo o hasta q punto, muy bueno el video, gracias!
@CarlosBuenosvinosZamora2 жыл бұрын
En el caso de PHP con Doctrine, la inheritance relation con discriminador te lo resuelve. Pero me apunto al TODO un video sobre esa y otras soluciones alternativas
@juanal07 Жыл бұрын
Esto es oro
@bikero_ Жыл бұрын
Muchísimas gracias por tus vídeos, Carlos. Como desarrollador habituado a lidiar con legacy code, suponen una inspiración para mejorar en proyectos venideros. Me queda claro que DDD aboga por acotar y separar claramente los contextos/funcionalidades, cada uno con su dominio, que asegura las invariantes y evitando el acoplamiento. De aquí me surge una duda: -¿Cuál es la forma adecuada de validar configuraciones a nivel multitenant? Aplicándolo a tu ejemplo de productos. Supongamos que cada Tenant puede crear un máximo número de productos, pero este número es diferente/parametrizable individualmente. Creo que en la clase Producto no tendría sentido validarlo, pues sólo es consciente de sí misma y no tiene acceso a la información global de base de datos. Probablemente en el repositorio inyectando la configuración del Tenant o directamente validando en el command handler, pero tengo dudas de cuál es la mejor solución, o si existe otra mejor. Gracias de nuevo por el tiempo que dedicas.
@diegguittoo Жыл бұрын
Puedes meter un DomainService (interface) que dependiendo del Tenant devuelva este objeto que tenga el número máximo de productos, por ejemplo y esto lo inyectas en el método de la entidad. Al ser una interfaz de dominio, no hay ningún problema, dependiendo del caso, se puede usar en el Command Handler o en el Agregado
@bikero_ Жыл бұрын
@@diegguittoo Muchas gracias. Le había estado dando vueltas y lo que más me encaja es inyectar ese servicio, como bien indicas. Lo del command handler me parece la segunda opción, aunque tampoco me disgusta
@davidtorrente8992 жыл бұрын
Gracias por seguir con los Rigor Talks Carlos, creo que viene bien a toda la comunidad. En mi caso he llegado siempre al paso 2 intentando empujar toda la logica de dominio lo mas cerca posible del dominio. En el paso 3, crear una especializacion de una entidad solo para empujarlo aun mas a Dominio, creo que seria bastante tedioso . ¿Que ocurre cuando un Objeto Enabled se desactiva? Deberia mutar y cambiar entonces su clase no? porque dejaria de ser enabledProduct para ser disabledProduct, no ? En Doctrine tendrias entonces la entidad Product, EnabledProduct y DisabledProduct mapeadas a sus respectivas tablas y tendrias entonces que mover la fila de una enabled a una tabla disabled(si eliges la estrategia de separar tablas) cuando hagas una operacion de este tipo ? Veo inconvenientes al paso 3, pero en segun que tipo de proyectos y logicas de negocio puede estar bien si no acarrea muchos problemas de performance y gestion de la informacion. Gracias Carlos.
@CarlosBuenosvinosZamora2 жыл бұрын
El objetivo no es empujar la lógica sólo por empujarla, sino para colocarla en aquellos contextos donde tenga más sentido. Tener un agregado Empleado con la gestión de vacaciones, nóminas, y otras responsabilidades separadas no sería mi recomendación. Es por eso que la especialización tiene sentido para aumentar la cohesión dentro de cada agregado y reducir el coupling. Ya he respondido a otros comentarios que el ejemplo que he elegido pueda llevar a confusión del objetivo principal de la técnica. Voy a ver si lo puedo especificar mejor en otro video. Para Doctrine, con un discriminator, se puede hacer fácil. Creo que en general, estamos más acostumbrad@s a no ir al paso 3 por conformismo, comodidad, etc. pero el objetivo del video es animaros a pensar en esa linea.
@angelromeroastorga41722 жыл бұрын
Enorme, muchísimas gracias por el video
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias Angel!
@davidramentol48772 жыл бұрын
Gracias por el video, muy interesante. Me pregunto si no es un poco extraño tener un EnabledProduct al que le llamas al disable() y sigue siendo un EnabledProduct pero disabled. No se si me explico.
@CarlosBuenosvinosZamora2 жыл бұрын
Sí, mea culpa. El objetivo era explicar los repositorios semánticos y después de los comentarios, creo que tendría que haber elegido otro ejemplo (persona, empleado, empleado por horas, empleado jornada completa, por ejemplo)
@r.amilcarrivasmarquez2892 Жыл бұрын
@@CarlosBuenosvinosZamora Quiero pensar que después de llamar a disable() es como eliminarla para ese caso de uso lo que provoca que en la próxima visita al dominio se encuentre en eneable() como si en ese caso de uso fuera un recién llegado.
@andresdiazbcn2 жыл бұрын
Buen vídeo 💪🏼
@kuja692 жыл бұрын
Hola Carlos, ¿En un ORM data mapper como Doctrine, recomiendas crear las entidades de infra con xml para que luego mapeen a entidades de dominio puro o por el contrario prefieres entidades php por anotaciones/atributos de Doctrine con sus propias funciones que mapeen a entidades de dominio puro? A lo mejor tienes otro enfoque diferente. Muchas gracias por tu vídeos. Eres un referente para mí.
@CarlosBuenosvinosZamora2 жыл бұрын
Hola! Veo dos temas en tu comentario. Primero, sobre mappeo en XML o Annotations, prefiero XML casi siempre. Otra cosa es que el algún proyecto sencillo o en algún video por simplificar use las annotations. Segundo, prefiero que no hayan “entidades de infraestructura” y hacer que las entidades de dominio estén bien mapeadas a través del ORM, Doctrine en este caso. Puede darse el caso, que alguna vez sea imposible un mapeo directo y tengas que recurrir a otros “trucos”: entidad de infra, hidratación ad-hoc de la entidad, ids surrogate, tipos básicos en los atributos internos con getters que convierten a Value Objects, etc.
@dioxino762 жыл бұрын
Yo era de las personas que pensaba que en la entidad no debía tener lógica relacionada con ellas, siempre usaba un servicio. Pensaba que las intoxicaba de responsabilidades que no debían ser suyas.
@dioxino762 жыл бұрын
Muchas gracias por compartir tu valiosísima experiencia e impagable conocimiento del mundo del desarrollo.
@CarlosBuenosvinosZamora2 жыл бұрын
A ver si hago un video del motivo de ese estilo. Spoiler: tiene que ver con el éxito de los Java Beans y J2EE que "obligaba" a cierta manera de trabajar y ha ido perdurando en el tiempo.
@k4l1ma2 жыл бұрын
Alguien tiene que decirlo, pero si yo viese una PR con el ultimo enfoque le rechazaría directamente, la simple idea de duplicar el dominio es terrible, el mapeo como dice se vuelve infumable, Crear N entidades por el numero de posibles estados n(o!) ficheros para mantener con logica distribuida y mas si encima toca permutar estados entre varios atributos, Creo q habra un momento y un lugar para un approach asi (everything is a tradeoff) pero creo q este video hace mas daño a la comunidad que el bien que pueda hacer sobre todo para la gente que solo copia. Hay una palabra Shuhari, que describe los estados de maestria, que asemeja el enfoque de este video, Shu va de proteger/obedecer seguir lo establecido (command handlers ✅ pero anémicos❎) Ha romper las reglas o desapego a lo tradicional, (command bus con entidades ricas) Ri trascender y saber moverse de modo natural sin técnicas (everything is a trade off)(duplicar el modelo para representar diferentes estados) Hay q entender que este approach requiere de maestría y no se debe aplicar a la ligera ni como template para todo tipo de proyectos y que probablemente solo deba existir en un momento y un lugar específico
@CarlosBuenosvinosZamora2 жыл бұрын
Gracias por el comentario. Algunas preguntas: Donde ves que se duplique el dominio? Cual es el problema de tener muchos ficheros? Por qué dices que la lógica está distribuida? Qué lógica es la que está distribuida? Qué significa permutar Estados entre atributos? Qué tipo de daño hace el vídeo? A qué comunidad? En qué momento y/o lugar crees que debería usarse sólo este approach? Gracias!
@k4l1ma2 жыл бұрын
@@CarlosBuenosvinosZamora Suponiendo tener mas de un estado GreenEnabled GreenDisabled BlueEnabled BlueDisabled cuando probablemente todo sea un product con a lo mas un builder o un factory, lo de duplicar fichero mas que nada por la complejidad de saber en el momento de hacer un cambio donde esta este cambio distribuido entre varios ficheros para cada uno de estos estados, por aquello de agrupar la logica por estado (color) o un estado (enabled disabled), creo que este approach no es 101 de OO y puede hacer mucho mas daño a toda la gente que como dije en el anterior comentario no esta en ese nivel de maestria para entender por que este enfoque existe y esta alli, como figura publica entiendo que estos videos llegan a todo los niveles, los que entienden que hay un momento y un lugar y los que creen q deben seguir estos approaches por que son de rigor, Creo que básicamente lo que has intentado hacer es un Strategy pattern encapsulando la logica de cada estrategia en un objeto solo que en el video se ve mas como encapsulado en diferentes entidades que extienden de la misma entidad producto lo q termina pudiendo ser visto como diferentes entidades cuando lo mas seguro es q tu dominio solo hable de productos y no de EnabledProduct and DisabledProduct Strategy siendo un patron de diseño de comportamiento tiene muchos momentos y lugares pero no creo q sea algo para toda ocasión Pero lo de tener diferentes entidades mapeada por el orm al mismo sitio suena a que podria traer mas problemas que lo que este approach intenta solucionar De hecho probablemente habrias podido obtener el mismo resultado con solo una entidad producto y aplicando realmente un Strategy pattern o varios para varios estados y asi poder hacer plug and play de diferentes permutaciones sin la necesidad de mappear varias entidades, y mantener la logica encapsulada en cada una de las estrategias Saludos !
@CarlosBuenosvinosZamora2 жыл бұрын
@@k4l1ma Mi intención con el vídeo no es explicar State Pattern, Strategy Pattern ni cualquier otro behavioral, sino mucho más sencillo: recomendar sacar lógica de los Command Handlers y metedla donde toca (a veces Entidades, otras Value Objects, … con más o menos patrones, con un diseño más sencillo o complejo). Me apunto hacer un par de vídeos sobre diseño aplicando esos patrones.
@extjmv2 жыл бұрын
Imagina que cuando el product está enabled, es obligatorio que tenga imagen. Pero cuando está disabled o draft, no es obligatorio. La propiedad $image, tendria una definición diferente en cada caso. De hecho, un producto enabled, no permitiría un update con una url de la imagen invalida. En cuando complicas un poco el negocio, tener varias versiones de tu entidad cobra mucho sentido, para no acabar con miles de if por los campos que dependen del estado.
@k4l1ma2 жыл бұрын
@@extjmv puedes conseguir lo mismo encapsulado los estados en objetos o VO pero usando una unica entidad y asi te olvidas de mappear varias entidades a una misma colleccion o tabla en el ORM y consigues liberarte de los varios if, el problema de este approach es que introduce mas problemas que los que intenta resolver con la duplicidad de las entidades, y que problamente necesites introducir logica donde antes no la necesitabas ejemplo supongamos q tienes tus entidadaes EnabledProduct y DisabledProduct y tus repositorios para hacer fetch de esas entidades como en el ejemplo, si haces un DisableProductRepo->find($id) y obtienes un Not Found significa que el producto no existe o que no pudo encontrar un producto con ese ID disabled? sobretodo por q si quieres mantener la idempotencia en un caso tienes q retornar un error al usuario y en el otro solo no hacer nada