Naar de inhoud

Blog ·

Documentatie van vóór de merge

Twee zinnen op een nieuwe documentatiepagina waren onwaar toen ze live gingen, omdat een andere tak eerder landde. Wat een bewaking vangt en wat een grep.

Door Provibr

Een documentatiepagina is een verzameling beweringen over code. Dat klinkt voor de hand liggend tot je merkt dat niets in de build er ook maar één van toetst. Tests beweren dingen over code. Typecontroles beweren dingen over code. Proza over code beweert dingen over code en wordt geverifieerd doordat één persoon het één keer leest, op de dag dat het geschreven is.

We schreven in één ronde twee nieuwe documentatiepagina's: één voor de automatiseringseditor, ongeveer 2930 Engelse woorden verdeeld over acht secties, en één voor het dashboard, ongeveer 909. Plus een sectie die aan twee al bestaande pagina's is toegevoegd. Twee zinnen op de automatiseringspagina waren al onwaar toen hij live ging.

Niemand had een onwaarheid geschreven. Beide zinnen klopten tegen de tak waarop ze geschreven waren.

De zin die waar was toen hij geschreven werd

Documentatie voor een functie wordt meestal ná die functie geschreven, en dat betekent dat ze geschreven wordt terwijl andere takken nog openstaan. De onze ook. De pagina beschreef een meldnode en zei in feite dat die geen e-mail verstuurt. Tegen de tak waarvoor ze geschreven was klopte dat precies: de node schreef een panelmelding en er verliet niets het gebouw.

Een parallelle ronde werd eerder gemerged en gaf de node een e-mailvinkje, standaard uit, een eigen afmeldcategorie, en een regel dat een testrun nooit iets verstuurt. Elk van die feiten is interessant voor een lezer. Geen ervan stond op de pagina, en wat er wel stond vertelde hem nu het tegendeel.

De tweede zin beschreef hoe een plan aan een flow vastzit. Er stond dat het plan de flow erachter draait, uit een tijd waarin die verhouding één op één was. Dezelfde merge verving hem door een join: een plan mag hoogstens één flow per moment hangen, uit drie momenten, en een handmatig of via een webhook getriggerde flow kan daar helemaal niet hangen. "Kan niet gekoppeld worden" is een beter antwoord dan "gekoppeld en doet stilletjes niets", maar het is een ander antwoord, en de pagina gaf nog steeds het oude.

De reparatie was klein. Het interessante is hoe hij gevonden werd, namelijk doordat iemand er bewust naar ging zoeken: een ronde die een onderwerp aanraakt is het enige moment waarop iemand een reden heeft om het proza over dat onderwerp te herlezen.

Wat een bewaking wel kan vangen

Er is een tweede faalvorm op dezelfde pagina's, en anders dan de eerste is die te mechaniseren.

De dashboardpagina heeft een tabel met de kaarten die een gebruiker kan toevoegen. Die kaarten hebben namen, in negen talen, en die namen bestaan al: het zijn de opschriften in de kiezer waar de gebruiker werkelijk op klikt. Een documentatietabel schrijven betekent ze een tweede keer schrijven.

Het ging meteen mis, in het eerste concept, in het Engels:

In de kiezerOp de documentatiepagina
Integration listConnections
Open ticketsTickets
Credit balanceCredit

Geen van die drie is fout als Engels. Alle drie zijn ze fout als documentatie, want een lezer die te horen krijgt dat hij "Connections" moet toevoegen, gaat zoeken naar een kaart die Connections heet en vindt een kaart die Integration list heet. Het uiteenlopen is per constructie stil: allebei de teksten zijn op zichzelf prima, en niemand legt een handleiding naast een kiezer.

De tabel neemt daarom nu dezelfde catalogussleutels als de kiezer, en een test eist dat ze in alle negen talen woord voor woord gelijk zijn. De documentatiesleutel wordt afgeleid uit het kaart-id in plaats van met de hand opgesomd, zodat de zevende optionele kaart die iemand volgend jaar toevoegt gemeten wordt zonder dat iemand eraan hoeft te denken hem hier bij te zetten. Dit is dezelfde vorm als de bewaking die we tussen de twee kopieën van de Engelse servertekst draaien, en hij bestaat om dezelfde reden: twee plekken die één waarheid dragen hebben een test nodig die dat zegt, geen afspraak.

De knopnamen op diezelfde pagina waren in vijf van de negen talen gegokt. Ook die komen nu uit de catalogus. En drie talen hadden het woord Scripts vertaald, de naam van een menu-item dat in het product niet vertaald wordt, dus de pagina vertelde een Spaanse, Portugese en Oekraïense lezer dat ze op iets moesten klikken dat onder die naam niet bestaat.

Een technisch token is geen woord

Productnamen, poorten, paden, modulenamen en statuscodes gaan in een monospace-token en blijven Engels, waar ze ook staan, in elke taal. Die regel is niet nieuw. Nieuw was dat hem in deze pagina's uitschrijven met twee andere bewakingen tegelijk botste.

Een <code>-element letterlijk in een tabelrij-array zetten laat de lintregel afgaan die op elk JSX-element in een array een sleutel wil, ook hier, waar het tabelcomponent elke cel in een eigen element met sleutel wikkelt en die sleutel nooit gelezen wordt. Er wel een sleutel op zetten laat een andere bewaking afgaan, die een kind met sleutel ziet staan naast vertaalaanroepen waarvan ze de sleutels in dat bestand niet kan herleiden.

De uitweg was een functie van één regel die het element teruggeeft. Voor de lintregel is het een functieaanroep en geen array-element; voor de andere bewaking is het geen sleutel. De gerenderde uitvoer is byte voor byte gelijk. Het is een kleinigheid, en het is precies het soort kleinigheid dat met een disable-commentaar wordt opgelost zodra niemand opschrijft waarom de twee regels het oneens waren.

Screenshots die geslaagd leken

De meting voor deze pagina's bevatte ankerscreenshots: scroll naar elke sectie, fotografeer hem, kijk ernaar.

Negen ervan toonden de paginakop.

Het browsercommando dat een gebied buiten het kijkvenster vastlegt berekent zijn uitsnede vanaf de bovenkant van het document, niet vanaf de huidige scrollpositie. Scroll naar een anker acht schermen lager, vraag om een gebied op de coördinaten die het element meldt, en je fotografeert in plaats daarvan de bovenkant van de pagina, op precies de juiste maat, in een bestand met de juiste naam. Elk van die screenshots was een aannemelijk ogende afbeelding van het verkeerde ding.

De huidige scrollafstand erbij optellen loste het op. De algemene vorm komen we steeds tegen: een meting die faalt door normaal ogende uitvoer te produceren is erger dan een die omvalt, want een crash wordt dezelfde dag nog onderzocht.

Het deel waar geen bewaking bij komt

De kaartnamen waren te mechaniseren omdat beide kanten tekenreeksen in één repository zijn. De twee verouderde zinnen waren dat niet, en het is de moeite waard precies te zijn over waarom, want het is verleidelijk te geloven dat er voor elk documentatieprobleem een test klaarligt om geschreven te worden.

Een zin die zegt dat een node geen e-mail verstuurt is een bewering over gedrag dat over vier bestanden verspreid ligt, een standaardwaarde, een vinkje en een categorielijst. Er is geen uitdrukking waarmee je hem kunt vergelijken. Het enige mechanisme dat hem zou vangen is een test die het gedrag rendert en de zin leest, en dat is een test die per zin geschreven moet worden, door iemand die al weet dat de zin fout is.

Wat we in plaats daarvan deden was goedkoper en verdient het als werkwijze benoemd te worden: toen de correctie gemaakt werd, is de hele documentatiedeelboom doorzocht op elke andere bewering over e-mail en elke andere bewering over een flow per plan. Er was geen derde plek. Dat is een uitkomst en geen formaliteit. Zonder die zoektocht had de ronde twee zinnen gerepareerd en de lezer achtergelaten met het redelijke geloof dat de pagina gecontroleerd was.

Diezelfde discipline bestaat elders in dit project al voor een ander paar: onze lange artikelen kunnen verouderen ten opzichte van de lijst met welke integraties live staan, en er wordt niets rood als dat gebeurt. Twee artikelen zeiden ooit zes weken lang dat twee hypervisors op de routekaart stonden terwijl ze allebei al draaiden. De regel die daaruit kwam is dezelfde: verandert een ronde de status van iets, grep dan het proza op zijn naam.

Wat we zouden opschrijven

  1. Proza over code is een ongetoetste bewering. Niets in de build leest het. Dat is prima, zolang iedereen dat weet en niemand aanneemt dat een groene run iets over de alinea zegt.
  2. Documentatie wordt tegen een tak geschreven, niet tegen main. Staan er andere rondes open, dan is de pagina een momentopname van een toestand die misschien nooit live gaat. Herlees haar ná de merge, niet ervoor.
  3. Een naam die in het product bestaat hoort gelezen te worden, niet overgetypt. Drie van de zes kaartnamen liepen al in het eerste concept uiteen. In negen talen is dat een foutsoort en geen ongeluk.
  4. Leid de documentatiesleutel af uit het id. Dan is de volgende kaart gedekt zonder dat iemand deze regel onthoudt.
  5. Een gegokt woord in een taal die je niet leest is onzichtbaar. Vijf talen hadden knopnamen gegokt en er was niets rood.
  6. Een productnaam vertalen is een kapotte instructie. Zegt het menu in elke taal Scripts, dan zegt de handleiding in elke taal Scripts.
  7. Botsen twee lintregels, schrijf dan op welke je gehoorzaamde en waarom. Het alternatief is een disable-commentaar dat later niemand kan wegen.
  8. Een meting die bij falen aannemelijke uitvoer geeft wordt niet in twijfel getrokken. Fotografeer iets dat je kunt herkennen, en kijk naar de foto's.

Voor de duidelijkheid over wat dit is: beide pagina's staan live in negen talen, de twee verouderde zinnen zijn in alle negen gecorrigeerd, en de bewaking op de kaartnamen zit in de suite en is rood bewezen voordat hij groen bewezen werd. De beweringen op de pagina's komen uit het lezen van de code en niet uit het draaien ervan; het curl-voorbeeld op de automatiseringspagina is niet op een levend endpoint afgevuurd; en elke vertaling heeft één lezer gehad, geen twee.

Uit het platformwerk aan Provibr. De kaarten waar die namen naar verwijzen staan in een snelkoppeling is een verwijzing, geen recht, en wat negen catalogi kosten om eerlijk te houden staat in zestienduizend sleutels, negen talen.

Begin met één host en één agent

Maak een account aan, installeer de agent met één commando en koppel je eerste Proxmox-host. De proefperiode loopt 14 dagen en vraagt geen betaalgegevens.