The Codest
  • Sobre nós
  • Serviços
    • Desenvolvimento de software
      • Desenvolvimento de front-end
      • Desenvolvimento backend
    • Staff Augmentation
      • Programadores Frontend
      • Programadores de back-end
      • Engenheiros de dados
      • Engenheiros de nuvem
      • Engenheiros de GQ
      • Outros
    • Aconselhamento
      • Auditoria e consultoria
  • Indústrias
    • Fintech e Banca
    • E-commerce
    • Adtech
    • Tecnologia da saúde
    • Fabrico
    • Logística
    • Automóvel
    • IOT
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • A nossa equipa
  • Case Studies
  • Saber como
    • Blogue
    • Encontros
    • Webinars
    • Recursos
Carreiras Entrar em contacto
  • Sobre nós
  • Serviços
    • Desenvolvimento de software
      • Desenvolvimento de front-end
      • Desenvolvimento backend
    • Staff Augmentation
      • Programadores Frontend
      • Programadores de back-end
      • Engenheiros de dados
      • Engenheiros de nuvem
      • Engenheiros de GQ
      • Outros
    • Aconselhamento
      • Auditoria e consultoria
  • Valor para
    • CEO
    • CTO
    • Gestor de entregas
  • A nossa equipa
  • Case Studies
  • Saber como
    • Blogue
    • Encontros
    • Webinars
    • Recursos
Carreiras Entrar em contacto
Seta para trás VOLTAR
2022-04-05
Desenvolvimento de software

Aplicando o padrão de caso de uso com Rails

Nicolas Nisoria

Um problema comum ao trabalhar com Rails é decidir onde colocar a lógica das nossas funcionalidades.

A lógica é frequentemente colocada nos controladores, modelos ou, se tivermos sorte, num objeto de serviço. Então, se temos Objectos de Serviço, porque é que precisamos de Casos de Utilização?

Siga-me neste artigo para descobrir os benefícios deste padrão.

Caso de utilização

Definição

Um caso de utilização é uma lista de acções ou etapas de eventos que normalmente definem as interações entre uma função e um sistema para atingir um objetivo.

Vale a pena mencionar que este padrão é aplicado de muitas formas diferentes e tem nomes alternativos. Podemos encontrá-lo como Interactores, Operadores ou Comandos, mas no Rubi comunidade com a qual nos mantemos Caso de utilização. Cada implementação é diferente, mas com o mesmo objetivo: servir o caso de utilização do sistema por um utilizador.

Mesmo que na nossa projeto não estamos a definir os requisitos utilizando Caso de utilizaçãos e UML, este padrão continua a ser útil para estruturar a lógica empresarial de uma forma prática.

Regras

O nosso Casos de utilização deve ser:

  • Agnóstico em relação à estrutura
  • Base de dados agnóstica
  • Responsável apenas por uma coisa (definir os passos para atingir o objetivo do utilizador)

Benefícios

  • Legibilidade: Fácil de ler e compreender, uma vez que as etapas estão claramente definidas.
  • Desacoplamento: Deslocar a lógica dos Controladores e Modelos e criar um novo nível de abstração.
  • Visibilidade: A base de código revela as funcionalidades disponíveis no sistema.

Para a prática

Vejamos o exemplo de um utilizador que pretende comprar algo no nosso sistema.

módulo UseCases
  módulo Comprador
    classe Compra
      def initialize(comprador:, carrinho:)
        @comprador = comprador
        @carrinho = carrinho
      fim
      def call
        return unless check_stock
        return unless create_purchase
notificar end
privado
      attr_reader :comprador, :carrinho
      def check_stock
        Services::CheckStock.call(carrinho: carrinho)
fim
      def criar_compra
        Services::CreatePurchase.call(buyer: buyer, cart: cart).call
      end
      def notify

         Services::NotifyBuyer.call(buyer: buyer)
       end
     end
   end
 fim

Como pode ver neste código exemplo, criámos um novo Caso de utilização chamado Purchase. Definimos apenas um método público chamada. Dentro do método call, encontramos passos bastante básicos para efetuar uma compra, e todos os passos são definidos como métodos privados. Cada passo está a chamar um Objeto de Serviço, desta forma o nosso Caso de utilização está apenas a definir os passos para efetuar uma compra e não a lógica em si. Isto dá nós uma imagem clara do que pode ser feito no nosso sistema (efetuar uma compra) e os passos para o conseguir.

Agora estamos prontos para chamar o nosso primeiro Caso de utilização de um controlador.

classe Controlador
  def purchase
    UseCases::Buyer::Purchase.new(
      comprador: purchase_params[:buyer],
      carrinho: purchase_params[:carrinho]
    ).call

    ...
  fim

  ...
fim

Nesta perspetiva, o Caso de utilização é muito parecido com um Objeto de Serviço, mas o seu objetivo é diferente. Um Objeto de Serviço realiza uma tarefa de baixo nível e interage com diferentes partes do sistema, como a Base de Dados, enquanto o Caso de utilização cria uma nova abstração de alto nível e define as etapas lógicas.

Melhorias

O nosso primeiro Caso de utilização funciona mas podia ser melhor. Como é que o podemos melhorar? Vamos utilizar o seco gemas. Neste caso, vamos utilizar transação seca.

Primeiro, vamos definir a nossa classe base.

classe UseCase
  include Dry::Transaction

  class << self
    def call(**args)
      new.call(**args)
    fim
  fim
fim

Isto ajudar-nos-á a passar atributos para a transação UseCase e a utilizá-los. Em seguida, estamos prontos para redefinir o nosso Caso de Utilização de Compra.

módulo UseCases
  módulo Comprador
    classe Compra
      def initialize(comprador:, carrinho:)
        @comprador = comprador
        @carrinho = carrinho
      fim

      def call
        return unless check_stock
        return unless create_purchase
        notificar
      fim

      privado

      attr_reader :comprador, :carrinho

      def check_stock
        Serviços::CheckStock.call(carrinho: carrinho)
      fim

      def create_purchase
        Services::CreatePurchase.call(buyer: buyer, cart: cart).call
      fim

      def notify
        Services::NotifyBuyer.call(buyer: buyer)
      end
    end
   end
 fim

Com as novas alterações, podemos ver claramente como as nossas etapas são definidas e podemos gerir o resultado de cada etapa com Success() e Failure().

Estamos prontos para chamar o nosso novo caso de utilização no controlador e preparar a nossa resposta em função do resultado final.

classe Controlador
  def purchase
    UseCases::Buyer::Purchase.new.call(
      comprador: purchase_params[:buyer],
      carrinho: purchase_params[:carrinho]
    ) do |result|
      result.success do
        ...
      fim
      result.failure do
        ...
      end
    fim

    ...
  fim

  ...
fim

Este exemplo poderia ser melhorado ainda mais com validações, mas é suficiente para mostrar o poder deste padrão.

Conclusões

Sejamos honestos, o Padrão de caso de utilização é bastante simples e parece-se muito com um Objeto de Serviço, mas este nível de abstração pode fazer uma grande mudança na sua aplicação.

Imagine que um novo programador se junta ao projeto e abre a pasta use_cases, como primeira impressão terá uma lista de todas as funcionalidades disponíveis no sistema e, depois de abrir um caso de utilização, verá todos os passos necessários para essa funcionalidade sem se aprofundar na lógica. Esta sensação de ordem e controlo é a principal vantagem deste padrão.

Leve isto na sua caixa de ferramentas e talvez no futuro lhe dê uma boa utilização.

Artigos relacionados

Desenvolvimento de software

Ruby on Rails modularização com Packwerk Episódio I

Os seres humanos têm dificuldade em ver o panorama geral de um problema sem dedicar muito tempo e esforço. Isto acontece especialmente quando se trabalha com aplicações grandes e complexas....

Nicolas Nisoria
Desenvolvimento de software

Ruby on Rails modularização com Packwerk Episode II

No segundo episódio da nossa modularização Ruby on Rails com Packwerk, vamos analisar de perto o conceito de aplicação como um pacote.

Nicolas Nisoria
Desenvolvimento de software

Carris e outros meios de transporte

Rails é um framework compatível com Rack focado no desenvolvimento rápido de aplicações. Infelizmente, a abordagem "tudo fora da caixa" e o comportamento cego do Rails-way muitas vezes fazem com que o código da aplicação perca qualidade,...

The Codest
Krzysztof Buszewicz Sénior Software Engineer

Subscreva a nossa base de conhecimentos e mantenha-se atualizado sobre os conhecimentos do sector das TI.

    Sobre nós

    The Codest - Empresa internacional de desenvolvimento de software com centros tecnológicos na Polónia.

    Reino Unido - Sede

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

    Polónia - Pólos tecnológicos locais

    • Parque de escritórios Fabryczna, Aleja
      Pokoju 18, 31-564 Cracóvia
    • Embaixada do Cérebro, Konstruktorska
      11, 02-673 Varsóvia, Polónia

      The Codest

    • Início
    • Sobre nós
    • Serviços
    • Case Studies
    • Saber como
    • Carreiras
    • Dicionário

      Serviços

    • Aconselhamento
    • Desenvolvimento de software
    • Desenvolvimento backend
    • Desenvolvimento de front-end
    • Staff Augmentation
    • Programadores de back-end
    • Engenheiros de nuvem
    • Engenheiros de dados
    • Outros
    • Engenheiros de GQ

      Recursos

    • Factos e mitos sobre a cooperação com um parceiro externo de desenvolvimento de software
    • Dos EUA para a Europa: Porque é que as empresas americanas decidem mudar-se para a Europa?
    • Comparação dos centros de desenvolvimento da Tech Offshore: Tech Offshore Europa (Polónia), ASEAN (Filipinas), Eurásia (Turquia)
    • Quais são os principais desafios dos CTOs e dos CIOs?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Direitos de autor © 2026 por The Codest. Todos os direitos reservados.

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