Contracten de praktische kant van semantiek

We erkennen allemaal dat we semantische code moeten schrijven. Misschien gebruik je het zelfs

of correct, en voel me goed over jezelf. Maar overweegt u ook het impliciete contract dat bestaat wanneer u codeert?

Laten we ons voorstellen dat een klant een tekstlink aanvraagt, "Bekijk meer,"Die extra tekst op de pagina zou moeten onthullen. Bekijk meer met een klik-handler zou het perfect moeten werken, toch? Hé, het ziet eruit en functioneert zoals gevraagd!

Nee, het zal niet altijd correct werken, omdat het in strijd is met het contract tussen u en de browser. In het bijzonder verwijs ik naar degene die het zegt href kenmerk moet een waarde hebben die een geldige URL is.

Er zijn praktische problemen die zich kunnen voordoen bij het schenden van contracten, en dat zijn veel betere redenen om semantische code te schrijven dan dingen waaraan u gewoonlijk denkt wanneer u de term 'semantisch' hoort.


Populaire argumenten voor semantische code

Er zijn echter veel meer praktische redenen om om semantiek te geven: contracten.

Als je een gemiddelde ontwikkelaar vraagt ​​wat de waarde is van semantische code, hoor je waarschijnlijk iets in de trant van:

  • Het helpt gehandicapten
  • Een goede beschrijving van de code maakt het voor machines eenvoudiger om te interpreteren

Beide zijn helaas heel gemakkelijk te verwaarlozen. "Blinde mensen en robots zijn niet het doelpubliek" is een te eenvoudig antwoord, ongeacht hoe misplaatst of onwetend het kan zijn.

In andere gevallen hoor je zelfs cyclisch redeneren, zoals "niet-semantische code is slecht, omdat het niet zinvol is." Het is zo'n populair begrip dat parodieën erop al op het web zijn ontstaan!

Er zijn echter veel meer praktische redenen om om semantiek te geven: contracten.


Gebruikscontracten

Telkens wanneer u bepaalde functionaliteit van browserleveranciers, uw programmeertaal of een API gebruikt, vertrouwt u op een contract.

Aan de ene kant van het contract bestaat een aanbieder van functionaliteit. Als u bijvoorbeeld een gebruikt tag, ontwikkelaars van browsers beloven je dat ze de gebruiker van je app een eenvoudige manier bieden om naar de opgegeven URL te navigeren.

Zoals altijd is er echter de andere kant van dat contract. De implementator van de functionaliteit belooft gebruik te maken van de functionaliteit zoals gespecificeerd. Zodra hij deze functionaliteit misbruikt, zijn alle weddenschappen niet van toepassing, wat kan leiden tot een mogelijke fout.

Browserfunctionaliteitscontracten

Laten we terugkeren naar de "Bekijk meer"Voorbeeld van eerder. In de begintijd van JavaScript zouden ontwikkelaars hun JavaScript schrijven met behulp van een pseudo-protocol, javascript:

 Bekijk meer

Relatief snel begonnen ze zich te realiseren dat deze benadering ten minste één praktische fout bevat: de JavaScript-code wordt weergegeven in de statusbalk van de browser, die er niet professioneel uitziet. Het antwoord op dit dilemma was om de code naar een te verplaatsen bij klikken handler en vervang de href kenmerk met een lege hash-id, zoals:

 Bekijk meer

Dit heeft natuurlijk niet alles opgelost. Als Laat meer zien heeft een fout, return false wordt nooit gebeld en de pagina wordt naar boven gescrold - zeker niet gewenst gedrag.

Tegenwoordig scheiden ontwikkelaars hun HTML en JavaScript en gebruiken ze de juiste technieken voor evenementpreventie:

 Bekijk meer
 $ ('a.show-more'). on ('klik', functie (event) event.preventDefault (); ShowMore (););

Maar Raad eens? Er zijn nog steeds veel problemen met deze aanpak: openen op een nieuw tabblad, toevoegen van een bladwijzer of kopiëren van de link werkt niet zoals de gebruiker zou verwachten (vooral als er een tag op de pagina), wat leidt tot verwarring en mogelijk een verloren klant.

Merk op hoe alle tot nu toe beschreven problemen voortkwamen uit één enkel feit. Ontwikkelaars schenden hun deel van het contract met de makers van de browser: href kenmerk moet een correcte URL bevatten, maar in plaats daarvan hebben ontwikkelaars allerlei soorten afval ingevoerd.

Als we proberen ons contract na te leven, moeten we ons afvragen: "Waarom staat het contract ons niet toe om te doen wat we nodig hebben?" Het antwoord is simpel: we misbruiken het label. We gebruiken het alleen, omdat we de tekst willen "Bekijk meer"Verschijnen en zich gedragen als een link. Wanneer we echter woorden gebruiken, zoals 'kijken' en 'voorkomen', is dit dan niet het domein van CSS? Is dit niet "Bekijk meer"link, in werkelijkheid, gewoon een knop? Dit is eenvoudig te implementeren:

 
 $ ('button.show-more'). on ('klik', ShowMore);
 a, .link-style color: @ your-shade-of-blue; tekstdecoratie: onderstrepen;  .link-style font: inherit; achtergrond: geen; rand: geen; cursor: pointer; 

Ongeacht het aantal nieuwe manieren om met links om te gaan, wordt toegevoegd aan toekomstige iteraties van de browsers, blijft deze aanpak werken, omdat we geen contract met de browser schenden. We gebruiken elementen om hun betekenis over te brengen, en in plaats van constant aan nieuwe problemen te werken, weten we dat de browser dit correct zal behandelen, omdat het begrijpt wat we willen.

Natuurlijk kan het een paar extra regels CSS vereisen om een ​​deel van de standaard knopstijl te resetten. Het is het waard! Wees niet lui.

Specificaties als contracten

... degenen die de semantiek wel kenden en bewust negeerden.

In 2005 leerde een groot deel van de webontwikkelaars de harde manier waarop het negeren van HTTP-vereisten slecht is. De nieuw uitgebrachte Google Web Accelerator prefetches URL's op een pagina om de wachttijd van de gebruiker met een klik te minimaliseren.

Deze verwoestende chaos in applicaties, waarbij HTTP werd genegeerd, en destructieve bewerkingen achter eenvoudige koppelingen werden geplaatst. En er waren veel van dergelijke toepassingen.

Het probleem rustte niet in de handen van de ontwikkelaars die de semantiek van HTTP-methoden niet begrepen. Nee, het probleem kwam van diegenen die de semantiek kenden, bewust negeerden en de kennis niet deelden.


Onderhoudscontracten

Verwarrende code is slecht!

Contracten bestaan ​​ook tussen ontwikkelaars. Elke keer dat je een regel code schrijft, beloof je toekomstige ontwikkelaars dat het precies doet wat het lijkt te doen. Met andere woorden, verwarrende code is slecht!

Gebruik bijvoorbeeld een filterfunctie (zoals filter in Python) om items om te lussen is onjuist, omdat er een impliciet contract is dat filterfuncties alleen de lijst wijzigen, zonder bijwerkingen te hebben:

 def show (item): print (item) fruit = ['orange', 'apple', 'lemon'] filter (show, fruit) # Incorrect gebruik van filter

Gebruik in plaats daarvan expliciet een lus over een lijst:

 def show (item): print (item) fruit = ['orange', 'apple', 'lemon'] voor fruit in fruit: show (fruit)

Aan de andere kant, als u op een contract kunt vertrouwen, kunt u daardoor uw code verduidelijken. Gebruik bijvoorbeeld array_filter inplaats van een voor loop in PHP om items te filteren stelt andere ontwikkelaars in staat om te begrijpen wat er gebeurt na een enkele blik:

 $ inkomen = [20, 15, -7, 19]; $ profits = array_filter ($ inkomsten, functie ($ i) return $ i> 0;);

Vergelijk het bovenstaande fragment met het gebruik van a voor lus:

 $ inkomen = [20, 15, -7, 19]; $ winst = []; foreach ($ inkomens als $ i) if ($ i> 0) $ winsten [] = $ i; 

De tweede versie is erger, niet alleen omdat deze langer is, maar ook omdat array_filter geeft een verwachting. Het is duidelijk dat $ winst is een subset van $ inkomens. Er is geen dergelijke conventie met een generiek voor loop, wat verklaart waarom we geen veronderstellingen kunnen maken, zonder eerst de interne lus te ontcijferen.


Correcte semantische code schrijven

Hoe onderscheid je code die wel en niet semantisch is? Hoe merk je deze contracten? Voor het grootste deel, zou het eenvoudig moeten zijn om jezelf vragen te stellen.

HTML-tags

"Ik gebruik een tag en ik moet iets in een href attribuut. href slaat de bestemmingsbestemming op. Dus waar doet mijn taglink naar? "Nergens? Welnu, ik kan dan concluderen dat ik deze tag waarschijnlijk misbruik.

Benoemde functies

"Ik moet de inhoud van mijn lijst in a afdrukken filter functie. Is het afdrukken van items onderdeel van het filterproces? "Niet echt. Dat betekent dat ik misbruik maak filter.

Functies die te veel doen

"Ik schrijf een getFoo methode, en moet er een modificatiecode aan toevoegen. Heeft het wijzigen van de staat zin als onderdeel van het krijgen van foo? Zou iemand die gewoon foo wil krijgen verwachten dat er iets anders gebeurt? "Waarschijnlijk niet!

Scheiding van zorgen

"Ik wil JavaScript toevoegen in een HTML bij klikken attribuut. Klopt dit? "Het bestand dat u aan het wijzigen bent, is .html, rechts? Plaats in plaats daarvan uw JavaScript en CSS in .js en .css bestanden, respectievelijk. Altijd.

Natuurlijk kan in veel gevallen enige aanvullende kennis vereist zijn om de situatie goed te kunnen beoordelen. Het belangrijkste is om over deze dingen na te denken en het principe te vermijden "het (soort van) werkt, dus het is goed genoeg."Vraag jezelf in plaats daarvan altijd af:" Wat betekent de code die ik schrijf eigenlijk? "


Conclusie

Het overtreden van een contract zorgt ervoor dat de samenwerking zal breken.

Samenwerking hangt altijd af van de inspanningen van beide partijen. Het grootste deel van de softwareontwikkeling gaat terug naar samenwerking: samenwerking tussen hardwarefabrikanten, systeemprogrammeurs, browserontwikkelaars, bibliotheekauteurs, websiteontwikkelaars en vele anderen. Het overtreden van een contract zorgt ervoor dat de samenwerking zal breken.

Code semantiek is zo'n contract. Geef het voor uw eigen bestwil!


voetnoten

semantische: De term 'semantisch' wordt vaak verkeerd begrepen. In de context van dit artikel gebruik ik de term om het te onderscheiden betekenis van de code van de resultaten die de code oplevert. De semantische betekenis van een tag is weergave van een link, terwijl de eenvoudige, praktische betekenis ervan is klikbare, onderstreepte tekst.

Strikt genomen, een lege fragment-identifier # kan in deze context als geldig worden beschouwd. Deze technische details missen echter het punt dat ik in het artikel maak.