implementera gränssnitt i JavaScript med implementera.js

Josh J
Josh j

följ
November 7, 2017 · 5 min läs

i detta blogginlägg kommer jag att introducera begreppet gränssnitt och hur de kan vara användbara även i dynamiska språk. Jag kommer också att använda biblioteket genomföra.js för att få konceptet till JavaScript, och visa dig hur du får lite extra verktyg ur gränssnitt.

Google definierar ett gränssnitt som ” en punkt där två system, ämnen, organisationer etc. Möt och interagera, ” och denna definition gäller för gränssnitt i programmering. I mjukvaruutveckling är ett gränssnitt en struktur som upprätthåller specifika egenskaper på ett objekt — på de flesta språk är detta objekt en klass.

Här är ett exempel på ett gränssnitt i Java:

i exemplet ovan beskriver gränssnittetCar en klass som har två metoder utan returtyp, som båda tar ett enda heltalsargument. Detaljerna i implementeringen av varje funktion lämnas upp till klassen, det är därför metoderna båda har ingen kropp. För att säkerställa att en klass implementerar Car gränssnittet använder viimplements nyckelordet:

enkel

gränssnitt i JavaScript

gränssnitt är inte en sak i JavaScript, inte riktigt ändå. JavaScript är ett dynamiskt språk, ett där typer ändras så ofta att utvecklaren kanske inte ens har insett, på grund av detta folk hävdar att det inte finns något behov av ett gränssnitt som ska läggas till ECMAScript-standarden som JavaScript bygger på.

JavaScript har dock vuxit massivt som ett backend-språk i form av Nod.js, och med det kommer olika krav och en annan publik som kan ha en annan åsikt. För att lägga till detta blir språket snabbt front-end-verktyget; det har kommit till den punkt där många utvecklare kommer att skriva den stora majoriteten av sin HTML inuti .js-filer i form av JSX.

så när språket växer för att ta på sig fler roller är det bra att se till att en av våra mest avgörande datastrukturer är vad vi förväntade oss att det skulle vara. JavaScript kan ha nyckelordet class, men i sanning är det bara en avinstallerad konstruktörfunktion, och en gång kallad är det helt enkelt ett objekt. Objekt är allestädes närvarande, så det är ibland fördelaktigt att se till att de matchar en viss form.

nyligen på jobbet hittade jag ett fall där en utvecklare förväntade sig att en egenskap som returneras som en del av ett API-svar skulle vara true men istället fick "true", vilket orsakade ett fel. Ett enkelt misstag, och ett som också kunde ha undvikits om vi hade ett gränssnitt.

men vänta, det finns mer!

gränssnitt, med några mindre ändringar, kan användas för att omforma objekt. Tänk dig att implementera ett ”strikt” gränssnitt, där inga egenskaper utanför gränssnittet är tillåtna, vi kan ta bort eller byta namn på dessa egenskaper, eller till och med kasta ett fel om vi stöter på dem.

så nu har vi ett gränssnitt som kommer att berätta när vi saknar vissa egenskaper, men också när vi har oväntade egenskaper, eller om egenskapernas typer inte är vad vi förväntar oss. Detta lägger till andra möjligheter, till exempel refactoring ett svar från ett API samtidigt som du lägger till det extra säkerhetsskiktet ovanpå gränssnittets standardbeteende. Vi kan också använda gränssnitt i enhetstester om vi får dem att kasta fel.

implementera.JS

implementera.js är ett bibliotek som försöker föra gränssnitt till JavaScript. Tanken är enkel: definiera ett gränssnitt, definiera typerna av dess egenskaper och använd det för att säkerställa att ett objekt är vad du förväntar dig att det ska vara.

Setup

Installera först paketet:

npm install implement-js

skapa sedan en .js — fil och import implementInterface och type:

vårt första gränssnitt

för att skapa ett gränssnitt, ring bara Interface och skicka i en sträng som namnet på ditt gränssnitt-det rekommenderas inte, men om du utelämnar namnet kommer ett unikt ID att genereras. Detta returnerar en funktion som accepterar ett objekt där egenskaperna är allatype objekt, ett andra argument kan också skickas med alternativ för att visa varningar, kasta fel, ta bort eller byta namn på Egenskaper, se till att endast egenskaperna hos gränssnittet finns, eller för att utöka en befintlig Interface.

här är ett gränssnitt som beskriver en bil:

den har enseats egenskap som ska vara av typnummer, en passagerare array som innehåller objekt som själva måste genomföraPassenger gränssnitt, och den innehåller enbeep egenskap, som bör vara en funktion. Alternativen error och strict har ställts in på true, vilket innebär att fel kommer att kastas när en egenskap i gränssnittet saknas och även när en egenskap som inte finns på gränssnittet hittas.

implementera vårt gränssnitt

nu vill vi implementera vårt gränssnitt, i ett enkelt exempel skapar vi ett objekt med ett objekt bokstavligt och ser om vi kan implementera vårt gränssnitt.

först skapar vi ettFord objekt, då försöker vi implementera det mot vårtCar gränssnitt:

som vi ser från kommentaren ovan, detta kastar ett fel. Låt oss titta tillbaka på vårtCar gränssnitt:

Vi kan se att medan alla egenskaper är närvarande är strikt läge också sant, vilket innebär att den extra egenskapen fuelType orsakar ett fel att kastas. Dessutom, även om vi har en passengers egenskap, är det inte en array.

för att korrekt implementera gränssnittet tar vi bort fuelType och ändrar värdet på passengers så att det är en array som innehåller objekt som implementerar Passenger gränssnitt:

” men JavaScript är inte ett objektorienterat språk!”

det är sant att även om gränssnitt vanligtvis är associerade med objektorienterade språk, och JavaScript är ett multiparadigmspråk som använder prototyparv, kan gränssnitt fortfarande vara mycket användbara.

till exempel, med implement-js kan vi enkelt refactor ett API-svar samtidigt som vi säkerställer att det inte har avvikit från vad vi förväntar oss. Här är ett exempel som används tillsammans med redux-thunk:

först definierar vi gränssnittet TwitterUser, som utökar gränssnittet User, som ett objekt med twitterId och twitterUsername egenskaper. trim är sann mening att vi kommer att kassera alla egenskaper som inte beskrivs på TwitterUser gränssnitt. Eftersom vårt API returnerar egenskaper i ett ovänligt format har vi bytt namn på egenskaperna från twitter_username och twitter_id till camelcase-versioner av sig själva.

därefter definierar vi en async-åtgärd medredux-thunk, åtgärden utlöser ett API-samtal och vi använder vårtTwitterUser gränssnitt för att kassera egenskaper som vi inte vill ha och för att säkerställa att det implementerar de egenskaper vi förväntar oss, med rätt typer. Om du föredrar att hålla dina Action creators rena (er) eller inte använder redux-thunk, kanske du vill kontrollera gränssnittet inuti twitterService.getUser och returnera resultatet.

Obs: vid förlängning av ett gränssnitt alternativ ärvs inte

enhetstester är också en lämplig plats att använda gränssnitt:

Sammanfattningsvis

Vi har sett hur gränssnitt kan vara användbara i JavaScript: även om det är ett mycket dynamiskt språk, kontrollerar formen på ett objekt och att dess egenskaper är en specifik datatyp ger oss ett extra lager av säkerhet som vi annars skulle missa. Genom att bygga på begreppet gränssnitt och använda implement-js har vi också kunnat få ytterligare verktyg utöver den extra säkerheten.

Posted on

Lämna ett svar

Din e-postadress kommer inte publiceras.