window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = finestra if (w.LeadBooster) { console.warn('LeadBooster esiste già') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Applicazione dello schema dei casi d'uso con Rails - The Codest
The Codest
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Industrie
    • Fintech e banche
    • E-commerce
    • Adtech
    • Tecnologia della salute
    • Produzione
    • Logistica
    • Automotive
    • IOT
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
Freccia indietro TORNA INDIETRO
2022-04-05
Sviluppo di software

Applicare lo schema dei casi d'uso con Rails

Nicolas Nisoria

Un problema comune quando si lavora con Rails è decidere dove collocare la logica delle nostre funzioni.

La logica è spesso collocata nei controllori, nei modelli o, se siamo fortunati, in un oggetto servizio. Quindi, se abbiamo gli oggetti di servizio, perché abbiamo bisogno dei casi d'uso?

Seguitemi in questo articolo per scoprire i vantaggi di questo modello.

Caso d'uso

Definizione

Un caso d'uso è un elenco di azioni o fasi di eventi che definiscono tipicamente le interazioni tra un ruolo e un sistema per raggiungere un obiettivo.

Vale la pena ricordare che questo schema viene applicato in molti modi diversi e ha nomi alternativi. Possiamo trovarlo come Interattori, Operatori o Comandi, ma nel Rubino comunità a cui ci atteniamo Caso d'uso. Ogni implementazione è diversa, ma con lo stesso scopo: servire il caso d'uso del sistema da parte dell'utente.

Anche se nel nostro progetto non stiamo definendo i requisiti utilizzando Caso d'usoe UML, questo pattern è ancora utile per strutturare la logica aziendale in modo pratico.

Regole

Il nostro Casi d'uso deve essere:

  • Agnostico al framework
  • Agnostico rispetto al database
  • Responsabile di una sola cosa (definire i passi per raggiungere l'obiettivo dell'utente)

Vantaggi

  • Leggibilità: Facile da leggere e da capire, poiché i passaggi sono chiaramente definiti.
  • Disaccoppiamento: Spostare la logica dai controllori e dai modelli e creare un nuovo livello di astrazione.
  • Visibilità: La base di codice rivela le funzionalità disponibili nel sistema.

Nella pratica

Prendiamo l'esempio di un utente che vuole acquistare qualcosa nel nostro sistema.

modulo Casi d'uso
  modulo Acquirente
    classe Acquisto
      def initialize(buyer:, cart:)
        @acquirente = acquirente
        @carrello = carrello
      fine
      def call
        return unless check_stock
        return a meno che create_purchase
notificare fine
privato
      attr_reader :buyer, :cart
      def check_stock
        Services::CheckStock.call(cart: cart)
fine
      def crea_acquisto
        Servizi::CreaAcquisto.call(acquirente: acquirente, carrello: carrello).call
      fine
      def notifica

         Servizi::NotificaAcquirente.call(acquirente: acquirente)
       fine
     fine
   fine
 fine

Come si può vedere in questo codice esempio, abbiamo creato un nuovo Caso d'uso chiamato Acquisto. Abbiamo definito un solo metodo pubblico chiamata. All'interno del metodo call, troviamo i passi fondamentali per effettuare un acquisto e tutti i passi sono definiti come metodi privati. Ogni passo è una chiamata a un oggetto servizio, in questo modo il nostro Caso d'uso sta definendo solo i passaggi per effettuare un acquisto e non la logica stessa. Questo ci dà un quadro chiaro di ciò che può essere fatto nel nostro sistema (effettuare un acquisto) e dei passaggi per ottenerlo.

Ora siamo pronti a chiamare il nostro primo Caso d'uso da un controllore.

classe Controllore
  def acquisto
    UseCases::Buyer::Purchase.new(
      acquirente: purchase_params[:buyer],
      carrello: purchase_params[:cart]
    ).call

    ...
  fine

  ...
fine

Da questo punto di vista, il Caso d'uso assomiglia molto a un Oggetto Servizio, ma lo scopo è diverso. Un oggetto servizio esegue un compito di basso livello e interagisce con diverse parti del sistema, come il database, mentre l'oggetto Il caso d'uso crea una nuova astrazione di alto livello e definisce i passaggi logici.

Miglioramenti

Il nostro primo Caso d'uso funziona ma potrebbe essere migliore. Come possiamo migliorarlo? Utilizziamo il asciutto gemme. In questo caso utilizzeremo transazione a secco.

Per prima cosa definiamo la nostra classe base.

classe UseCase
  includere Dry::Transaction

  classe << self
    def call(**args)
      new.call(**args)
    fine
  fine
fine

Questo ci aiuterà a passare gli attributi alla transazione UseCase e a utilizzarli. Siamo quindi pronti a ridefinire il nostro Caso d'uso Acquisto.

modulo Casi d'uso
  modulo Acquirente
    classe Acquisto
      def initialize(buyer:, cart:)
        @acquirente = acquirente
        @carrello = carrello
      fine

      def call
        return unless check_stock
        ritorno a meno che non si crei un acquisto
        notificare
      fine

      privato

      attr_reader :buyer, :cart

      def check_stock
        Services::CheckStock.call(cart: cart)
      fine

      def crea_acquisto
        Servizi::CreaAcquisto.call(acquirente: acquirente, carrello: carrello).call
      fine

      def notificare
        Servizi::NotificaAcquirente.call(acquirente: acquirente)
      fine
    fine
   fine
 fine

Con le nuove modifiche, possiamo vedere in modo chiaro come vengono definiti i nostri passi e possiamo gestire il risultato di ogni passo con Success() e Failure().

Siamo pronti a richiamare il nostro nuovo caso d'uso nel controllore e a preparare la nostra risposta in base al risultato finale.

classe Controllore
  def acquisto
    UseCases::Buyer::Purchase.new.call(
      acquirente: purchase_params[:buyer],
      carrello: purchase_params[:cart]
    ) do |risultato|
      risultato.successo do
        ...
      fine
      risultato.fallimento fare
        ...
      fine
    fine

    ...
  fine

  ...
fine

Questo esempio potrebbe essere migliorato ancora di più con le convalide, ma è sufficiente per mostrare la potenza di questo modello.

Conclusioni

Siamo onesti: il Modello di caso d'uso è piuttosto semplice e assomiglia molto a un oggetto servizio, ma questo livello di astrazione può cambiare notevolmente l'applicazione.

Immaginate che un nuovo sviluppatore entri nel progetto e apra la cartella use_cases: come prima impressione avrà un elenco di tutte le funzionalità disponibili nel sistema e, dopo aver aperto un Use Case, vedrà tutti i passaggi necessari per quella funzionalità senza addentrarsi nella logica. Questo senso di ordine e controllo è il principale vantaggio di questo modello.

Portatelo nella vostra cassetta degli attrezzi e forse in futuro ne farete buon uso.

Articoli correlati

Sviluppo di software

Modularizzazione della Ruby on Rails con Packwerk Episodio I

Gli esseri umani hanno difficoltà a vedere il quadro generale di un problema senza dedicare molto tempo e sforzi. Questo accade soprattutto quando si lavora con applicazioni grandi e complesse....

Nicolas Nisoria
Sviluppo di software

Ruby on Rails modulare con Packwerk Episode II

Nella seconda puntata della nostra modularizzazione dell'Ruby on Rails con Packwerk esamineremo da vicino il concetto di applicazione come pacchetto.

Nicolas Nisoria
Sviluppo di software

Rotaie e altri mezzi di trasporto

Rails è un framework compatibile con Rack e incentrato sullo sviluppo rapido di applicazioni. Purtroppo, l'approccio "tutto fuori dalla scatola" e il comportamento cieco del Rails-way spesso fanno perdere qualità al codice dell'applicazione,...

The Codest
Krzysztof Buszewicz Senior Software Engineer

Iscrivetevi alla nostra knowledge base e rimanete aggiornati sulle competenze del settore IT.

    Chi siamo

    The Codest - Società internazionale di sviluppo software con centri tecnologici in Polonia.

    Regno Unito - Sede centrale

    • Ufficio 303B, 182-184 High Street North E6 2JA
      Londra, Inghilterra

    Polonia - Poli tecnologici locali

    • Parco uffici Fabryczna, Aleja
      Pokoju 18, 31-564 Cracovia
    • Ambasciata del cervello, Konstruktorska
      11, 02-673 Varsavia, Polonia

      The Codest

    • Casa
    • Chi siamo
    • Servizi
    • Case Studies
    • Sapere come
    • Carriera
    • Dizionario

      Servizi

    • Consulenza
    • Sviluppo di software
    • Sviluppo backend
    • Sviluppo Frontend
    • Staff Augmentation
    • Sviluppatori backend
    • Ingegneri del cloud
    • Ingegneri dei dati
    • Altro
    • Ingegneri QA

      Risorse

    • Fatti e miti sulla collaborazione con un partner esterno per lo sviluppo di software
    • Dagli Stati Uniti all'Europa: Perché le startup americane decidono di trasferirsi in Europa
    • Confronto tra gli hub di sviluppo Tech Offshore: Tech Offshore Europa (Polonia), ASEAN (Filippine), Eurasia (Turchia)
    • Quali sono le principali sfide di CTO e CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Condizioni di utilizzo del sito web

    Copyright © 2025 di The Codest. Tutti i diritti riservati.

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