Majomfoltozás dinamikus programozási nyelveken: JavaScript példa

Javascript
dinamikus programozás
Majomfoltozás dinamikus programozási nyelveken cover image

Bevezetés

Ez a cikk megvizsgálja a dinamikus és statikus programozási nyelvek fogalmait, a kettő közötti fő különbségeket, és azt, hogy az egyes paradigmák milyen előnyöket és buktatókat kínálnak. Ez a feltárás tovább összpontosít a dinamikus programozási nyelvekre, különösen az egyik alapvető mintára, amelyet lehetővé tesz: Monkey Patch, ezt a mintát egy példa segítségével mutatjuk be a JavaScript nyelven.

Dinamikus vs statikus programozási nyelvek

Terminológia

Ahhoz, hogy megértsük, mi számít dinamikus vagy statikus nyelvnek, meg kell értenünk néhány, ebben a kontextusban gyakran használt kulcskifejezést: Fordítási idő, Futtatási idő és *Típusellenőrzés *.

A Fordítás és a Runtime két olyan kifejezés, amelyek a számítógépes program életciklusának különböző szakaszainak felelnek meg, kezdve a fordítási idővel.

Összeállítási idő

A fordítási idő a program életciklusának első lépése. A fejlesztő kódot ír egy adott programozási nyelven. Leggyakrabban a gép nem képes megérteni a magas szintű nyelven írt kódot, ezért egy dedikált fordító segítségével lefordítják azt egy alacsonyabb szintű, köztes formátumra, amely készen áll a végrehajtásra.

Futásidő

A futási idő általában két lépésből áll: a program betöltése a memóriába a végrehajtásához szükséges erőforrások és az utasítások lefoglalásával, majd a program végrehajtása az utasítások sorrendjében.

Az alábbi diagram ezt a folyamatot szemlélteti:

Típusellenőrzés

A típusellenőrzés szinte minden programozási nyelv beépített funkciója. Ez annak ellenőrzése, hogy egy adott változóhoz rendelt érték megfelel-e az adott változó megfelelő típusának. Minden programozási nyelvnek más módja van egy adott típusú érték megjelenítésére a memóriában. Ezek a különböző ábrázolások lehetővé teszik az érték típusa és az értéket hozzárendelni kívánt változó típusa közötti megfelelés ellenőrzését.

Most, hogy magas szintű ismereteink vannak a program életciklusáról és a típusellenőrzésről, folytathatjuk a statikus programozási nyelvek felfedezését.

Statikus programozási nyelvek

A statikus programozási nyelvek, más néven statikusan tipizált nyelvek olyan nyelvek, amelyek alkalmazzák a fordítási fázisban említett típusellenőrzést. Ez gyakorlatilag azt jelenti, hogy egy változó megtartja a típusát a deklarációból, és nem lehet hozzá más értéket rendelni, mint a deklarációs típusából származó értékeket. A statikus programozási nyelvek extra biztonságot nyújtanak a típusok kezelésekor, de bizonyos használati esetekben lelassíthatják a fejlesztési folyamatot, amikor ez szigorú korlátozást jelent.

Dinamikus programozási nyelvek

A dinamikus programozási nyelvek viszont típusellenőrzést alkalmaznak futás közben. Ez azt jelenti, hogy a program bármely pontján bármely változó bármilyen értéket tartalmazhat. Ez előnyös lehet, mivel olyan szintű rugalmasságot biztosít a fejlesztő számára, amely nincs jelen a statikus nyelvekben. A dinamikus nyelvek általában lassabbak a végrehajtás során, mint statikus társaik, mivel egy további lépést tartalmaznak az egyes változók beírásának dinamikus kitalálására.

Monkey Patch

A statikus vs. dinamikus gépelés alapvető tulajdonsága a programozási nyelveknek, mivel az egyik paradigmával a másikkal szemben egy sor különböző mintát és gyakorlatot tesz lehetővé, amelyek jelentősen javíthatják a fejlesztés minőségét és sebességét. Számos korlátozás és mintaellenesség előtt is megnyithatja az ajtót, ha nem veszik figyelembe a tervezési döntéseket.

Különösen a dinamikusan tipizált programozási nyelvekről ismert, hogy magasabb szintű rugalmasságot kínálnak, mivel nem korlátozzák a változókat egyetlen típusra. Ez a rugalmasság azzal jár, hogy a fejlesztőnek több felelősséget kell vállalnia a programok megvalósítása és hibakeresése során, hogy megbizonyosodjon arról, hogy nem fordul elő előre nem látható viselkedés. A majomfolt minta ebből a filozófiából származik.

A Monkey Patch egy összetevő működésének futás közbeni kiterjesztésének/módosításának folyamatára utal. A szóban forgó komponens lehet könyvtár, osztály, metódus vagy akár modul is. Az ötlet ugyanaz: egy kódrészletet egy bizonyos feladat elvégzésére készítenek, és a majomfoltozás célja az adott kódrészlet viselkedésének megváltoztatása vagy kiterjesztése, hogy az új feladatot hajtson végre, mindezt anélkül, hogy magát a kódot megváltoztatná. .

Ez a dinamikus programozási nyelvben lehetővé válik, mivel függetlenül attól, hogy milyen típusú komponenssel van dolgunk, annak mindig ugyanaz a szerkezete, mint egy objektum különböző attribútumokkal, az attribútumok olyan metódusokat tartalmazhatnak, amelyeket át lehet rendelni, hogy új viselkedést érjünk el az objektumban. anélkül, hogy belemennénk a belső részébe és a megvalósítás részleteibe. Ez különösen hasznos lehet harmadik féltől származó könyvtárak és modulok esetében, mivel ezeket általában nehezebb módosítani.

A következő példa egy gyakori felhasználási esetet mutat be, amelynek előnyös lehet a majomfolt technika használata. Javascriptet használtunk a megvalósítás érdekében, de ennek továbbra is általánosan érvényesnek kell lennie bármely más dinamikus programozási nyelvre.

Példa

Valósítson meg egy minimális tesztelési keretrendszert a Node natív HTTP-moduljával

Az egység- és integrációs tesztelés a Monkey foltozás használati esetei alá eshet. Általában olyan teszteseteket foglalnak magukban, amelyek egynél több szolgáltatásra terjednek ki az integrációs teszteléshez, vagy API- és/vagy adatbázis-függőségekre az egységteszteknél. Ebben a két forgatókönyvben, és elsősorban a tesztelés céljainak elérése érdekében azt szeretnénk, ha tesztjeink függetlenek lennének ezektől a külső erőforrásoktól. Ezt a gúnyolással lehet elérni. A gúnyolás a külső szolgáltatások viselkedését szimulálja, így a teszt a kód tényleges logikájára összpontosíthat. A majomfoltozás itt hasznos lehet, mivel módosíthatja a külső szolgáltatások metódusait úgy, hogy azokat helyőrző metódusokkal helyettesíti, amelyeket „csonknak” nevezünk. Ezek a módszerek a tesztesetekben a várt eredményt adják vissza, így elkerülhetjük, hogy pusztán a tesztek kedvéért kéréseket kezdeményezzünk az éles szolgáltatások felé.

A következő példa a Monkey javítás egyszerű megvalósítása a NodeJ natív http modulján. A http modul az az interfész, amely megvalósítja a http protokoll metódusait a NodeJ-k számára. Főleg barebone http szerverek létrehozására és külső szolgáltatásokkal való kommunikációra használják a http protokoll használatával.

Az alábbi példában van egy egyszerű tesztelési eset, amikor egy külső szolgáltatást hívunk meg a felhasználói azonosítók listájának lekéréséhez. Ahelyett, hogy a tényleges szolgáltatást hívnánk meg, javítjuk a http get metódust, így az csak a várt eredményt adja vissza, amely véletlenszerű felhasználói azonosítók tömbje. Ez talán nem tűnik nagy jelentőségűnek, mivel csak adatokat kérünk le, de ha egy másik tesztesetet implementálunk, amely valamilyen adatmódosítást tartalmaz, akkor véletlenül megváltoztathatjuk a termelési adatokat a tesztek futtatásakor.

Így tudjuk megvalósítani funkcionalitásainkat, és teszteket írni minden egyes funkcióhoz, miközben garantáljuk termelési szolgáltatásaink biztonságát.

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

A fenti kód egyértelmű, importáljuk a http modult, újra hozzárendeljük a http.get metódust egy új metódussal, amely csak egy azonosító tömböt ad vissza. Most a teszteseten belül meghívjuk az új patched metódust, és megkapjuk az új várt eredményt.

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

Gyakori buktatók és korlátok

Nem meglepő, hogy a majomfoltozásnak megvannak a maga hibái és korlátai. A csomóponti modulrendszer moduljaival összefüggésben egy globális modul, például a http javítása mellékhatásokkal járó műveletnek minősül, mivel a http a kódbázis bármely pontjáról elérhető, és bármely más entitás függhet tőle. Ezek az entitások azt várják a http modultól, hogy a szokásos viselkedésében működjön, az egyik http metódus megváltoztatásával hatékonyan megtörjük a kódbázison belüli összes többi http függőséget.

Mivel dinamikusan tipizált nyelven dolgozunk, előfordulhat, hogy a dolgok nem azonnal hibáznak, és inkább egy előre nem látható viselkedést váltanak ki, ami rendkívül összetett feladattá teszi a hibakeresést. Más használati esetekben előfordulhat, hogy ugyanannak az attribútumnak két különböző foltja van ugyanannak a komponensnek, ilyenkor nem tudjuk igazán megjósolni, hogy melyik javítás élvez elsőbbséget a másikkal szemben, ami még kiszámíthatatlanabb kódot eredményez.

Azt is fontos megemlíteni, hogy a majomfoltozás viselkedésében kismértékű eltérések lehetnek a különböző programozási nyelvek között. Minden a nyelvi tervezéstől és a megvalósítás választásától függ. Például a pythonban nem minden, javított módszert használó példányt érint a javítás. Ha egy példány kifejezetten meghívja a javított metódust, akkor megkapja az új frissített verziót, ellenkezőleg, azok a példányok, amelyeknek csak a javított metódusra mutató attribútumai vannak, és nem hívják meg kifejezetten, megkapják az eredeti verziót, ennek oka a python osztályokban történő kötés működik.

Következtetés

Ebben a cikkben feltártuk a statikus és dinamikus programozási nyelvek közötti magas szintű különbségeket, és láttuk, hogy a dinamikus programozási nyelvek hogyan profitálhatnak az új paradigmákból és mintákból, kihasználva a nyelvek által kínált belső rugalmasságot. Az általunk bemutatott példa a Monkey foltozáshoz kapcsolódik, egy olyan technikához, amelyet a kód viselkedésének kiterjesztésére használnak anélkül, hogy megváltoztatnák azt a forrásból. Láttunk olyan esetet, amikor ennek a technikának a használata előnyös lenne a lehetséges hátrányaival együtt. A szoftverfejlesztés a kompromisszumokról szól, és a probléma megfelelő megoldásának alkalmazása a fejlesztőtől alapos megfontolásokat, valamint az architektúra elveinek és alapjainak megfelelő megértését követeli meg.


Career Services background pattern

Karrier szolgáltatások

Contact Section background image

Maradjunk kapcsolatban

Code Labs Academy © 2024 Minden jog fenntartva.