Refactorizando código aplicando Casos de Uso

Refactorizando código aplicando Casos de Uso

Deja una respuesta

Comment as a guest.

  1. Hola excelente tutorial mas bien mi duda seria como la esta la estructura de folders en tu proyectos me imagino que todos las clases de tus casos de uso estan en un folder llamado «UseCases» Y por cada módulo otro subfolder llamado «Profile» Como para tu ejemplo no se si estaría bien de esa forma o como lo trabajas tu? Tambien por ultimo estoy confundido si casos de uso serian igual que servicios? Ya que yo toda la logica del negocio la coloco en una clase por ejemplo «ProfileService» Por eso queria saber la diferencia nose si estaría bien o no para aprender buenas prácticas

    1. Hola Thiago, cómo estás?
      Agrupó por entidades. Por ejemplo, en Profile/ metería todo lo relacionado con este.
      Y la segunda pregunta, si, casos de uso y servicios son lo mismo pero en terminología de Arquitectura Limpia se usa UseCase.
      Lo malo del nombre ProfileService es que no sabes que puede haber ahí adentro. Cualquier programador que quiera agregar una feature relacionada al Profile, seguramente la agregara adentro de esa clase. Es mejor usar Acción+Entidad como lo hago en este artículo.

      1. Me gusto mucho el articulo, y dejo mi comentario aca dado que mi consulta es muy similar a la del amigo Thiago, y siguiendo el hilo, para ese caso recomendarias ordenar la logica que ya esta en services/ProfileService.php pasarla a un subdirectorio organizado por entidad y accion quedando de esta forma: Services/Profile/ UpdateProfile.php y GenerateAvatar.php o hay otra manera de organizar mejor la logica de negocio?

        1. Hola Jose como estas? Me alegro que te haya gustado el artículo!
          Lo ideal es tener Profile/Services/UpdateProfile.php (o cambiar services por UseCases). Por otro lado tener Avatar/Services/GenerateAvatar.php.
          Me parece lo mejor tenerlo así, no solo los casos de uso, sino también su modelo, sus controllers, etc. De esta forma te ahorras tener las cosas separadas por todos lados.
          Si se te hace mucho trabajo hacer esta estructura de carpetas porque es un proyecto heredado, bueno, no esta mal ponerlo como Services/Profiles/[Casos de uso].

          Saludos y gracias por visitar el blog.

        2. Seria interesante que Matias muestre un ejemplo de como podrias hacer esa estructura de carpetas y ver como tener asi un proyecto limpio separando los modelos, controladores, casos, etc.

          Se te agradeceria mucho!

  2. Excelente post, espero que esto ayude a los desarrolladores a ser mejores y dejar de un lado la mediocridad, si en verdad les apasiona la programación, deben hacer el esfuerzo máximo para ser mejor cada día en este campo y que sea un gusto programar, ese código inicial es un desastre, no lo insulto porque todos comenzamos por ahí, conocí alguien que trabajo en una empresa donde realizan exactamente ese mismo tipo de código y no quería mejorar porque así estaban todos sus códigos y todos deben programar así, ósea promoviendo las malas practicas, a compartir este articulo se dijo aver si mejoran.

    1. Si, seguramente varios hemos empezado programando así. Por eso esta bueno que se promuevan las buenas practicas cuando uno las aprende.
      Muchas gracias por tu comentario.

  3. Muy bueno , algo que vi en algunos repos , es que en lugar de usar controladores , los cuales generalmente abusamos de la cantidad de responsabilidades que tiene (los explotamos con un monton de metodos) , se usan actions , seria hacer una clase por cada metodo por ejemplo CreateUserAction , esta clase tendra sus dependencias, junto con su logica y sera mucho mas facil de leer y manejar . Y estaremos cumpliendo con Single Responsibility Principle

    1. Como va Marcelo? Exacto, son lo mismo. En otro lados lo llaman Services también, pero el fin es el mismo.
      A mí me gusta UseCase porque es el mismo lenguaje que usan otros sectores de la empresa, por ejemplo, análisis o QA. Si a un analista le hablas de Actions o Services no te van a entender. Pero sí les hablas de «casos de uso» sabrá exactamente a que te estas refiriendo.

  4. Hola Matias, muy bueno el post.
    Ta hago una consulta, estoy reestructurando una app que tuve que hacer a los ponchazos ya que el cliente necesitaba empezar a vender y bueno esta muy atada con alambre, entonces empece a leer un poco sobre como ordenar todo un poco y hacer mejor las cosas, ya que estoy laburando solo en esto por el momento y por ahora yo lo entiendo, pero se me va a hacer mucho lio.
    Bueno el tema es el siguiente, estoy tratando de aplicar un poco ddd, no a fondo, siguiente la estructura de laravel, y desacoplando lo que hice como service, que imagínate tengo un service por modelo y es un lio barbaro.
    La pregunta en si es la siguiente: estoy armado el action para crear una orden, como esta en el ejemplo, con la función execute que recibe el request y el customer, pero necesito devolver la orden para usarla en el controller y hacer un redirect al show de la orden. Me conviene hacer un return en el execute o podría agregar un método getOrder() para que una vez creada la llamo así , perdón por lo extenso. Muchas gracias.

    1. Como estás Mariano?
      No te hagas problema porque es bastante común hacer un sistema a los ponchazos, ver si es redituable y recién ahí empezar a atender la deuda técnica que dejamos.
      Con respecto a la pregunta, por ahora no estaría mal que execute devuelva la orden. Cuando empieces a implementar DDD puede que tengas que hacer una modificación para esto. Pero te va a llevar un segundo porque ya vas a tener todo ordenado. Por ahora anda paso a paso como estas haciendo.

      Suerte y cualquier cosa volve a darte una vuelta por acá.
      Saludos.

  5. Hola, al igual que tus otros post, este esta genial muy bueno.
    Solo una pregunta en la clase UpdateProfile, en método publico inyecta el request, esto no genera dependencia de lo que venga en el request, ese decir no se le debería pasar como parametro todo lo que vaya a necesitar el método?…Por ejm hay una clase StoreVenta, esta me permite guardar una venta desde un erp(guarda venta, factura, comprobante, etc), ahora se esta desarrollando un POS(otro frontend), y desde ahí también se realiza venta y esta se debe guardar de la misma manera en como se guarda en el erp…Mi pregunta, desde el pos podria llegar la data de una manera distinta, entonces el método(que guarda la venta del erp) de la clase creada ya no me sirve…o como podría ser la estructura, para tener solo un método que se encargue de guardar una venta, venga del erp o pos, o desde una app quizas y que vayan a tener maneras distintas en como llega el request.
    Saludos y gracias de antemano.

  6. Me uno a los amigos que dicen que sería bueno un articulo sobre estructura de tus aplicaciones y donde poner cada cosa.

    Esta página vale oro :), gracias por todo .

  7. Súper buena la explicación muchas gracias, como puedo acceder al articulo que dice ahí que continúa y que habla sobre testeabilidad.

  8. una pregunta, por ejemplo para un listar de productos….es necesario crear una clase useCase para eso? o en el controller puede inyectar por ejemplo el repositorio y llamar al método que trae el listado de productos?

      1. la interfaz, pero es lo correcto eso?, puedo inyectar el repositorio directamente?….es que yo pienso que todo tiene que ir controller -> servicio -> repositorio, pero también lo veo innecesario un useCase(o servicio) para el listar…Lo hize asi, pero vi que en el servicio solo pasaba los mismos parametros al metodo del repositorio. Tengo esa duda o como seria en casos donde no hay logica de nogocio, ejm: un listar, no tiene logica todo viene directo de un script sql…Espero se entienda, gracias

        1. Hola Artura, disculpa la demora en contestar.
          Si, los casos de uso son lógica de negocio. Si solo necesitas obtener los registros y devolverlos, no hace falta que crees un UseCase.

  9. Hola Matias, me encantó el articulo. Tengo una duda en mi proyecto: al desarrollar el caso de uso ‘Invitar usuario a grupo de trabajo’, este se subdivide en 3 casos según si el usuario no está registrado, está registrado pero no tiene perfil adecuado, está registrado y tiene perfil. Debería crear 3 nuevas clases para estos ‘sub-casos de uso’? O realizar toda la logica en el casu de uso principal con metodos privados?

    1. Hola Juan, como estas?
      Lo podrías hacer como métodos privados si son simples. Pero lo ideal sería que los modeles en 3 casos de uso separados.

      1. Perfecto, otra duda que me surgió es como manejar los errores. Si falla algo en los servicios (por ejemplo, usuario ya agregado al grupo de trabajo), como le advierto al controller?

        1. Muy buena pregunta Juan! Fijate que el controller ejecuta los casos de usa dentro de un try/catch, por lo tanto, siempre que haya un error tenes que lanzar una exception y el controller será el encargado de handlearlo.

  10. Buenas tardes Matias, tengo una pequeña duda en un hipotetico caso de uso createProduct.
    El controller ejecutaría el servicio de la siguiente forma: $this->productService->create($data);
    Está bien que el servicio tenga un atributo privado de tipo Product inyectado en el constructor?
    Es decir, está bien que el servicio haga un $this->product->save() luego de asignar los datos al producto ($this->product->fill($data))? O debería hacer un new Product() en lugar de tener el producto como un atributo del servicio?
    Espero se entienda la consulta, saludos!

Sliding Sidebar

Matias Echazarreta

¡Hola!

Mi nombre es Matias Echazarreta.
Soy desarrollador web con más de 12 años de experiencia. Amante de Laravel, de los libros y del rock de los ’90. Te puedes comunicar conmigo  por trabajos de contratación, haciendo click aquí.

Nuestro Patreon

Desde Patreon puedes solicitar asesoria personalizado. ¡Ir a Patreon!

Suscríbete a nuestra lista de correo