Codest
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Toimialat
    • Fintech & pankkitoiminta
    • E-commerce
    • Adtech
    • Terveysteknologia
    • Valmistus
    • Logistiikka
    • Autoteollisuus
    • IOT
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
  • Tietoa meistä
  • Palvelut
    • Ohjelmistokehitys
      • Frontend-kehitys
      • Backend-kehitys
    • Staff Augmentation
      • Frontend-kehittäjät
      • Backend-kehittäjät
      • Tietoinsinöörit
      • Pilvi-insinöörit
      • QA insinöörit
      • Muut
    • Se neuvoa-antava
      • Tilintarkastus & konsultointi
  • Arvo
    • TOIMITUSJOHTAJA
    • CTO
    • Toimituspäällikkö
  • Tiimimme
  • Tapaustutkimukset
  • Tiedä miten
    • Blogi
    • Tapaamiset
    • Webinaarit
    • Resurssit
Työurat Ota yhteyttä
Takaisin nuoli PALAA TAAKSE
2022-01-13
Ohjelmistokehitys

Polymorfismi Rubyssä ja GraphQL:ssä

Lukasz Brzeszcz

Tässä artikkelissa esittelen polymorfismin käyttöä GraphQL:ssä. Ennen kuin aloitan, on kuitenkin syytä palauttaa mieleen, mitä polymorfismi ja GraphQL ovat.

Polymorfismi

Polymorfismi on keskeinen osa oliosuuntautunut ohjelmointi. Yksinkertaistaen se perustuu siihen, että eri luokkien objekteilla on pääsy samaan rajapintaan, mikä tarkoittaa, että voimme odottaa jokaiselta niistä samaa toiminnallisuutta, mutta sitä ei välttämättä ole toteutettu samalla tavalla. Osoitteessa Ruby-kehittäjät voi saada polymorfismi kolmella tavalla:

Perinnöllisyys

Perinnöllisyys koostuu vanhemman luokan ja lapsiluokkien luomisesta (eli vanhemman luokan periyttämisestä). Alaluokat saavat vanhemman luokan toiminnallisuuden ja mahdollistavat myös toiminnallisuuden muuttamisen ja lisäämisen.

Esimerkki:

luokka Document
  attr_reader :name
end

class PDFDocument < Dokumentti
  def extension
    :pdf
  end
end

class ODTDocument < Document
  def extension
    :odt
  end
end

Moduulit

Moduulit Ruby on monia käyttötarkoituksia. Yksi niistä on yhdistelmät (lue lisää yhdistelmistä luvussa Lopullinen hajoaminen: Ruby vs. Python). Rubyn sekoituksia voidaan käyttää samalla tavalla kuin rajapintoja muissa ohjelmointikielissä (esim. Java), voit esimerkiksi määritellä niissä metodeja, jotka ovat yhteisiä objekteille, jotka sisältävät tietyn yhdistelmän. On hyvä käytäntö sisällyttää moduuleihin vain lukemiseen tarkoitettuja metodeja, eli metodeja, jotka eivät muuta tämän objektin tilaa.

Esimerkki:

moduuli Verotettava
  def tax

     hinta * 0.23
  end
end

luokka Auto
  include Taxable
 attr_reader :price
end

luokka Book
  include Taxable

 attr_reader :price
end

Ankka kirjoittaminen

Tämä on yksi dynaamisesti tyypiteltyjen kielten tärkeimmistä ominaisuuksista. Nimi tulee kuuluisasta testistä: jos se näyttää ankalta, ui kuin ankka ja kukkoilee kuin ankka, se on todennäköisesti ankka. The ohjelmoija ei tarvitse olla kiinnostunut siitä, mihin luokkaan kyseinen objekti kuuluu. Tärkeää ovat metodit, joita voidaan kutsua tällä objektilla.

Käyttämällä yllä olevassa esimerkissä määriteltyjä luokkia:

luokka Auto
  attr_reader :price

 def initialize(hinta)
    @price = hinta
   end
end

luokka Book
  attr_reader :price

 def initialize(hinta)
    @price = hinta
  end
end

car = Car.new(20.0)
book = Book.new(10.0)

[auto, kirja].map(&:hinta)

GrapQL

GraphQL on suhteellisen uusi kyselykieli sovellusrajapintoja varten. Sen etuihin kuuluu se, että sen syntaksi on hyvin yksinkertainen, ja lisäksi asiakas päättää itse, mitä hän haluaa saada, sillä jokainen asiakas saa juuri sen, mitä hän haluaa, eikä mitään muuta.

Esimerkkikysely osoitteessa GraphQL:

{
  allUsers {
     users {
        id
        login
        email

       }
     }
   }

Esimerkkivastaus:

{
  "allUsers": {
    "users": [
     {
        "id": 1,
        "login": "user1",
        "email": "[email protected]"
      },
      {
        "id": 2,
        "login": "user2",
        "email": "[email protected]"
      },
    ]
  }
}

Tämä on luultavasti kaikki, mitä meidän tarvitsee tällä hetkellä tietää. Mennään siis asiaan.

Ongelman esittely

Jotta ymmärtäisimme parhaiten ongelman ja sen ratkaisun, luodaan esimerkki. Olisi hyvä, jos esimerkki olisi sekä omaperäinen että melko maanläheinen. Sellainen, jonka jokainen meistä voi kohdata joskus. Miten olisi... eläimet? Kyllä! Loistava idea!

ruby ja grapql polymorfismi - eläimet

Oletetaan, että meillä on backend-sovellus, joka on kirjoitettu kielellä Ruby on Rails. Se on jo mukautettu edellä mainittua järjestelmää varten. Oletetaan myös, että meillä on jo GraphQL konfiguroitu. Haluamme antaa asiakkaalle mahdollisuuden tehdä kysely seuraavan rakenteen mukaisesti:

{
 allZoos : {
    zoo: {
      name
      kaupunki
      eläimet: {
        ...
      }
    }
  }
}

Mitä pitäisi laittaa kolmen pisteen tilalle, jotta saataisiin puuttuvat tiedot - se selviää myöhemmin.

Täytäntöönpano

Seuraavassa esittelen tavoitteen saavuttamiseen tarvittavat vaiheet.

Kyselyn lisääminen QueryType-luokkaan

Ensin on määriteltävä, mitä kysely allZoos tarkalleen ottaen tarkoittaa. Tätä varten meidän on käytävä tiedostossa nimeltäapp/graphql/types/query_type.rb ja määrittele kysely:

   moduuli Tyypit
      class QueryType < Types::BaseObject
       kenttä :all_zoos, [Types::ZooType], null: false

       def all_zoos
          Zoo.all
       end
    end
 end

Kysely on jo määritelty. Nyt on aika määritellä paluutyypit.

Tyyppien määritelmä

Ensimmäinen tarvittava tyyppi on ZooType. Määritellään se tiedostossa app/graphql/types/ zoo_type.rb:

moduuli Tyypit
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalType], null: false
  end
end

Nyt on aika määritellä tyyppi AnimalType:

moduuli Tyypit
  class AnimalType < Types::BaseUnion
   possible_types ElephantType, CatType, DogType

     def self.resolve_type(obj, ctx)
       if obj.is_a?(Elefantti)
          ElephantType
       elsif obj.is_a?(Cat)
         CatType
       elsif obj.is_a?(Dog)
        DogType
      end
    end
  end
end

Mitä näemme koodi edellä?

  1. AnimalType periytyy nimestä Types::BaseUnion.
  2. Meidän on lueteltava kaikki tyypit, jotka voivat muodostaa tietyn liiton.
    3.Me ohitamme funktion self.resolve_object(obj, ctx),jonka on palautettava tietyn objektin tyyppi.

Seuraavaksi määritellään eläintyypit. Tiedämme kuitenkin, että jotkin kentät ovat kaikille eläimille yhteisiä. Sisällytetään ne tyyppiin AnimalInterface:

moduuli Tyypit
  moduuli AnimalInterface
    include Types::BaseInterface

    field :name, String, null: false
    field :age, Kokonaisluku, null: false
  end
end

Kun tämä rajapinta on valmis, voimme määritellä tiettyjen eläinten tyypit:

moduuli Tyypit
  class ElephantType < Types::BaseObject
    implements Types::AnimalInterface

    kenttä :trunk_length, Float, null: false
  end
end

moduuli Types
  class CatType < Types::BaseObject
   implements Types::AnimalInterface

   field :hair_type, String, null: false
  end
end

moduuli Tyypit
  class DogType < Types::BaseObject
    implements Types::AnimalInterface

     field :breed, String, null: false
  end
end

Juuri noin! Valmiina! Vielä yksi kysymys: miten voimme käyttää sitä, mitä olemme tehneet asiakkaan puolella?

Kyselyn rakentaminen

{
 allZoos : {
   zoo: {
      name
      kaupunki
      eläimet: {
        __typename

        ... on ElephantType {
          name
          age
          trunkLength
        }

         ... on CatType {
          name
          age
          hairType
         }
         ... on DogType {
          name
          age
          rotu
         }
       }
     }
   }
 }

Voimme käyttää tässä ylimääräistä __typename-kenttää, joka palauttaa tietyn elementin tarkan tyypin (esim. CatType). Miltä esimerkkivastaus näyttää?

{
  "allZoos": [

   {
      "name": "Natura Artis Magistra",
      "city": "Amsterdam",
      "animals": [
        {
          "__tyyppinimi": "ElephantType"
          "name": "Franco",
          "age": 28,
          "trunkLength": 9.27
         },
         {
         "__typename": "DogType"
         "name": "Jack",
         "age": 9,
         "rotu": "Jack Russell Terrier"
        },
      ]
    }
  ]
} 

Analyysi

Yksi tämän lähestymistavan haittapuoli on ilmeinen. Kyselyssä meidän on syötettävä nimi ja ikä jokaiseen tyyppiin, vaikka tiedämme, että kaikilla eläimillä on nämä kentät. Tämä ei ole häiritsevää, kun kokoelma sisältää täysin erilaisia objekteja. Tässä tapauksessa eläimillä on kuitenkin lähes kaikki samat kentät. Voidaanko tätä jotenkin parantaa?

Totta kai! Teemme ensimmäisen muutoksen tiedostoon app/graphql/types/zoo_type.rb:

moduuli Tyypit
  class ZooType < Types::BaseObject
    field :name, String, null: false
    field :city, String, null: false
    field :animals, [Types::AnimalInterface], null: false
  end
end

Emme enää tarvitse aiemmin määrittelemäämme liittoa. Muutamme Types::AnimalType osoitteeseen Types::AnimalInterface.

Seuraava askel on lisätä funktio, joka palauttaa tyypin, joka on peräisin Tyypit :: AnimalInterface ja lisää myös luettelo orphan_types-tyypeistä, eli tyypeistä, joita ei koskaan käytetä suoraan:

moduuli Tyypit
  moduuli AnimalInterface
    include Types::BaseInterface

   field :name, String, null: false
   field :age, Kokonaisluku, null: false

   definition_methods do
      def resolve_type(obj, ctx)
        if obj.is_a?(Elephant)
          ElephantType
        elsif obj.is_a?(Cat)
          CatType
        elsif obj.is_a?(Dog)
          DogType
        end
      end
    end
    orphan_types Types::ElephantType, Types::CatType, Types::DogType
  end
end

Tämän yksinkertaisen menettelyn ansiosta kysely on vähemmän monimutkainen:

{
  allZoos : {
   zoo: {
      name
      kaupunki
      eläimet: {
        __typename
        name
        ikä

       ... on ElephantType {
          trunkLength

       }
       ... on CatType {
          hairType

       }
       ... on DogType {
          breed

        }
      }
    }
  }
}

Yhteenveto

GraphQL on todella hyvä ratkaisu. Jos et vielä tiedä sitä, kokeile sitä. Luota minuun, se on sen arvoista. Se tekee loistavaa työtä ratkaistessaan ongelmia, joita esiintyy esimerkiksi REST API:issa. Kuten edellä osoitin, polymorfismi ei ole todellinen este sille. Esittelin kaksi menetelmää sen ratkaisemiseksi.
Muistutus:

  • Jos käytät luetteloa objekteista, joilla on yhteinen pohja tai yhteinen rajapinta - käytä rajapintoja,
  • Jos operoit rakenteeltaan erilaisten objektien luettelolla, käytä eri rajapintaa - käytä unionia

Lue lisää

GraphQL Ruby. Entä suorituskyky?

Kiskot ja muut liikennevälineet

Rails-kehitys TMUX, Vim, Fzf + Ripgrep -ohjelmilla

Aiheeseen liittyvät artikkelit

Ohjelmistokehitys

Tulevaisuuden web-sovellusten rakentaminen: The Codest:n asiantuntijatiimin näkemyksiä

Tutustu siihen, miten The Codest loistaa skaalautuvien, interaktiivisten verkkosovellusten luomisessa huipputeknologian avulla ja tarjoaa saumattomia käyttäjäkokemuksia kaikilla alustoilla. Lue, miten asiantuntemuksemme edistää digitaalista muutosta ja liiketoimintaa...

THECODEST
Ohjelmistokehitys

Top 10 Latviassa toimivaa ohjelmistokehitysyritystä

Tutustu Latvian parhaisiin ohjelmistokehitysyrityksiin ja niiden innovatiivisiin ratkaisuihin uusimmassa artikkelissamme. Tutustu siihen, miten nämä teknologiajohtajat voivat auttaa nostamaan liiketoimintaasi.

thecodest
Yritys- ja skaalausratkaisut

Java-ohjelmistokehityksen perusteet: A Guide to Outsourcing Successfully

Tutustu tähän keskeiseen oppaaseen Java-ohjelmistokehityksen onnistuneesta ulkoistamisesta tehokkuuden parantamiseksi, asiantuntemuksen saamiseksi ja projektin onnistumiseksi The Codestin avulla.

thecodest
Ohjelmistokehitys

Perimmäinen opas ulkoistamiseen Puolassa

Ulkoistamisen lisääntyminen Puolassa johtuu taloudellisesta, koulutuksellisesta ja teknologisesta kehityksestä, joka edistää tietotekniikan kasvua ja yritysystävällistä ilmapiiriä.

TheCodest
Yritys- ja skaalausratkaisut

Täydellinen opas IT-tarkastustyökaluihin ja -tekniikoihin

Tietotekniikan tarkastuksilla varmistetaan turvalliset, tehokkaat ja vaatimustenmukaiset järjestelmät. Lue lisää niiden merkityksestä lukemalla koko artikkeli.

Codest
Jakub Jakubowicz teknologiajohtaja ja toinen perustaja

Tilaa tietopankkimme ja pysy ajan tasalla IT-alan asiantuntemuksesta.

    Tietoa meistä

    The Codest - Kansainvälinen ohjelmistokehitysyritys, jolla on teknologiakeskuksia Puolassa.

    Yhdistynyt kuningaskunta - pääkonttori

    • Toimisto 303B, 182-184 High Street North E6 2JA
      Lontoo, Englanti

    Puola - Paikalliset teknologiakeskukset

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Krakova
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsova, Puola

      Codest

    • Etusivu
    • Tietoa meistä
    • Palvelut
    • Tapaustutkimukset
    • Tiedä miten
    • Työurat
    • Sanakirja

      Palvelut

    • Se neuvoa-antava
    • Ohjelmistokehitys
    • Backend-kehitys
    • Frontend-kehitys
    • Staff Augmentation
    • Backend-kehittäjät
    • Pilvi-insinöörit
    • Tietoinsinöörit
    • Muut
    • QA insinöörit

      Resurssit

    • Faktoja ja myyttejä yhteistyöstä ulkoisen ohjelmistokehityskumppanin kanssa
    • Yhdysvalloista Eurooppaan: Miksi amerikkalaiset startup-yritykset päättävät muuttaa Eurooppaan?
    • Tech Offshore -kehityskeskusten vertailu: Tech Offshore Eurooppa (Puola), ASEAN (Filippiinit), Euraasia (Turkki).
    • Mitkä ovat teknologiajohtajien ja tietohallintojohtajien tärkeimmät haasteet?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Verkkosivuston käyttöehdot

    Tekijänoikeus © 2025 by The Codest. Kaikki oikeudet pidätetään.

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