Beždžionių taisymas dinaminio programavimo kalbomis: „JavaScript“ pavyzdys

Javascript
dinaminis programavimas
Beždžionių pataisymas dinaminio programavimo kalbomis cover image

Įvadas

Šiame straipsnyje bus nagrinėjamos dinaminės ir statinės programavimo kalbų sąvokos, pagrindiniai jų skirtumai ir kiekvienos paradigmos pranašumai bei trūkumai. Atliekant šį tyrimą daugiau dėmesio bus skiriama dinaminėms programavimo kalboms, ypač vienam iš esminių šablonų, kuriuos ji įgalina: Monkey Patch, šis modelis bus parodytas naudojant JavaScript pavyzdį.

Dinaminės vs statinės programavimo kalbos

Terminija

Kad suprastume, kas yra dinaminė ar statinė kalba, turime suprasti kelis pagrindinius, dažniausiai šiame kontekste vartojamus terminus: Kompiliavimo laikas, Vykdymo laikas ir *Tipo tikrinimas *.

Kompiliavimas ir vykdymo laikas yra du terminai, atitinkantys skirtingus kompiuterio programos gyvavimo ciklo etapus, pradedant kompiliavimo laiku.

Kompiliavimo laikas

Kompiliavimo laikas yra pirmasis programos gyvavimo ciklo žingsnis. Kūrėjas rašo kodą tam tikra programavimo kalba. Dažniau mašina nesugeba suprasti kodo, parašyto aukšto lygio kalba, todėl naudojamas specialus kompiliatorius, kuris išverčia jį į žemesnio lygio tarpinį formatą, kuris yra paruoštas vykdyti.

Vykdymo laikas

Vykdymo laikas paprastai apima du veiksmus: programos įkėlimas į atmintį, skiriant jos vykdymui reikalingus išteklius kartu su instrukcijomis, ir tada programos vykdymas tų instrukcijų tvarka.

Toliau pateikta diagrama iliustruoja šį procesą:

Tipo tikrinimas

Tipo tikrinimas yra integruota funkcija beveik visose programavimo kalbose. Tai galimybė patikrinti, ar tam tikram kintamajam priskirta reikšmė atitinka teisingą to kintamojo tipą. Kiekviena programavimo kalba turi skirtingą būdą atminti tam tikro tipo reikšmę. Šie skirtingi atvaizdai leidžia patikrinti vertės tipo ir kintamojo, kuriam bandote priskirti tą reikšmę, tipo atitikimą.

Dabar, kai turime aukšto lygio supratimą apie programos gyvavimo ciklą ir tipo tikrinimą, galime pradėti tyrinėti statines programavimo kalbas.

Statinio programavimo kalbos

Statinės programavimo kalbos, taip pat vadinamos statiškai įvestomis kalbomis, yra kalbos, kuriose taikomas tipo tikrinimas, kurį minėjome kompiliavimo etape. Tai iš tikrųjų reiškia, kad kintamasis išlaiko savo tipą deklaruojant ir jam negali būti priskirta jokia kita reikšmė, išskyrus reikšmes iš jo deklaracijos tipo. Statinės programavimo kalbos suteikia papildomos saugos dirbant su tipais, tačiau tam tikrais atvejais gali sulėtinti kūrimo procesą, kai tai tampa griežtu apribojimu.

Dinaminio programavimo kalbos

Kita vertus, dinaminės programavimo kalbos taiko tipo tikrinimą vykdymo metu. Tai reiškia, kad bet kuris kintamasis gali turėti bet kokią reikšmę bet kuriame programos taške. Tai gali būti naudinga, nes tai suteikia kūrėjui lankstumo, kurio nėra statinėse kalbose. Dinaminės kalbos paprastai vykdomos lėčiau nei jų statinės kalbos, nes jos apima papildomą veiksmą dinamiškai išsiaiškinti kiekvieno kintamojo įvedimą.

Beždžionių pleistras

Statinis vs dinaminis rašymas yra pagrindinis programavimo kalbos bruožas, o tai, kad viena paradigma viršija kitą, gali įgalinti daugybę skirtingų modelių ir praktikų, kurie gali žymiai pagerinti kūrimo kokybę ir greitį. Jis taip pat gali atverti duris daugeliui apribojimų ir anti-modelių, jei priimant dizaino sprendimus neatsižvelgiama į tai.

Ypač žinoma, kad dinamiškai įvestos programavimo kalbos siūlo didesnį lankstumo lygį, nes jos neapriboja kintamojo iki vieno tipo. Šis lankstumas susijęs su papildoma kūrėjo atsakomybe diegiant ir derinant programas, siekiant užtikrinti, kad neatsirastų nenuspėjamų veiksmų. Beždžionių pleistrų modelis kilęs iš šios filosofijos.

Monkey Patch reiškia komponento veikimo išplėtimo / pakeitimo vykdymo metu procesą. Aptariamas komponentas gali būti biblioteka, klasė, metodas ar net modulis. Idėja ta pati: kodo dalis yra sukurta tam tikrai užduočiai atlikti, o beždžionių pataisymo tikslas yra pakeisti arba išplėsti tos kodo dalies elgseną, kad ji atliktų naują užduotį, nekeičiant paties kodo. .

Tai įmanoma dinaminėje programavimo kalboje, nes nesvarbu, su kokio tipo komponentu susiduriame, jis vis tiek turi tą pačią objekto struktūrą su skirtingais atributais, atributai gali turėti metodus, kuriuos galima priskirti iš naujo, norint pasiekti naują objekto elgesį. nesigilinant į jo vidų ir įgyvendinimo detales. Tai ypač naudinga trečiųjų šalių bibliotekoms ir moduliams, nes juos paprastai sunkiau koreguoti.

Toliau pateiktame pavyzdyje bus parodytas įprastas naudojimo atvejis, kai gali būti naudinga naudoti beždžionių pleistro techniką. „Javascript“ buvo naudojamas įgyvendinant čia, tačiau tai vis tiek turėtų būti taikoma bet kuriai kitai dinaminio programavimo kalbai.

Pavyzdys

Įdiekite minimalų testavimo sistemą naudodami Node vietinį HTTP modulį

Vienetų ir integravimo testavimas gali būti naudojamas beždžionių pataisymo atvejais. Paprastai jie apima testavimo atvejus, apimančius daugiau nei vieną paslaugą, skirtą integracijos testavimui, arba API ir (arba) duomenų bazių priklausomybes vienetų testavimui. Pagal šiuos du scenarijus ir norėdami visų pirma pasiekti testavimo tikslus, norėtume, kad mūsų testai būtų nepriklausomi nuo šių išorinių išteklių. Būdas to pasiekti – tyčiotis. Tyčiojimasis imituoja išorinių tarnybų elgseną, kad bandymas galėtų sutelkti dėmesį į tikrąją kodo logiką. Beždžionių pataisymas čia gali būti naudingas, nes jis gali pakeisti išorinių paslaugų metodus, pakeičiant juos vietos rezervavimo metodais, kuriuos vadiname „stub“. Šie metodai grąžina laukiamą rezultatą testavimo atvejais, todėl galime išvengti užklausų inicijavimo gamybos tarnyboms vien dėl bandymų.

Šis pavyzdys yra paprastas „Monkey“ pataisymo įgyvendinimas „NodeJs“ vietiniame http modulyje. http modulis yra sąsaja, kuri įgyvendina http protokolo metodus NodeJ. Jis daugiausia naudojamas kuriant barebone http serverius ir bendraujant su išorinėmis paslaugomis naudojant http protokolą.

Toliau pateiktame pavyzdyje turime paprastą testavimo atvejį, kai iškviečiame išorinę paslaugą, kad gautume vartotojų ID sąrašą. Užuot iškvietę tikrąją paslaugą, pataisome http get metodą, todėl jis tiesiog grąžina laukiamą rezultatą, kuris yra atsitiktinių vartotojo ID masyvas. Tai gali neatrodyti labai svarbu, nes mes tik gauname duomenis, bet jei įdiegsime kitą bandomąjį atvejį, apimantį tam tikrų duomenų keitimą, atlikdami bandymus galime netyčia pakeisti gamybos duomenis.

Taip galime įdiegti savo funkcijas ir parašyti kiekvienos funkcijos testus, tuo pačiu užtikrindami savo gamybos paslaugų saugumą.

// 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");
});

Aukščiau pateiktas kodas yra paprastas, importuojame http modulį, iš naujo priskiriame metodą http.get su nauju metodu, kuris tiesiog grąžina ID masyvą. Dabar mes vadiname naują pataisytą metodą bandymo atveju ir gauname naują laukiamą rezultatą.

~/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.

Dažni spąstai ir apribojimai

Nenuostabu, kad beždžionių lopymas turi savų trūkumų ir apribojimų. Mazgo modulių sistemos modulių kontekste visuotinio modulio, pvz., http, pataisymas laikomas operacija su šalutiniais poveikiais, nes http pasiekiama iš bet kurio kodų bazės taško ir bet kuris kitas subjektas gali būti nuo jo priklausomas. Šie subjektai tikisi, kad http modulis veiks įprastu elgesiu, o pakeitę vieną iš http metodų efektyviai panaikinsime visas kitas http priklausomybes kodų bazėje.

Kadangi dirbame dinamiškai spausdinama kalba, viskas gali nepavykti iš karto ir veikiau pagal nutylėjimą elgsis nenuspėjamai, todėl derinimas tampa itin sudėtinga užduotimi. Kitais naudojimo atvejais tame pačiame atribute gali būti dvi skirtingos to paties komponento pataisos. Tokiu atveju tikrai negalime numatyti, kuri pataisa bus svarbesnė už kitą, todėl kodas bus dar labiau nenuspėjamas.

Taip pat svarbu paminėti, kad beždžionių pataisymas gali šiek tiek skirtis skirtingose ​​programavimo kalbose. Viskas priklauso nuo kalbos dizaino ir įgyvendinimo pasirinkimų. Pavyzdžiui, „python“ pataisa paveiks ne visus atvejus, naudojant pataisymo metodą. Jei egzempliorius aiškiai iškviečia pataisytą metodą, jis gaus naują atnaujintą versiją, priešingai, kiti egzemplioriai, kurie gali turėti tik atributus, nurodančius pataisytą metodą, o ne tiesiogiai jo iškviečiantys, gaus pirminę versiją. Taip yra dėl to, kaip python įrišimas klasėse veikia.

Išvada

Šiame straipsnyje mes ištyrėme aukšto lygio skirtumus tarp statinių ir dinaminių programavimo kalbų, matėme, kaip dinamiškoms programavimo kalboms gali būti naudingos naujos paradigmos ir modeliai, išnaudojantys šioms kalboms būdingą lankstumą. Mūsų parodytas pavyzdys buvo susijęs su beždžionių pataisymu – technika, naudojama išplėsti kodo veikimą nekeičiant jo iš šaltinio. Matėme atvejį, kai šios technikos naudojimas būtų naudingas kartu su galimais trūkumais. Programinės įrangos kūrimas yra susijęs su kompromisais, o norint naudoti tinkamą problemos sprendimą, kūrėjas turi išsamiai apsvarstyti ir gerai suprasti architektūros principus ir pagrindus.


Career Services background pattern

Karjeros paslaugos

Contact Section background image

Palaikykime ryšį

Code Labs Academy © 2024 Visos teisės saugomos.