Cocinando Command Handlers "Ricos En Hierro" (No Anémicos)

  Рет қаралды 3,846

Carlos Buenosvinos

Carlos Buenosvinos

Күн бұрын

Пікірлер: 62
@izharsanz
@izharsanz 2 жыл бұрын
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 :)
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias! Alegría la mía al ver vuestras reacciones. Seguimos!
@jammaj5
@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
@ciltocruz Жыл бұрын
Hostia, el caso 3 es rizar el rizo. Chapeau. Brillante.
@SamuDeep13
@SamuDeep13 2 жыл бұрын
Me he sentido feliz al ver en el feed un video de nuevo! Enhorabuena y espero que siga durante mucho tiempo!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Samuel!
@andrescristancho3851
@andrescristancho3851 Жыл бұрын
Muy feliz de encontrar nuevo contenido tuyo Carlos. 🎉🎉🎉🎉
@javiermadueno
@javiermadueno 2 жыл бұрын
Que bueno verte de nuevo por aqui! May the rigor be with you!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Javier! Yo también tenía ganas de compartir algunas cositas :)
@r.amilcarrivasmarquez2892
@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!!!
@anaguerravega6603
@anaguerravega6603 2 жыл бұрын
Buenísimo Carlos, qué alegría volver a disfrutar de tus videos. Gracias!
@dodo11858
@dodo11858 2 жыл бұрын
Grande Carlos! Se te echaba de menos por aquí
@elmerdavidentenzamadrigal63
@elmerdavidentenzamadrigal63 Жыл бұрын
Muchas gracias por toda esta enseñanaza!
@danielvaqueiro9178
@danielvaqueiro9178 2 жыл бұрын
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.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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.
@minayaserrano
@minayaserrano 2 жыл бұрын
¡Notición del día, el regreso de las rigor talks! Mil gracias por compartir estas "perlitas" :)
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias a ti!
@DiegoGarcia-ln3sz
@DiegoGarcia-ln3sz 2 жыл бұрын
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!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Diego, te animo a pensar qué cambios tienes que introducir para llegar al tercer paso con tu stack actual.
@kmiiloberrio-dev
@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.
@jonmaurolagoitia7702
@jonmaurolagoitia7702 2 жыл бұрын
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
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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.
@FernandoPalacios26
@FernandoPalacios26 2 жыл бұрын
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!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Me revisaré los vídeos anteriores, pero te diría que la gran mayoría, por no decir todos, son bastante atemporales. Los reviso!
@algiru
@algiru 2 жыл бұрын
Grande! Retomando las charlas técnicas.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias!
@gerarduab9960
@gerarduab9960 2 жыл бұрын
Tu vídeos siempre son ricos en conocimiento
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Gerard! Me alegro que sean útiles!
@LucasMancini
@LucasMancini 2 жыл бұрын
Excelente charla amigo!! Felicidades por tan buena calidad de los contenidos.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Lucas!
@micanal7053
@micanal7053 2 жыл бұрын
¡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.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Correcto, podrías hacerlo con un método en el repo
@juanpablocanepaalvarez9607
@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.
@RafaDG88
@RafaDG88 2 жыл бұрын
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!!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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!
@RafaDG88
@RafaDG88 2 жыл бұрын
@@CarlosBuenosvinosZamora perfecto, muchas gracias Carlos :)
@suntzutk
@suntzutk 2 жыл бұрын
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!
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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
@juanal07 Жыл бұрын
Esto es oro
@bikero_
@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
@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_
@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
@davidtorrente899
@davidtorrente899 2 жыл бұрын
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.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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.
@angelromeroastorga4172
@angelromeroastorga4172 2 жыл бұрын
Enorme, muchísimas gracias por el video
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
Gracias Angel!
@davidramentol4877
@davidramentol4877 2 жыл бұрын
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.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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
@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.
@andresdiazbcn
@andresdiazbcn 2 жыл бұрын
Buen vídeo 💪🏼
@kuja69
@kuja69 2 жыл бұрын
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í.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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.
@dioxino76
@dioxino76 2 жыл бұрын
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.
@dioxino76
@dioxino76 2 жыл бұрын
Muchas gracias por compartir tu valiosísima experiencia e impagable conocimiento del mundo del desarrollo.
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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.
@k4l1ma
@k4l1ma 2 жыл бұрын
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
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
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!
@k4l1ma
@k4l1ma 2 жыл бұрын
@@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 !
@CarlosBuenosvinosZamora
@CarlosBuenosvinosZamora 2 жыл бұрын
@@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.
@extjmv
@extjmv 2 жыл бұрын
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.
@k4l1ma
@k4l1ma 2 жыл бұрын
​@@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
Rigor Talks - PHP - #25 - Persisting Domain Events (Spanish)
12:50
Carlos Buenosvinos
Рет қаралды 3,9 М.
Introducción a Domain-Driven Design en Tarragona Developers (tgndevs)
2:28:20
小蚂蚁会选到什么呢!#火影忍者 #佐助 #家庭
00:47
火影忍者一家
Рет қаралды 125 МЛН
Sigma baby, you've conquered soap! 😲😮‍💨 LeoNata family #shorts
00:37
Não sabe esconder Comida
00:20
DUDU e CAROL
Рет қаралды 55 МЛН
Mom had to stand up for the whole family!❤️😍😁
00:39
Entrevista Carlos Buenosvinos: Director Técnico Xing / Ex-CTO Atrápalo
37:39
CodelyTV - Redescubre la programación
Рет қаралды 10 М.
Agregados y Domain Services, una historia de amor incomprendida
9:39
Carlos Buenosvinos
Рет қаралды 6 М.
Genéricos en Go (Parte 1) #golang #generics #programacion
27:31
Agustin Couding
Рет қаралды 21
Live Coding en Geekshubs: Refactorizando Aplicaciones PHP
1:28:12
Carlos Buenosvinos
Рет қаралды 6 М.
Rigor Talks - PHP - #20 - Application Services & Command Handlers (Spanish)
12:55
Rigor Talks - PHP - #21 - Command Bus (Spanish)
12:43
Carlos Buenosvinos
Рет қаралды 7 М.
Por qué NO usar getters y setters | Tell don't ask
14:46
CodelyTV - Redescubre la programación
Рет қаралды 68 М.
Lecture 1: Course Overview + The Shell (2020)
48:17
Missing Semester
Рет қаралды 754 М.
Rigor Talks - PHP - #17 - Refactor Use Case V (Spanish)
12:25
Carlos Buenosvinos
Рет қаралды 3,1 М.
Rigor Talks - PHP - #31 - Viewing Domain Events with Kibana (Spanish)
15:59
Carlos Buenosvinos
Рет қаралды 2,8 М.
小蚂蚁会选到什么呢!#火影忍者 #佐助 #家庭
00:47
火影忍者一家
Рет қаралды 125 МЛН