The Codest
  • Quiénes somos
  • Servicios
    • Desarrollo de software
      • Desarrollo Frontend
      • Desarrollo backend
    • Staff Augmentation
      • Desarrolladores frontales
      • Desarrolladores de backend
      • Ingenieros de datos
      • Ingenieros de la nube
      • Ingenieros de control de calidad
      • Otros
    • Asesoramiento
      • Auditoría y consultoría
  • Industrias
    • Fintech y Banca
    • E-commerce
    • Adtech
    • Tecnología sanitaria
    • Fabricación
    • Logística
    • Automoción
    • IOT
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • Nuestro equipo
  • Case Studies
  • Saber cómo
    • Blog
    • Meetups
    • Seminarios en línea
    • Recursos
Carreras profesionales Póngase en contacto
  • Quiénes somos
  • Servicios
    • Desarrollo de software
      • Desarrollo Frontend
      • Desarrollo backend
    • Staff Augmentation
      • Desarrolladores frontales
      • Desarrolladores de backend
      • Ingenieros de datos
      • Ingenieros de la nube
      • Ingenieros de control de calidad
      • Otros
    • Asesoramiento
      • Auditoría y consultoría
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • Nuestro equipo
  • Case Studies
  • Saber cómo
    • Blog
    • Meetups
    • Seminarios en línea
    • Recursos
Carreras profesionales Póngase en contacto
Flecha atrás VOLVER
2022-04-05
Desarrollo de software

Aplicación del patrón de casos de uso con Rails

Nicolas Nisoria

Un problema habitual al trabajar con Rails es decidir dónde colocar la lógica de nuestras funcionalidades.

La lógica a menudo se coloca en los Controladores, Modelos, o si tenemos suerte en un Objeto de Servicio. Entonces, si tenemos Objetos de Servicio, ¿por qué necesitamos Casos de Uso?

Sígueme en este artículo para descubrir los beneficios de este patrón.

Caso práctico

Definición

Un caso de uso es una lista de acciones o pasos de eventos que suelen definir las interacciones entre un rol y un sistema para alcanzar un objetivo.

Vale la pena mencionar que este patrón se aplica de muchas maneras diferentes y tiene nombres alternativos. Podemos encontrarlo como Interactores, Operadores o Comandospero en el Ruby comunidad con la que nos quedamos Caso práctico. Cada implementación es diferente, pero con el mismo propósito: servir a un caso de uso del sistema por parte del usuario.

Aunque en nuestro proyecto no estamos definiendo los requisitos utilizando Caso prácticos y UML este patrón sigue siendo útil para estructurar la lógica empresarial de forma práctica.

Reglas

Nuestra Casos prácticos debe ser:

  • Marco agnóstico
  • Base de datos agnóstica
  • Responsable de una sola cosa (definir los pasos para alcanzar el objetivo del usuario)

Beneficios

  • Legibilidad: Fácil de leer y entender ya que los pasos están claramente definidos.
  • Desacoplamiento: Desplazar la lógica de Controladores y Modelos y crear un nuevo nivel de abstracción.
  • Visibilidad: El código base revela las funciones disponibles en el sistema.

A la práctica

Tomemos el ejemplo de un usuario que quiere comprar algo en nuestro sistema.

módulo UseCases
  módulo Buyer
    clase Compra
      def initialize(comprador:, carrito:)
        @comprador = comprador
        @carrito = carrito
      end
      def call
        return unless comprobar_stock
        return unless crear_compra
notify end
privado
      attr_reader :comprador, :carrito
      def comprobar_stock
        Services::CheckStock.call(carrito: carrito)
end
      def crear_compra
        Servicios::CrearCompra.call(comprador: comprador, carrito: carrito).call
      end
      def notificar

         Servicios::NotificarComprador.call(comprador: comprador)
       end
     end
   end
 fin

Como puede ver en este código creamos un nuevo Caso práctico llamado Compra. Definimos sólo un método público llame a. Dentro del método call, encontramos pasos bastante básicos para realizar una compra, y todos los pasos están definidos como métodos privados. Cada paso está llamando a un Objeto de Servicio, de esta forma nuestro Caso práctico es sólo definir los pasos para realizar una compra y no la lógica en sí. Esto nos da una idea clara de lo que se puede hacer en nuestro sistema (realizar una compra) y los pasos para conseguirlo.

Ahora estamos listos para llamar a nuestro primer Caso práctico de un controlador.

clase Controlador
  def compra
    UseCases::Comprador::Compra.new(
      comprador: parámetros_compra[:comprador],
      carrito: parámetros_de_compra[:carrito]
    ).call

    ...
  fin

  ...
fin

Desde esta perspectiva, la Caso práctico se parece bastante a un Objeto de Servicio pero el propósito es diferente. Un Objeto de Servicio realiza una tarea de bajo nivel e interactúa con diferentes partes del sistema como la Base de Datos mientras que el Objeto de Servicio El caso de uso crea una nueva abstracción de alto nivel y define los pasos lógicos.

Mejoras

Nuestro primer Caso práctico funciona pero podría ser mejor. ¿Cómo podríamos mejorarlo? Utilicemos el seco gemas. En este caso vamos a utilizar transacción en seco.

Primero definamos nuestra clase base.

clase UseCase
  include Dry::Transacción

  class << self
    def llamada(**cargas)
      new.call(**args)
    end
  end
end

Esto nos ayudará a pasar atributos a la transacción UseCase y utilizarlos. Entonces estamos listos para redefinir nuestro Caso de Uso de Compra.

módulo UseCases
  módulo Buyer
    clase Compra
      def initialize(comprador:, carrito:)
        @comprador = comprador
        @carrito = carrito
      end

      def call
        return unless comprobar_stock
        return unless crear_compra
        notificar
      end

      privado

      attr_reader :comprador, :carrito

      def comprobar_stock
        Services::CheckStock.call(carrito: carrito)
      end

      def crear_compra
        Servicios::CrearCompra.call(comprador: comprador, carrito: carrito).call
      end

      def notificar
        Servicios::NotificarComprador.call(comprador: comprador)
      end
    end
   end
 end

Con los nuevos cambios, podemos ver de forma clara como se definen nuestros pasos y podemos gestionar el resultado de cada paso con Success() y Failure().

Estamos listos para llamar a nuestro nuevo Caso de Uso en el controlador y preparar nuestra respuesta dependiendo del resultado final.

clase Controlador
  def compra
    UseCases::Comprador::Compra.new.call(
      comprador: parámetros_compra[:comprador],
      carrito: parámetros_de_compra[:carrito]
    ) do |result|
      result.success do
        ...
      end
      resultado.fallo do
        ...
      end
    fin

    ...
  fin

  ...
fin

Este ejemplo podría mejorarse aún más con validaciones, pero es suficiente para mostrar la potencia de este patrón.

Conclusiones

Seamos sinceros, el Patrón de casos de uso es bastante simple y se parece mucho a un Objeto de Servicio, pero este nivel de abstracción puede suponer un gran cambio en tu aplicación.

Imagina que un nuevo desarrollador se une al proyecto y abre la carpeta use_cases, como primera impresión tendrá una lista de todas las funcionalidades disponibles en el sistema y tras abrir un Caso de Uso verá todos los pasos necesarios para esa funcionalidad sin profundizar en la lógica. Esta sensación de orden y control es el mayor beneficio de este patrón.

Llévese esto en su caja de herramientas y quizá en el futuro haga buen uso de él.

Artículos relacionados

Desarrollo de software

Ruby on Rails modularización con Packwerk Episodio I

A los humanos nos resulta difícil ver el panorama general de un problema sin dedicarle mucho tiempo y esfuerzo. Esto ocurre especialmente cuando se trabaja con aplicaciones grandes y complejas....

Nicolas Nisoria
Desarrollo de software

Modularización Ruby on Rails con Packwerk Episodio II

En el segundo episodio de nuestra modularización Ruby on Rails con Packwerk vamos a examinar detenidamente el concepto de aplicación como paquete.

Nicolas Nisoria
Desarrollo de software

Ferrocarriles y otros medios de transporte

Rails es un framework compatible con Rack centrado en el desarrollo rápido de aplicaciones. Desafortunadamente, el enfoque de "todo fuera de la caja" y el comportamiento ciego Rails-manera a menudo hacen que el código de la aplicación pierda calidad,...

The Codest
Krzysztof Buszewicz Senior Software Engineer

Suscríbase a nuestra base de conocimientos y manténgase al día de la experiencia del sector informático.

    Quiénes somos

    The Codest - Empresa internacional de desarrollo de software con centros tecnológicos en Polonia.

    Reino Unido - Sede central

    • Oficina 303B, 182-184 High Street North E6 2JA
      Londres, Inglaterra

    Polonia - Centros tecnológicos locales

    • Parque de oficinas Fabryczna, Aleja
      Pokoju 18, 31-564 Cracovia
    • Embajada del Cerebro, Konstruktorska
      11, 02-673 Varsovia, Polonia

      The Codest

    • Inicio
    • Quiénes somos
    • Servicios
    • Case Studies
    • Saber cómo
    • Carreras profesionales
    • Diccionario

      Servicios

    • Asesoramiento
    • Desarrollo de software
    • Desarrollo backend
    • Desarrollo Frontend
    • Staff Augmentation
    • Desarrolladores de backend
    • Ingenieros de la nube
    • Ingenieros de datos
    • Otros
    • Ingenieros de control de calidad

      Recursos

    • Hechos y mitos sobre la cooperación con un socio externo de desarrollo de software
    • De EE.UU. a Europa: ¿Por qué las startups estadounidenses deciden trasladarse a Europa?
    • Comparación de los polos de desarrollo de Tech Offshore: Tech Offshore Europa (Polonia), ASEAN (Filipinas), Eurasia (Turquía)
    • ¿Cuáles son los principales retos de los CTO y los CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Condiciones de uso del sitio web

    Copyright © 2025 por The Codest. Todos los derechos reservados.

    es_ESSpanish
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean nl_NLDutch etEstonian elGreek es_ESSpanish