Monkey Patching dynaamisilla ohjelmointikielillä: JavaScript-esimerkki

Javascript
dynaaminen ohjelmointi
Monkey Patching dynaamisilla ohjelmointikielillä cover image

Johdanto

Tässä artikkelissa tarkastellaan dynaamisten ja staattisten ohjelmointikielten käsitteitä, tärkeimpiä eroja näiden kahden välillä ja sitä, mitä kukin paradigma tarjoaa etujen ja sudenkuoppien suhteen. Tämä tutkimus keskittyy edelleen dynaamisiin ohjelmointikieliin, erityisesti yhteen sen mahdollistamaan olennaiseen malliin: Monkey Patch, tämä malli esitellään JavaScriptin esimerkin avulla.

Dynaamiset vs staattiset ohjelmointikielet

Terminologia

Ymmärtääksemme, mikä on dynaaminen kieli tai staattinen kieli, meidän on ymmärrettävä muutamia tässä yhteydessä yleisesti käytettyjä avaintermejä: Käännösaika, Suoritusaika ja *Tyypin tarkistus *.

Compile ja Runtime ovat kaksi termiä, jotka vastaavat tietokoneohjelman elinkaaren eri vaiheita, alkaen käännösajasta.

Kokoamisaika

Käännösaika on ensimmäinen askel ohjelman elinkaaressa. Kehittäjä kirjoittaa koodia tietyllä ohjelmointikielellä. Useimmiten kone ei pysty ymmärtämään korkean tason kielellä kirjoitettua koodia, joten erillistä kääntäjää käytetään kääntämään se alemman tason välimuotoon, joka on valmis suoritettavaksi.

Kesto

Ajonaika sisältää yleensä kaksi vaihetta: ohjelman lataaminen muistiin varaamalla sen suorittamiseen tarvittavat resurssit ohjeineen, ja sitten ohjelma suoritetaan näiden ohjeiden järjestyksessä.

Seuraava kaavio havainnollistaa tätä prosessia:

Tyypin tarkistus

Tyypintarkistus on sisäänrakennettu ominaisuus lähes kaikissa ohjelmointikielissä. Se on kyky tarkistaa, vastaako tietylle muuttujalle annettu arvo kyseisen muuttujan oikeaa tyyppiä. Jokaisella ohjelmointikielellä on erilainen tapa esittää tietyn tyyppinen arvo muistissa. Nämä erilaiset esitykset mahdollistavat vastaavuuden tarkistamisen arvon tyypin ja sen muuttujan tyypin välillä, jolle yrität määrittää kyseisen arvon.

Nyt kun meillä on korkeatasoinen ymmärrys ohjelman elinkaaresta ja tyypin tarkistuksesta, voimme jatkaa staattisten ohjelmointikielien tutkimista.

Staattiset ohjelmointikielet

Staattiset ohjelmointikielet, joita kutsutaan myös staattisesti kirjoitetuiksi kieliksi, ovat kieliä, jotka käyttävät käännösvaiheessa mainitsemaamme tyyppitarkistusta. Tämä tarkoittaa käytännössä sitä, että muuttuja säilyttää tyyppinsä ilmoituksesta ja sille ei voida antaa muita arvoja kuin sen ilmoitustyypin arvot. Staattiset ohjelmointikielet tarjoavat lisäturvaa käsiteltäessä tyyppejä, mutta ne voivat hidastaa kehitysprosessia tietyissä käyttötapauksissa, kun siitä tulee ankara rajoitus.

Dynaamiset ohjelmointikielet

Dynaamiset ohjelmointikielet sen sijaan käyttävät tyyppitarkistusta suorituksen aikana. Tämä tarkoittaa, että mikä tahansa muuttuja voi sisältää minkä tahansa arvon missä tahansa ohjelman kohdassa. Tästä voi olla hyötyä, koska se tarjoaa kehittäjälle joustavuutta, jota ei ole staattisissa kielissä. Dynaamiset kielet ovat yleensä hitaampia suoritettaessa kuin niiden staattiset kielet, koska ne sisältävät lisävaiheen kunkin muuttujan kirjoituksen selvittämiseksi dynaamisesti.

Monkey Patch

Staattinen vs. dynaaminen kirjoittaminen on ohjelmointikielen perusominaisuus, sillä yhden paradigman käyttäminen toisen päälle voi mahdollistaa joukon erilaisia ​​malleja ja käytäntöjä, jotka voivat parantaa merkittävästi kehityksen laatua ja nopeutta. Se voi myös avata oven monille rajoituksille ja anti-kuvioille, jos suunnittelupäätöksiä tehtäessä ei oteta huomioon huolellisia huomioita.

Erityisesti dynaamisesti kirjoitettujen ohjelmointikielten tiedetään tarjoavan korkeampaa joustavuutta, koska ne eivät rajoita muuttujaa yhteen tyyppiin. Tämä joustavuus tuo mukanaan lisävastuun kehittäjälle ohjelmien käyttöönoton ja virheenkorjauksen yhteydessä varmistaakseen, ettei ennalta arvaamattomia toimintoja tapahdu. Apinalappukuvio tulee tästä filosofiasta.

Monkey Patch viittaa prosessiin, jossa komponentin toimintaa laajennetaan/muutetaan ajon aikana. Kyseinen komponentti voi olla kirjasto, luokka, menetelmä tai jopa moduuli. Ajatus on sama: koodinpätkä on tehty suorittamaan tietty tehtävä, ja apinan paikannuksen tavoitteena on muuttaa tai laajentaa kyseisen koodinpalan käyttäytymistä niin, että se suorittaa uuden tehtävän, kaikki muuttamatta itse koodia .

Tämä on mahdollista dynaamisessa ohjelmointikielessä, koska riippumatta siitä minkä tyyppisestä komponentista olemme tekemisissä, sillä on silti sama objektin rakenne erilaisilla attribuutteilla, attribuuteissa voi olla menetelmiä, jotka voidaan määrittää uudelleen saavuttamaan objektissa uusi käyttäytyminen menemättä sen sisäisiin osiin ja toteutuksen yksityiskohtiin. Tämä on erityisen hyödyllistä kolmannen osapuolen kirjastoissa ja moduuleissa, koska niitä on yleensä vaikea säätää.

Seuraava esimerkki esittelee yleisen käyttötapauksen, joka voi hyötyä apinalapputekniikan käyttämisestä. Javascriptiä käytettiin toteutuksen vuoksi, mutta tämän pitäisi silti koskea kaikkia muita dynaamisia ohjelmointikieliä.

Esimerkki

Ota käyttöön Minimaalinen testauskehys Noden alkuperäisellä HTTP-moduulilla

Yksikkö- ja integrointitestaus voi kuulua Monkey-korjauksen käyttötapauksiin. Ne sisältävät yleensä testitapauksia, jotka kattavat useamman kuin yhden palvelun integrointitestausta varten tai API- ja/tai tietokantariippuvuuksia yksikkötestauksessa. Näissä kahdessa skenaariossa ja ennen kaikkea testauksen tavoitteiden saavuttamiseksi haluaisimme, että testimme ovat riippumattomia näistä ulkoisista resursseista. Tapa saavuttaa tämä on pilkkaamalla. Pilkkaaminen on ulkoisten palvelujen toiminnan simulointia, jotta testi voi keskittyä koodin todelliseen logiikkaan. Apinoiden korjaus voi olla hyödyllinen tässä, koska se voi muokata ulkoisten palveluiden menetelmiä korvaamalla ne paikkamerkkimenetelmillä, joita kutsumme "stubiksi". Nämä menetelmät palauttavat odotetun tuloksen testaustapauksissa, jotta voimme välttää pyyntöjen käynnistämisen tuotantopalveluihin pelkästään testien vuoksi.

Seuraava esimerkki on yksinkertainen Monkey-korjauksen toteutus NodeJ:n alkuperäisessä http-moduulissa. http-moduuli on käyttöliittymä, joka toteuttaa http-protokollamenetelmät NodeJ:ille. Sitä käytetään pääasiassa luomaan barebone http-palvelimia ja kommunikoimaan ulkoisten palveluiden kanssa käyttämällä http-protokollaa.

Alla olevassa esimerkissä meillä on yksinkertainen testaustapaus, jossa kutsumme ulkopuolista palvelua hakemaan käyttäjätunnusluettelon. Varsinaisen palvelun kutsumisen sijaan korjaamme http get -menetelmän, joten se palauttaa vain odotetun tuloksen, joka on joukko satunnaisia ​​käyttäjätunnuksia. Tämä ei ehkä vaikuta kovin tärkeältä, koska haemme vain tietoja, mutta jos otamme käyttöön toisen testitapauksen, joka sisältää jonkinlaisen datan muuttamisen, saatamme vahingossa muuttaa tuotantotietoja suoritettaessa testejä.

Näin voimme toteuttaa toiminnallisuuksiamme ja kirjoittaa jokaiselle toiminnallisuudelle testejä ja samalla varmistaa tuotantopalveluidemme turvallisuuden.

// import the http module
let http = require("http");

// patch the get method of the http module
http.get = async function(url) {
  return {
    data: ["1234", "1235", "1236", "1236"]
  };
}

// example test suite, call new patched get method for testing
test('get array of user ids from users api', async () => {
  const res = await http.get("https://users.api.com/ids");
  const userIds = res.data;
  expect(userIds).toBeDefined();
  expect(userIds.length).toBe(4);
  expect(userIds[0]).toBe("1234");
});

Yllä oleva koodi on yksinkertainen, tuomme http-moduulin, määritämme http.get-menetelmän uudelleen uudella menetelmällä, joka palauttaa vain joukon tunnuslukuja. Nyt kutsumme uutta patched-menetelmää testitapauksen sisällä ja saamme uuden odotetun tuloksen.

~/SphericalTartWorker$ npm test

> nodejs@1.0.0 test
> jest

PASS  ./index.test.js
  ✓ get array of user ids from users api (25 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.977 s, estimated 2 s
Ran all test suites.

Yleisiä sudenkuoppia ja rajoituksia

Ei pitäisi tulla yllätyksenä, että apinoiden korjauksella on omat puutteensa ja rajoituksensa. Solmumoduulijärjestelmän moduulien yhteydessä globaalin moduulin, kuten http:n, korjausta pidetään sivuvaikutteisena toimenpiteenä, koska http on käytettävissä mistä tahansa koodikannan kohdasta ja mikä tahansa muu entiteetti voi olla riippuvainen siitä. Nämä entiteetit odottavat http-moduulin toimivan tavanomaisella tavallaan. Muutamalla yhtä http-menetelmistä katkaisemme tehokkaasti kaikki muut http-riippuvuudet koodikannan sisällä.

Koska toimimme dynaamisesti kirjoitetulla kielellä, asiat eivät välttämättä epäonnistu heti ja mieluummin käyttäytyvät oletuksena arvaamattomalla tavalla, mikä tekee virheenkorjauksesta erittäin monimutkaisen tehtävän. Muissa käyttötapauksissa samassa attribuutissa voi olla kaksi eri korjaustiedostoa samasta komponentista, jolloin emme voi oikein ennustaa, kumpi korjaustiedosto menee toisen edelle, mikä johtaa vielä arvaamattomampaan koodiin.

On myös tärkeää mainita, että apinoiden paikannuksen käyttäytymisessä voi olla pieniä eroja eri ohjelmointikielten välillä. Kaikki riippuu kielisuunnittelusta ja toteutusvalinnoista. Esimerkiksi pythonissa korjaustiedosto ei vaikuta kaikkiin ilmentymiin, joissa on korjattu menetelmä. Jos ilmentymä nimenomaan kutsuu korjattua menetelmää, se saa uuden päivitetyn version, päinvastoin, muut ilmentymät, joilla saattaa olla vain korjausmenetelmään osoittavia attribuutteja, jotka eivät kutsu sitä nimenomaisesti, saavat alkuperäisen version, tämä johtuu siitä, kuinka python sidonta luokissa toimii.

Johtopäätös

Tässä artikkelissa tutkimme staattisten ja dynaamisten ohjelmointikielten välisiä korkean tason eroja, näimme kuinka dynaamiset ohjelmointikielet voivat hyötyä uusista paradigmoista ja malleista, jotka hyödyntävät näiden kielten luontaista joustavuutta. Esittelemämme esimerkki liittyi Monkey patchingiin, tekniikkaan, jota käytetään koodin käyttäytymisen laajentamiseen muuttamatta sitä lähteestä. Näimme tapauksen, jossa tämän tekniikan käyttö olisi hyödyllistä mahdollisten haittojen ohella. Ohjelmistokehityksessä on kyse kompromisseista, ja oikean ratkaisun käyttäminen ongelmaan vaatii kehittäjältä tarkkoja pohdintoja ja hyvää ymmärrystä arkkitehtuurin periaatteista ja perusteista.


Career Services background pattern

Urapalvelut

Contact Section background image

Pidetään yhteyttä

Code Labs Academy © 2025 Kaikki oikeudet pidätetään.