Ruby on Rails modulariseerimine koos Packwerki I episoodiga
Inimestel on raske näha probleemi suurt pilti, ilma et nad pühendaksid sellele palju aega ja vaeva. See juhtub eriti suurte ja keeruliste rakendustega töötades.....
Railsiga töötades on levinud probleemiks otsustada, kuhu paigutada meie funktsioonide loogika.
Loogika paigutatakse sageli kontrolleritesse, mudelitesse või kui meil on õnne, siis teenusobjektidesse. Kui meil on olemas Service Objects, siis milleks meil on vaja Use Cases?
Jälgi mind selles artiklis, et avastada selle mustri eelised.
Kasutusjuhtum on tegevuste või sündmuste sammude loetelu, mis tavaliselt määratleb rolli ja süsteemi vahelist suhtlust eesmärgi saavutamiseks.
Väärib märkimist, et seda mustrit rakendatakse mitmel erineval viisil ja sellel on alternatiivseid nimetusi. Me võime seda leida kui Interaktorid, Operaatorid või Käsklused, kuid selles Ruby kogukond, kellega me koos püsime Kasutusjuhtum. Iga rakendamine on erinev, kuid selle eesmärk on sama: süsteemi kasutajakohane kasutamine.
Isegi kui meie projekt me ei määratle nõudeid, kasutades Kasutusjuhtums ja UMLi puhul on see muster endiselt kasulik äriloogika struktureerimiseks praktilisel viisil.
Meie Kasutusjuhtumid peab olema:
Võtame näiteks kasutaja, kes soovib meie süsteemis midagi osta.
moodul UseCases
moodul Ostja
klass Ostmine
def initialize(buyer:, cart:)
@buyer = ostja
@cart = cart
end
def call
return unless check_stock
return unless create_purchase
notify end
private
attr_reader :buyer, :cart
def check_stock
Services::CheckStock.call(cart: cart)
end
def create_purchase
Services::CreatePurchase.call(buyer: buyer, cart: cart).call
end
def notify
Services::NotifyBuyer.call(buyer: buyer)
end
end
end
end
Nagu te võite näha selles kood näiteks lõime uue Kasutusjuhtum nimega Ostmine. Me defineerisime ainult ühe avaliku meetodi helista. Kutsemeetodi sees leiame üsna põhilised sammud ostu sooritamiseks ja kõik sammud on määratletud privaatsete meetoditena. Iga samm kutsub Service Objecti, nii et meie Kasutusjuhtum määratleb ainult ostu sooritamise sammud, mitte aga loogika ise. See annab meile selge pildi sellest, mida meie süsteemis saab teha (ostu sooritada) ja millised on selle saavutamiseks vajalikud sammud.
Nüüd oleme valmis helistama oma esimesele Kasutusjuhtum kontrollerist.
klass Controller
def purchase
UseCases::Buyer::Purchase.new(
buyer: purchase_params[:buyer],
cart: purchase_params[:cart]
).call
...
end
...
end
Sellest vaatenurgast vaadatuna on Kasutusjuhtum näeb välja nagu Service Object, kuid selle eesmärk on erinev. Service Object täidab madalatasemelist ülesannet ja suhtleb süsteemi erinevate osadega, nagu andmebaas, samas kui Kasutusjuhtum loob uus kõrgetasemeline abstraktsioon ja määratleb loogilised sammud.
Meie esimene Kasutusjuhtum töötab, kuid võiks olla parem. Kuidas saaksime seda parandada? Kasutame ära kuiv kalliskivid. Sel juhul kasutame kuivtoiming.
Kõigepealt defineerime oma baasklassi.
klass UseCase
include Dry::Transaction
class << self
def call(**args)
new.call(**args)
end
end
end
See aitab meil UseCase'i tehingule atribuute üle anda ja neid kasutada. Seejärel oleme valmis oma Purchase Use Case'i uuesti defineerima.
moodul UseCases
moodul Ostja
klass Ostmine
def initialize(buyer:, cart:)
@buyer = ostja
@cart = cart
end
def call
return unless check_stock
return unless create_purchase
teavitab
end
private
attr_reader :buyer, :cart
def check_stock
Services::CheckStock.call(cart: cart)
end
def create_purchase
Services::CreatePurchase.call(buyer: buyer, cart: cart).call
end
def notify
Services::NotifyBuyer.call(buyer: buyer)
end
end
end
end
Uute muudatustega näeme selgelt, kuidas meie sammud on määratletud ja saame iga sammu tulemust hallata Success() ja Failure() abil.
Oleme valmis kutsuma meie uut kasutusjuhtumit kontrolleris ja valmistama oma vastuse sõltuvalt lõpptulemusest.
klass Controller
def purchase
UseCases::Buyer::Purchase.new.call(
buyer: purchase_params[:buyer],
cart: purchase_params[:cart]
) do |result|
result.success do
...
end
result.failure do
...
end
end
...
end
...
end
Seda näidet võiks veelgi parandada valideerimisega, kuid sellest piisab, et näidata selle mustri võimsust.
Olgem siinkohal ausad, et Kasutusjuhtumi muster on üsna lihtne ja näeb välja nagu Service Object, kuid see abstraktsioonitase võib teie rakenduses suuri muutusi tuua.
Kujutage ette, et uus arendaja liitub projektiga ja avab kausta use_cases, esimese muljena näeb ta nimekirja kõigist süsteemis olemasolevatest funktsioonidest ja pärast ühe Use Case'i avamist näeb ta kõiki vajalikke samme selle funktsiooni jaoks, ilma et ta läheks sügavale loogikasse. See korrastatuse ja kontrolli tunne on selle mustri peamine eelis.
Võtke see oma tööriistakasti ja võib-olla saate seda tulevikus hästi kasutada.