Mejora la Calidad de tu Código utilizando Value Objects

แชร์
ฝัง
  • เผยแพร่เมื่อ 7 มิ.ย. 2023
  • El patrón Value Object es uno de los más famosos en cuanto a Diseño de Software, pero también uno de los más odiados.
    Curso de Value Objects! bit.ly/curso-vo
    Es criticado porque nos induce a "classitis" y porque añade complejidad al código, pero, en nuestra opinión, los beneficios compensan de forma desmesurada a sus contraprestaciones.
    En este vídeo te demostramos que programar con Value Objects acaba simplificando mucho tu código
    ﹤🍍﹥ CodelyTV
    ├ 🎥 Suscríbete: th-cam.com/users/CodelyTV?sub_co...
    ├ 🐦 Twitter CodelyTV: / codelytv
    ├ 🧔🏻 Twitter Javi: / javiercane
    ├ 💂‍♀️ Twitter Rafa: / rafaoe
    ├ 📸 Instagram: / codelytv
    ├ ℹ️ LinkedIn: / codelytv
    ├ 🥋 Academy: codely.com/academy
    └ 📕 Catálogo cursos: bit.ly/cursos-codely
  • วิทยาศาสตร์และเทคโนโลยี

ความคิดเห็น • 55

  • @ciltocruz
    @ciltocruz ปีที่แล้ว +61

    No suelo comentar mucho, pero hay que decir que la presentación del código, cómo cambian las diapositivas y la explicación a medida que va ocurriendo ha sido BRILLANTE.

  • @felixinit
    @felixinit 8 หลายเดือนก่อน +6

    Que forma tan pro de llevar al siguiente nivel la programación. Es el tipo de formación que deseo para mí. Una vez comprendido lo básico de programación uds son el siguiente paso lógico en nuestra formación.

  • @Ak4n0
    @Ak4n0 10 หลายเดือนก่อน +3

    Me impresiona que todos esto 'modelos' o 'arquitecturas' es hacer lo que has hecho toda la vida solo que alguien le ha puesto un nombre elegante.

  • @art_bat
    @art_bat ปีที่แล้ว +37

    La expresión regular del email debería ser estática, para no hacer que el motor JS tenga que compilar la misma expresión una y otra vez en cada instanciación de value object

    • @JorgeDev92
      @JorgeDev92 ปีที่แล้ว +9

      A mi ya de entrada me parece extremadamente raro tener que validar tan profundamente que el email es un email y además validarlo en el momento de su creación y durante el resto de su vida, como si alguien fuese a coger la bdd y a romperla, normalmente yo valido estos inputs lo más pronto posible en el tipico middleware de validación.
      En clases tan chorras como las que mencionan en sus ejemplos tal vez no es evidente, pero instanciar 150 propiedades (que pueden repetirse si es un array de objetos) de un modelo bien complejo (por ejemplo, nuestro order tiene de todo, cupones, descuentos a nivel de pedido, a nivel de transporte, a nivel de producto, todos los datos de producto congelados el dia de la creación, etc...) no es gratis, es la diferencia entre que una petición gaste 1MB de ram o gaste 10MB, por no hablar de que la ram irá subiendo más rápidamente y hará falta mas GC, si encima esta ram sube tan rapido que no puede limpiarse con 3GC de vida corta (rapido) entraran en el GC de vida larga (lento), además de lo evidente, hacer new es más CPU, en un objeto no es apreciable, en un proceso que use muchos de estos objetos tal vez el tiempo y la ram pasen a ser un problema.
      Si tuviese que seguir este patrón lo haría solo donde hace falta y solo cuando hace falta, es decir, si me viene de la bdd debería de suponer que la base de datos no está rota, ya que si al guardar has validado no tiene porque romperse mágicamente.
      Otra cosa que es bastante evidente es la polución que hay en el codigo, cada propiedad tiene la propiedad en la clase, el getter, el setter, la propiedad en los parametros del constructor, la propiedad que setean en el constructor, osea, por cada propiedad vienen a ser tranquilamente 12 lineas de código, que de nuevo, no se aprecia bien dado el tamaño de la clase, pero ya se intuye, con solo 3 propiedades el codigo no les cabe en la pantalla, imaginate el ejemplo anterior, recordemos que tener ValueObjects no es la única manera de hacer una validación, perfectamente si no quieres ensuciar la clase lo puedes sacar fuera con funciones exactamente de la misma manera que los ValueObjects y usarlos cuando hace falta, que no tiene porqué ser necesariamente en el constructor, donde se ejecutará en cada instanciación

    • @lococba84
      @lococba84 ปีที่แล้ว +1

      @@JorgeDev92 Por eso la programación con paradigma mas funcional está ganando la pulseada, yo ahora estoy explorando la arquitectura vertical slice, donde si bien hay acoplamiento permite generar responsabilidad única por cada funcionalidad que se desarrolle y es mas flexible ya que si hay que aplicar DDD también es posible.

    • @gurugamer176
      @gurugamer176 ปีที่แล้ว

      @@lococba84 siempre ha sido el vencedor

    • @gurugamer176
      @gurugamer176 ปีที่แล้ว

      eso deberia estar separado en una clase de validacion, por otra parte no se compila sino se interpreta en este caso de js...

    • @carlossolorzano505
      @carlossolorzano505 7 หลายเดือนก่อน

      @@lococba84 Hola, me parece super interesante y valido este punto. De casualidad tienes algún ejemplo que puedas compartir para terminar de entenderlo?

  • @matiasjaime3443
    @matiasjaime3443 9 หลายเดือนก่อน +3

    INCREIBLE la calidad del video
    Super claro

  • @jmanuelcorral
    @jmanuelcorral ปีที่แล้ว +5

    Buenas introducción, me ha encantado! la unica pega es que personalmente no me gusta que un value object devuelva excepciones. Ya que imaginemos que incumples varias validaciones con ello dentro de un ValueObject, sólo la primera que ocurra será la que haga early exit del objeto. Vi otro video en el que usabais EITHER como monada y creo que vi otro con Results... si los combinais y haceis un metodo create estático (poniendo constructor a privado), tendríais lo que buscais pero devolviendo "un tipo de resultado que no es una excepción". Eso es muy util por ejemplo cuando has de devolver resultados que no son "totalmente correctos" o "totalmente falsos", por ejemplo imaginad un alta de un usuario en el que faltan ciertos datos del usuario para hacer ciertas operaciones, puedes tener "warnings" para esos casos de uso...

    • @CodelyTV
      @CodelyTV  ปีที่แล้ว +9

      Ahí diferenciamos el tratamiento de validaciones de cara al usuario, como lo sería el formulario que comentas, de lo que entenderíamos cómo garantizar esas reglas de integridad. Es decir, en el punto en el que estamos sí entendemos cómo excepcional que nos llegue un valor incorrecto, pero antes, en la capa del controlador por ejemplo, sí meteríamos las validaciones que comentas enfocadas a mejor UX 👼

  • @r.amilcarrivasmarquez2892
    @r.amilcarrivasmarquez2892 ปีที่แล้ว +1

    Mejoran con los años... En hora bueno. Me ha servido mucho está clase

  • @arialapps
    @arialapps 8 หลายเดือนก่อน

    Gracias por el contenido, muy bueno!! Una mejora que veo es no colocar las validaciones y excepciones en el constructor de VO, el constructor debería estar limpio, por lo tanto, crearía un método estático "Create" en el VO donde valido y llamo a mi constructor privado.

  • @thisisaavv
    @thisisaavv ปีที่แล้ว

    Gracias por estos videos. 🙋🏽‍♂

  • @esteam
    @esteam 8 หลายเดือนก่อน +1

    Corríjanme si me equivoco pero no que inversión de control es cuando se le pasa el control de las instancias a otro?, generalmente un framework, creo que se refieren a IoC como a inversión de dependencia.

  • @tuttodev
    @tuttodev ปีที่แล้ว +1

    Excelente video, primero felicitarlos, una pregunta, que pasa si un value object no solo tiene un value sino más de uno ? es decir por ejemplo el value object credentials en donde tenga userName y userPassword como value object ? es más que pasa si el value userPassword sea otro value object llamada Password

  • @victrio1996
    @victrio1996 ปีที่แล้ว

    tengo una duda respecto al uso del patrón repository, en este caso se llama al repositorio desde la capa de aplicación, yo acostumbro a inyectar el repo en la entidad del dominio y desde ahí hacer el registro.

  • @NulledExp
    @NulledExp ปีที่แล้ว +3

    Grande chicos grandes excelente todo su contenido como siempre

  • @oscarsanchez5530
    @oscarsanchez5530 ปีที่แล้ว

    Uaahhhh!!!! !buenisisisisisimo vídeo!!!!!!

  • @dtito1991
    @dtito1991 ปีที่แล้ว +2

    Creo que ni bien vi el video me falto costo entrar en ritmo con "userRegistrar" y un metodo "register", tal vez más coherencia con todo ingles o español.

  • @xxnurioxx
    @xxnurioxx ปีที่แล้ว +4

    Es mucho más reutilizable, mucho más mantenible y muchísimo más simple, crear validadores externos a los modelos que hacer toda esta liada. 🥺😜🤗

  • @carlosdavila4999
    @carlosdavila4999 ปีที่แล้ว +1

    Y que pasa cuando el valueObject es otra clase, por ejemplo Factura -> detalle ?

  • @oscargalvez4
    @oscargalvez4 ปีที่แล้ว +6

    Iba a preguntar por qué no recibir los value objects desde fuera (yo personalmente le veo más ventajas siempre que se haga bien y sólo para las capas de dominio y aplicación), pero ya veo que lo comentáis en el curso. Así que habrá que activar la cuenta. 😂

    • @CodelyTV
      @CodelyTV  ปีที่แล้ว +1

      Tú sí que sabes!! 💪

  • @crayder03
    @crayder03 4 หลายเดือนก่อน

    ¿con que programa hacen las presentaciones?

  • @jesusledesma895
    @jesusledesma895 ปีที่แล้ว

    Hay algo que me gustaria plantear, supongamos que estamos en un contexto de clean-architecture, si tengo validaciones que necesitan usar librerias externas estoy poniendo en mi dominio esas librerias que deberian estar en una capa superior (A menos que armemos alguna interfaz para comunicarnos con esa libreria y que usemos desde la clase de dominio)
    Otra opcion que yo veo, es crear una clase builder, un UserBuilder que dentro llame a 3 ValidationService (uno para cada property). Luego para solventar que el mail se pueda modificar tendriamos un UpdateUserUseCase, donde un metodo seria updateMail en cual dentro tambien llamaria al mismo ValidatonService
    Todo esto lo planteo con el objetivo de no llenar mi Clase User con libreria externas, ya que User es de mi dominio

    • @diegoperez6575
      @diegoperez6575 ปีที่แล้ว +2

      Hola, en mi caso suelo usar interfaces que encapsulen las funciones de la librería en algunos casos (por ejemplo date-fns) y en otros (lodash), acabo metiendo directamente el import en la clase del dominio. La verdad es que si se quiere ser 100% ortodoxo con la clean arch, debería ir todo a infraestructura y usar interfaces para desacoplar de las implementaciones reales, pero muchas veces lo asumo por conveniencia. Asumo el riesgo de no ser 100% ortodoxo y de tener ese acoplamiento que me supone por contra menos trabajo que andar montando una interfaz para una llamada a un método de lodash. Al final estas arquitecturas son una filosofía y si se quiere ser 100% estricto, muchas veces se complica demasiado el asunto o se pierde mucho más tiempo. Aunque más que perder, yo diría que quizás pueda ser empleado de forma más productiva en otra parte de la aplicación, como test unitarios, test integrados, alguna refactorización, etc...si tienes tiempo infinito y estás 100% agusto con lo que tienes, pues ahí a tope con la clean arch siempre.

  • @barrenaedu
    @barrenaedu 6 หลายเดือนก่อน

    en el constructor de UserEmail haria la asignacion luego de los ensure, osea: constructor() { this.ensureValueIsDefined(value); this.ensureIsValidEmail(value); this.value = value} ya que utilizan parametros en los ensure. Caso contrario se podrian eliminar los parametros, asignar this.value = value y luego llamar a los ensures sin parametro. Pero el primer caso me gusta mas, no se que piensan uds. Saludos

  • @JSneider05
    @JSneider05 ปีที่แล้ว +1

    🔥 Buen video, a activar esa cuenta. Me gusta este patrón y lo aplico en mis proyectos tal cual. Pero me he enfrentado al problema de que algunos campos del objeto de dominio son opcionales (se actualizan en flujos posteriores de la aplicación).
    ¿Cual seria la buena práctica para manejas VO opcionales pero mantener esas validaciones dentro del VO?
    Recomendaciones?

    • @felixmontalico2735
      @felixmontalico2735 9 หลายเดือนก่อน +1

      Lo que yo hago es que el valor del Value Object pueda ser nulo, para que no se rompa las demás validaciones siempre verifico que no sea nulo. Por ejemplo, si el email es opcional en el ejemplo del video quitaría la validación de ensureValueIsDefined y en la validación de ensureIsValidEmail añadiría una verificación de que si value es nulo se omite dicha validación.

  • @Paul7Peterson
    @Paul7Peterson ปีที่แล้ว +1

    Se puede hacer lo mismo con tipos en TS.
    type UserId = number & { __type__: 'UserId' }

  • @ChaloCode
    @ChaloCode ปีที่แล้ว

    Excelente video, me ayuda un monton!! pregunto sus cursos los tienen para JAVA?

    • @norbertocontreras4725
      @norbertocontreras4725 ปีที่แล้ว

      siempre codean en typescript, solo un par de videos lo hace con Java

  • @gopher9879
    @gopher9879 ปีที่แล้ว

    Esto sería el equivalente a crear un tipo personalizado de go y darle métodos

  • @barrenaedu
    @barrenaedu 6 หลายเดือนก่อน

    Otro comentario, yo soy del mundo java y veo mucho código con el uso excesivo del "this" cuando no es necesario salvo casos especiales (herencias, etc...); en el caso del UserEmail veo que en el constructor usan el "this" para llamar a los métodos ensure, si la cosa funciona como en java yo creo que es una mala costumbre usar el "this" ahí porque se empieza a propagar por todo el código, genera confusión para quien no sabe bien el uso del this, y se termina usando el this para todo como un prefijo que no tiene sentido y se pone "por las dudas" o "porque todo el mundo lo pone". Veo mucho esto, no se que opinan. Saludos.

    • @barrenaedu
      @barrenaedu 6 หลายเดือนก่อน

      Por ejemplo también veo lo estan usando en otros métodos de la clase, creo que ahí se puede mejorar la calidad del código, salvo desconozca algo del lenguaje que usan o haya algun patron/principio que me este pasando por alto; en cuyo caso super agradecido si me lo aclaran. Saludos

  • @Paul7Peterson
    @Paul7Peterson ปีที่แล้ว

    Y para ese "ensureValueIsDefined()" podéis poner como devolución de tipo ": value is string" y un "return true;" para mejorar la inferencia de tipos en hilo.

    • @luka4695
      @luka4695 ปีที่แล้ว

      en que mejoraria poner que devuelva un boolean en un void? que seria mejorar la inferencia?

    • @Paul7Peterson
      @Paul7Peterson ปีที่แล้ว +2

      @@luka4695 Por el narrowing. Al poner "value is string" como tipo de vuelta, cuando usas la función como condicional de bloque, dentro del bloque positivo el valor de la variable que has pasado como 'string | null | undefined' será de 'string'. Se puede hacer un "NotEmptyString" como tipo, pero eso es más avanzado.

    • @luka4695
      @luka4695 ปีที่แล้ว +1

      @@Paul7Peterson gracias por la data

  • @ESArnau
    @ESArnau ปีที่แล้ว

    Habria que añadir el hashtag en los private tambien o no seria necesario? Para que sea 100% privado

    • @Paul7Peterson
      @Paul7Peterson ปีที่แล้ว +2

      TypeScript te lo va a respetar si no haces castings o cosas que no debes, por lo que en la práctica van a ser privados para TypeScript, pero accesibles si no van con el "#".

  • @erickgabrielcampuzanotorre1838
    @erickgabrielcampuzanotorre1838 ปีที่แล้ว

    que fuente y que teman usan en la muestra de codigo?

    • @CodelyTV
      @CodelyTV  ปีที่แล้ว

      Aquí toda la info th-cam.com/video/4anod6sSALE/w-d-xo.html 🙂

  • @lupaco26
    @lupaco26 ปีที่แล้ว

    Actualicen Codely Theme para vscode 😢😢😢 he comprado dank mono y luce genial pero podría ser mejor

  • @felipemedinasalvatierra2094
    @felipemedinasalvatierra2094 ปีที่แล้ว

    Bueno si es un patron, pero VO igual DTO, es mejor usar estos objetos planos para la transferencia de datos y no usar modelos de dominios anemicos como la mayoria lo hace.

  • @hba6018
    @hba6018 2 หลายเดือนก่อน

    Solucion elegante y sin verbosidad? Java Records.

  • @juanluispaz8282
    @juanluispaz8282 ปีที่แล้ว +35

    Uf, cuantas cosas están mal en este vídeo.
    Este patrón es también conocido como tipos opacos, muy común en programación funcional. El objetivo de este patrón es sacarle el máximo provecho al compilador; y al organizar el código con los tipos opacos consigues que las validaciones salgan de un montón de lugares (no solo en tu objeto user), quedando solo en el momento de colección de esos datos; que insisto es ante de crear un objeto user.
    Para ello creas un tipo para un dato concreto y lo usas a lo largo de tu aplicación, no solamente en User.
    Haciéndolo así permites que el compilador te ayude a detectar muchos problemas en muchos lugares diferentes.
    Aquí dicen que se crean una clase UserEmail, eso no existe, existe Email, da igual si se usa en User o no; y debe representar un email válido. En cuando a Id, debe ser una clase que valide que sea un uuid válido, y debe recibir como argumento genérico la entidad para la cual se aplica ese Id, de esa forma el compilador puede detectar el que intentes usar un id de una entidad en otra entidad.
    Si vas a crear una clase con un montón de clases internas solo para evitar llamar una función; y para ello tienes que armar tal lío teniendo que poner getters y setters en todo lados; por favor, no lo hagas, crea tus funciones de validación separadas de User sin más; el código final será más limpio que con estas clases que contienen un valor y que no aportan nada a tu objeto final más allá de complicarlo y de incrementar la presión sobre el recolector de basura.
    El valor del patrón radica en que los tipos opacos sean de uso extendido en la aplicación y no escondidos dentro una sola clase que nadie puede aprovechar.
    Estos tipos opacos normalmente los sueles ver con facilidad cuando haces el diseño de tu base de datos.

    • @gurugamer176
      @gurugamer176 ปีที่แล้ว +1

      Eso mismo pense, ya con eso que explicaste se infringe solid especificamente la responsabilidad unica, deberia haber una clase externa que haga validaciones que sea abstracta a user, user es solo una entidad que representa atributos del usuario

    • @erickjhormanromero6905
      @erickjhormanromero6905 ปีที่แล้ว +1

      Estos manes no saben nada

    • @tupapa7642
      @tupapa7642 9 หลายเดือนก่อน

      Lo único que entendí es que eres virgen JuanLuisPanza

  • @PedroSanchez-od7cc
    @PedroSanchez-od7cc ปีที่แล้ว

    Mucho boilerplate

  • @jorgegustavobanegas8491
    @jorgegustavobanegas8491 9 หลายเดือนก่อน

    Estos videos son un crimen, sobre todo para lo que estan aprendiendo, porque empiezan a aprender las cosas mal.

  • @JoseQR
    @JoseQR ปีที่แล้ว

    Hola!, para las privadas los uso así:
    readonly #id: UserId;