Kontrakter Den praktiske siden av semantikken

Vi innser alle at vi skal skrive semantisk kode. Kanskje, du bruker enda

eller riktig, og føler deg ganske bra om deg selv. Men vurderer du også den underforståtte kontrakten som eksisterer når du kodes?

La oss forestille oss at en kunde ber om en tekstlink, "Se mer,"Som bør avdekke tilleggs tekst på siden. se mer med en klikkbehandler bør jobbe perfekt, ikke sant? Hei, det ser ut og fungerer som ønsket!

Nei, det vil ikke alltid fungere riktig, da det bryter kontrakten mellom deg og nettleseren. Spesielt refererer jeg til den som sier href Attributtet må ha en verdi som er en gyldig nettadresse.

Det er praktiske problemer som kan oppstå ved brudd på kontrakter, og det er mye bedre grunner til å skrive semantisk kode enn ting du vanligvis tenker på når du hører begrepet "semantisk".


Populære argumenter for semantisk kode

Det er imidlertid mye mer praktiske grunner til å bry seg om semantikk: kontrakter.

Hvis du spør en gjennomsnittlig utvikler hva verdien av semantisk kode, vil du sannsynligvis høre noe i tråd med:

  • Det hjelper de funksjonshemmede
  • Korrekt beskrivende kode gjør det lettere for maskiner å tolke

Begge er dessverre veldig lett å forsømme. "Blinde mennesker og roboter er ikke målgruppen" er for enkelt til et svar, uansett hvor misvisende eller uvitende det kan være.

I andre tilfeller kan du kanskje høre syklisk begrunnelse, for eksempel "ikke-semantisk kode er dårlig, fordi det ikke er meningsfullt." Det er så populært å si at parodier på den allerede har spratt opp rundt på nettet!

Det er imidlertid mye mer praktiske grunner til å bry seg om semantikk: kontrakter.


Brukskontrakter

Hver gang du bruker noen funksjonalitet fra nettleservirksomhetene, programmeringsspråket ditt, eller en API, stole du på en kontrakt.

På den ene siden av kontrakten finnes en leverandør av funksjonalitet. For eksempel, når du bruker en tag, er nettleserutviklere lovende for deg at de vil gi en enkel måte for brukeren av søknaden din å navigere til den angitte webadressen.

Som alltid er det imidlertid den andre siden av kontrakten. Implementeren av funksjonaliteten lover å bruke funksjonaliteten som spesifisert. Så snart han misbruker denne funksjonaliteten, er alle spillene slått av - som fører til potensiell feil.

Nettleserfunksjonalitetskontrakter

La oss gå tilbake til "Se mer"Eksempel fra tidligere. I de tidlige dagene av JavaScript, ville utviklere skrive deres JavaScript ved hjelp av en pseudo-protokoll, javascript:

 Se mer

Relativt raskt begynte de å innse at denne tilnærmingen har minst en praktisk feil: JavaScript-koden vises i statuslinjen i nettleseren, som ikke ser profesjonell ut. Svaret på dette dilemmaet var å flytte koden til en ved trykk handler, og erstatte href Tilordne med en tom hashidentifikator, slik som:

 Se mer

Selvfølgelig løste dette ikke alt. Hvis ShowMore har en feil, returner falsk er aldri kalt, og siden rulles til toppen - absolutt ikke ønsket oppførsel.

I dag separerer utviklere deres HTML og JavaScript og bruker riktige hendelsesforebyggende teknikker:

 Se mer
 $ ('a.show-more'). på ('klikk', funksjon (hendelse) event.preventDefault (); ShowMore (););

Men gjett hva? Det er fortsatt mange problemer med denne tilnærmingen: Å åpne en ny fane, fungerer ikke bokmerke eller kopiering av koblingen som brukeren kan forvente (spesielt hvis det er en tag på siden), noe som resulterer i forvirring, og muligens en tapt kunde.

Legg merke til hvordan alle problemene som hittil er beskrevet, stammer fra et enkelt faktum. Utviklere har krenket sin del av kontrakten med nettleserenes beslutningstakere: href Attributtet må inneholde en korrekt nettadresse, men i stedet ble utviklere innsatt alle slags søppel.

Hvis vi prøver å overholde kontrakten, må vi spørre oss selv: "Hvorfor tillater kontrakten ikke oss å gjøre det vi trenger?" Svaret er enkelt: Vi misbruker stikkord. Vi bruker det bare fordi vi vil ha teksten "Se mer"Å vises og oppføre seg som en lenke. Men når vi bruker ord, som "se" og "vises", er dette ikke domenet til CSS? Er ikke dette "Se mer"lenke, i virkeligheten, bare en knapp? Dette er enkelt å implementere:

 
 $ ('button.show-more'). på ('klikk', ShowMore);
 a, .link-style color: @ your-shade-of-blue; tekst-dekorasjon: understreke;  .link-style font: inherit; bakgrunn: ingen; grense: ingen; markør: pointer; 

Uansett hvor mange nye måter å samhandle med koblinger legges til i fremtidige iterasjoner av nettleserne, vil denne tilnærmingen fortsette å fungere, fordi vi ikke bryter noen kontrakt med nettleseren. Vi bruker elementer for å formidle deres mening, og i stedet for å kontinuerlig arbeide med nye problemer, vet vi at nettleseren vil behandle dette riktig, da det forstår hva vi vil ha.

Visst, det kan kreve noen ekstra linjer med CSS for å tilbakestille noen av standardknappen styling. Det er verdt det! Ikke vær lat.

Spesifikasjoner som kontrakter

... de som kjente semantikken, og bevidst ignorert dem.

I 2005 lærte en stor del av nettutviklingssamfunnet den vanskelige måten at ignorering av HTTP-krav er dårlig. Den nylig utgitte Google Web Accelerator prefetcherer nettadresser på en side for å minimere brukerens ventetid på et klikk.

Dette ødela ødeleggelse i applikasjoner, som ignorert HTTP, og satte destruktive operasjoner bak enkle koblinger. Og det var mange slike applikasjoner.

Problemet hvilte ikke på utviklerne som ikke forstod semantikken til HTTP-metoder. Nei, problemet kom fra de som kjente semantikken, ignorert bevidst, og delte ikke kunnskapen.


Vedlikeholdskontrakter

Forvirrende kode er dårlig!

Kontrakter eksisterer også mellom utviklere. Hver gang du skriver en kode, legger du et løfte til fremtidige utviklere om at det gjør akkurat hva det ser ut til å gjøre. Med andre ord er forvirrende kode dårlig!

For eksempel bruker du en filtreringsfunksjon (for eksempel filter i Python) å gå over elementer er feil, fordi det er en underforstått kontrakt at filtreringsfunksjoner bare endrer listen uten å ha noen bivirkninger:

 def show (element): print (item) fruits = ['orange', 'apple', 'sitron'] filter (show, fruits) # Feil bruk av filter

I stedet bruker du eksplisitt looping over en liste:

 def show (item): print (item) fruit = ['appelsin', 'eple', 'sitron'] for frukt i frukt: show (frukt)

På den annen side, hvis du kan stole på en kontrakt, kan du som følge av dette avklare koden din. For eksempel bruker array_filter i stedet for a til loop i PHP for å filtrere elementer tillater andre utviklere å forstå hva som skjer etter et enkelt blikk:

 $ inntekter = [20, 15, -7, 19]; $ profit = array_filter ($ inntekt, funksjon ($ i) return $ i> 0;);

Sammenlign koden ovenfor for å bruke a til løkke:

 $ inntekter = [20, 15, -7, 19]; $ fortjeneste = []; foreach ($ inntekter som $ i) hvis ($ i> 0) $ overskudd [] = $ i; 

Den andre versjonen er verre, ikke bare fordi den er lengre, men også fordi array_filter gir en forventning. Det er klart at $ fortjeneste er en delmengde av $ inntekter. Det er ingen slik konvensjon med en generisk til sløyfe, som forklarer hvorfor vi ikke kan gjøre noen antagelser uten først å dechiffrere sløyfens indre.


Skrive ordentlig semantisk kode

Hvordan skiller du mellom kode som er og er ikke semantisk? Hvordan ser du disse kontraktene? For det meste, bare spørre deg selv spørsmål bør være tilstrekkelig.

HTML-tagger

"Jeg bruker en tag og jeg må sette noe i en href Egenskap. href lagrer linkmåldestinasjonen. Så hvor gjør min tag link til? "Ingen steder? Vel, jeg kan da konkludere med at jeg sannsynligvis misbruker denne taggen.

Navngitte funksjoner

"Jeg må skrive ut innholdet i listen min i en filter funksjon. Er utskrift av elementer en del av filtreringsprosessen? "Egentlig ikke. Det betyr at jeg misbruker filter.

Funksjoner som gjør for mye

"Jeg skriver en getFoo metode, og må legge til noen endringskode i den. Gjør endringsstaten mening som en del av å få foo? Ville noen som bare vil få foo forventer at noe annet skjer? "Sannsynligvis ikke!

Separasjon av bekymringer

"Jeg vil legge til litt JavaScript i en HTML ved trykk Egenskap. Er dette riktig? "Filen du endrer er .html, Ikke sant? I stedet plasserer du JavaScript og CSS innen .js og .css filer, henholdsvis. Alltid.

Selvfølgelig kan det i mange tilfeller være nødvendig med ytterligere kunnskap for å vurdere situasjonen riktig. Det som betyr mest er å begynne å tenke på disse tingene, og for å unngå prinsippet "den (på en måte) fungerer, så det er fint nok."I stedet spør alltid deg selv," Hva betyr koden jeg skriver egentlig? "


Konklusjon

Brudd på kontrakt sikrer at samarbeidet bryter.

Samarbeidet er alltid avhengig av innsats fra begge parter. Det meste av programvareutviklingen reduserer til samarbeid: Samarbeid mellom maskinvareprodusenter, systemprogrammerere, nettleserutviklere, biblioteksforfattere, webutviklere og mange andre. Brudd på kontrakt sikrer at samarbeidet bryter.

Kodesemantikk er en slik kontrakt. Ta vare på det for ditt eget gode!


Fotnoter

semantisk: Begrepet "semantisk" er ofte misforstått. I sammenheng med denne artikkelen bruker jeg begrepet for å skille mellom meningen med koden fra resultater koden produserer. For eksempel, semantisk betydning av en tag er representasjon av en lenke, mens den enkle, praktiske meningen med den er klikkbar, understreket tekst.

Strengt tatt, et tomt fragmentidentifikator # kan anses å være gyldig i denne konteksten. Denne teknikken, men savner det punktet jeg lager i artikkelen.