window.pipedriveLeadboosterConfig = { base: leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster on juba olemas') } 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 }) }, } } })() Koodi optimeerimine päringuobjektide abil - The Codest
The Codest
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Tööstusharud
    • Fintech & pangandus
    • E-commerce
    • Adtech
    • Healthtech
    • Tootmine
    • Logistika
    • Autotööstus
    • IOT
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
  • Meie kohta
  • Teenused
    • Tarkvaraarendus
      • Frontend arendus
      • Backend arendus
    • Staff Augmentation
      • Frontend arendajad
      • Backend arendajad
      • Andmeinsenerid
      • Pilveinsenerid
      • QA insenerid
      • Muud
    • See nõuandev
      • Audit ja nõustamine
  • Väärtus
    • CEO
    • CTO
    • Tarnejuht
  • Meie meeskond
  • Case Studies
  • Tea kuidas
    • Blogi
    • Kohtumised
    • Veebiseminarid
    • Ressursid
Karjäärivõimalused Võtke ühendust
Tagasi nool TAGASI
2019-03-08
Tarkvaraarendus

Koodi optimeerimine päringuobjektide abil

The Codest

Tomasz Szkaradek

Arendusarhitekt

On üsna tõenäoline, et olete tööl kokku puutunud ülekoormatud mudelite ja tohutu hulga kõnedega kontrollerites üsna palju kordi. Lähtudes teadmistest Railsi keskkonnas, pakun selles artiklis välja lihtsa lahenduse sellele probleemile.

Väga oluline aspekt rails'i rakenduses on vähendada üleliigsete sõltuvuste arvu, mistõttu kogu Rails'i keskkond on viimasel ajal propageerinud teenuseobjektide lähenemist ja PORO (Pure Old Ruby Object) meetodi kasutamist. Kirjelduse sellise lahenduse kasutamise kohta leiate siin. Selles artiklis lahendame kontseptsiooni samm-sammult ja kohandame seda probleemile.

Probleem

Hüpoteetilises rakenduses on tegemist keerulise tehingusüsteemiga. Meie mudelil, mis esindab iga tehingut, on hulk ulatusi, mis aitavad saada andmeid. See on suur töö lihtsustamine, kuna see on leitav ühest kohast. See ei kesta aga kaua. Rakenduse arendamisel on projekt muutub üha keerulisemaks. Skeemidel ei ole enam lihtsaid "kus" viiteid, meil puuduvad andmed ja hakkame laadima seoseid. Mõne aja pärast meenutab see keerulist peeglisüsteemi. Ja mis veel hullem, me ei oska teha mitmerealist lambda't!

Allpool leiate juba laiendatud rakendusmudeli. Maksesüsteemi tehingud on salvestatud. Nagu näete alljärgnevas näites:

class Transaction  { where(visible: true) }

  scope(:active, lambda do
    joins(<<-SQL
      LEFT OUTER JOIN source ON transactions.source_id = source.id
      AND source.accepted_at IS NOT NULL
    SQL
  end)
end

Mudel on üks asi, kuid kui meie projekti ulatus kasvab, hakkavad ka kontrollerid paisuma. Vaatame alljärgnevat näidet:

class TransactionsController < ApplicationController
  def index
    @transactions = Transaction.for_publishers
                                   .active
                                   .visible
                                   .joins("LEFT JOIN withdrawal_items ON withdrawal_items.transaction_id = transactions.id")
                                   .joins("LEFT JOIN taganemised ON taganemised.id = taganemised_tooted.taganemiste_id OR
 (withdrawals.id = source.resource_id AND source.resource_type = 'Withdrawal')")
                                   .order(:created_at)
                                   .page(params[:page])
                                   .per(params[:page])
    @transactions = apply_filters(@transactions)
  end
end

Siin näeme mitmeid ridu aheldatud meetodeid koos täiendavate ühendustega, mida me ei taha paljudes kohtades teostada, vaid ainult selles konkreetses kohas. Lisatud andmeid kasutab hiljem meetod apply_filters, mis lisab GET-parameetrite põhjal sobiva andmete filtreerimise. Loomulikult saame mõned neist viidetest üle viia scope'ile, kuid kas see ei ole mitte see probleem, mida me tegelikult püüame lahendada?

Lahendus

Kuna me juba teame, et meil on probleem, peame selle lahendama. Sissejuhatuses toodud viite põhjal kasutame siinkohal PORO lähenemist. Täpselt sellisel juhul nimetatakse seda lähenemisviisi päringuobjektiks, mis on teenuseobjektide kontseptsiooni edasiarendus.

Loome uue kataloogi nimega "services", mis asub meie projekti rakenduste kataloogis. Seal loome klassi nimega TransactionsQuery.

klass TransactionsQuery
end

Järgmise sammuna peame looma initsialiseerija, kus luuakse meie objektile vaikimisi kutsetee

klass TransactionsQuery
  def initialize(scope = Transaction.all)
    @scope = scope
  end
end

Tänu sellele saame me aktiivsest registrist kanda suhte üle meie rajatisse. Nüüd saame kanda kõik meie ulatused üle klassi, mida on vaja ainult esitatud kontrolleris.

klass TransactionsQuery
  def initialize(scope = Transaction.all)
    @scope = scope
  end

  private

  def active(scope)
    scope.joins(<<-SQL
      LEFT OUTER JOIN source ON transactions.source_id = source.id
      AND source.accepted_at IS NOT NULL
    SQL
  end

  def visible(scope)
    scope.where(visible: true)
  end

  def for_publishers(scope)
    scope.select("transactions.*")
         .joins(:account)
         .where("accounts.owner_type = 'Publisher'")
         .joins("JOIN publishers ON owner_id = publishers.id")
  end
end

Meil jääb endiselt puudu kõige olulisem osa, st andmete kogumine ühte stringi ja liidese avalikustamine. Meetod, kus me kõik kokku kleebime, saab nimeks "call".

Tõeliselt oluline on see, et me kasutame seal @scope instantsmuutujat, kus asub meie kõne ulatus.

klass TransactionsQuery
  ...
  def call
    visible(@scope)
        .then(&method(:active))
        .then(&method(:for_publishers))
        .order(:created_at)
  end

  private
  ...
end

Kogu klass esitleb end järgmiselt:

klass TransactionsQuery
  def initialize(scope = Transaction.all)
    @scope = scope
  end

  def call
    visible(@scope)
        .then(&method(:active))
        .then(&method(:for_publishers))
        .order(:created_at)
  end

  private

  def active(scope)
    scope.joins(<<-SQL
      LEFT OUTER JOIN source ON transactions.source_id = source.id
      AND source.accepted_at IS NOT NULL
    SQL
  end

  def visible(scope)
    scope.where(visible: true)
  end

  def for_publishers(scope)
    scope.select("transactions.*")
         .joins(:account)
         .where("accounts.owner_type = 'Publisher'")
         .joins("JOIN publishers ON owner_id = publishers.id")
  end
end

Pärast meie puhastamist näeb mudel kindlasti kergem välja. Seal keskendume ainult andmete valideerimisele ja teiste mudelite vahelistele seostele.

class Transaction < ActiveRecord::Base
  belongs_to :account
  has_one :withdrawal_item
end

Kontroller on juba rakendanud meie lahenduse; me oleme kõik täiendavad päringud viinud eraldi klassi. Kuid kutsed, meil ei olnud mudelis, jäävad lahendamata probleemiks. Pärast mõningaid muudatusi näeb meie indeksitegevus välja selline:

class TransactionsController < ApplicationController
  def index
    @transactions = TransactionsQuery.new
                                     .call
                                     .joins("LEFT JOIN withdrawal_items ON withdrawal_items.accounting_event_id = transactions.id")
                                     .joins("LEFT JOIN taganemised ON taganemised.id = taganemised_tooted.taganemiste_id OR
 (withdrawals.id = source.resource_id AND source.resource_type = 'Withdrawal')")
                                     .order(:created_at)
                                     .page(params[:page])
                                     .per(params[:page])
    @transactions = apply_filters(@transactions)
  end
end

Lahendus

Heade tavade ja konventsioonide rakendamisel võib olla hea mõte asendada kõik antud probleemi sarnased esinemiskohad. Seetõttu liigutame SQL-küsitluse indeksitegevusest eraldi küsitlusobjekti. Nimetame seda TransactionsFilterableQuery klass. Stiil, milles me klassi ette valmistame, on sarnane sellega, mida esitletakse aastal TransactionsQuery. Osana kood muutuste puhul smugeldatakse suuremate SQL päringute intuitiivsemat salvestust, kasutades mitmerealisi tähemärgijada, mida nimetatakse heredoc. Saadaval oleva lahenduse leiad allpool:

klass TransactionsFilterableQuery
  def initialize(scope = Transaction.all)
    @scope = scope
  end

  def call
    withdrawal(@scope).then(&method(:withdrawal_items))
  end

  private

  def withdrawal(scope)
    scope.joins(<<-SQL
      LEFT JOIN withdrawals ON withdrawals.id = withdrawal_items.withdrawal_id OR
      (withdrawals.id = source.resource_id AND source.resource_type = 'Withdrawal')
    SQL
  end

  def withdrawal_items(scope)
    scope.joins(<<-SQL
      LEFT JOIN withdrawal_items ON withdrawal_items.accounting_event_id = transactions.id
    SQL
  end
end

Kontrolleri muudatuste korral vähendame ridade massi, lisades päringuobjekti. Oluline on, et me eraldame kõik peale lehekülgede koostamise eest vastutava osa.

class TransactionsController < ApplicationController
  def index
    @transactions = TransactionsQuery.new.call.then do |scope|
      TransactionsFilterableQuery.new(scope).call
    end.page(params[:page]).per(params[:page])

    @transactions = apply_filters(@transactions)
  end
end

Kokkuvõte

Päringu objekt muudab palju lähenemist SQL päringute kirjutamisele. ActiveRecordis on väga lihtne paigutada kogu äri- ja andmebaasiloogika mudelisse, kuna kõik on ühes kohas. See töötab üsna hästi väiksemate rakenduste puhul. Kui projekti keerukus suureneb, paigutame loogika teistesse kohtadesse. Sama päringuobjekt võimaldab rühmitada liikmete päringuid konkreetseks probleemiks.

Tänu sellele on meil lihtne võimalus koodi hilisemaks pärimiseks ja tänu pardatüübile saab neid lahendusi kasutada ka teistes mudelites. Selle lahenduse puuduseks on suurem koodimaht ja vastutuse killustatus. Kuid kas me tahame sellise väljakutse vastu võtta või mitte, sõltub meist endist ja sellest, kui väga meid rasvased mudelid häirivad.

Seotud artiklid

Tarkvaraarendus

Tulevikukindlate veebirakenduste loomine: The Codest ekspertide meeskonna ülevaade

Avastage, kuidas The Codest paistab skaleeritavate, interaktiivsete veebirakenduste loomisel silma tipptehnoloogiatega, mis pakuvad sujuvat kasutajakogemust kõigil platvormidel. Saate teada, kuidas meie eksperditeadmised aitavad kaasa digitaalsele ümberkujundamisele ja äritegevusele...

THECODEST
Tarkvaraarendus

Top 10 Lätis asuvat tarkvaraarendusettevõtet

Tutvu Läti parimate tarkvaraarendusettevõtete ja nende innovaatiliste lahendustega meie viimases artiklis. Avastage, kuidas need tehnoloogiajuhid saavad aidata teie äri edendada.

thecodest
Enterprise & Scaleups lahendused

Java tarkvaraarenduse põhitõed: A Guide to Outsourcing Successfully

Tutvuge selle olulise juhendiga, kuidas edukalt outsourcing Java tarkvara arendada, et suurendada tõhusust, pääseda ligi eksperditeadmistele ja edendada projekti edu The Codest abil.

thecodest
Tarkvaraarendus

Ülim juhend Poola allhanke kohta

outsourcing kasv Poolas on tingitud majanduslikust, hariduslikust ja tehnoloogilisest arengust, mis soodustab IT kasvu ja ettevõtlussõbralikku kliimat.

TheCodest
Enterprise & Scaleups lahendused

Täielik juhend IT-auditi vahendite ja tehnikate kohta

IT-auditid tagavad turvalised, tõhusad ja nõuetele vastavad süsteemid. Lisateavet nende tähtsuse kohta leiate kogu artiklist.

The Codest
Jakub Jakubowicz CTO & kaasasutajad

Tellige meie teadmistebaas ja jääge kursis IT-sektori eksperditeadmistega.

    Meie kohta

    The Codest - rahvusvaheline tarkvaraarendusettevõte, mille tehnoloogiakeskused asuvad Poolas.

    Ühendkuningriik - peakorter

    • Büroo 303B, 182-184 High Street North E6 2JA
      London, Inglismaa

    Poola - kohalikud tehnoloogiakeskused

    • Fabryczna büroopark, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varssavi, Poola

      The Codest

    • Kodu
    • Meie kohta
    • Teenused
    • Case Studies
    • Tea kuidas
    • Karjäärivõimalused
    • Sõnastik

      Teenused

    • See nõuandev
    • Tarkvaraarendus
    • Backend arendus
    • Frontend arendus
    • Staff Augmentation
    • Backend arendajad
    • Pilveinsenerid
    • Andmeinsenerid
    • Muud
    • QA insenerid

      Ressursid

    • Faktid ja müüdid koostööst välise tarkvaraarenduspartneriga
    • USAst Euroopasse: Miks otsustavad Ameerika idufirmad Euroopasse ümber asuda?
    • Tech Offshore arenduskeskuste võrdlus: Euroopa (Poola), ASEAN (Filipiinid), Euraasia (Türgi).
    • Millised on CTO ja CIOde peamised väljakutsed?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. Kõik õigused kaitstud.

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