Help:Lua/Lua best practice/nb

Som enhver «beste praksis», så er denne Lua beste praksis tungt påvirket av enhver individuell bidragsyters mening om hva som bør være en god praksis. Bruk det du mener er viktig for ditt spesifikke prosjekt, men vit også at disse reglene har vist at de virker!

Eksemplene i det etterfølgende er for Lua, men de bør være enkle å reformulere for JavaScript, PHP, og Python. Grunnen for å gi eksempler for Lua er at modulene for dette språket er brukt mye, ofte av ikke-programmerere som ikke ser konsekvensene av sine valg.

Som et generelt råd så kan det være til stor hjelp å importere koden i et skikkelig programmeringsmiljø og sjekke det der for åpenbare feil og mangler. Flere frie alternativ eksisterer, blant dem Eclipse, TextMate, og Visual Studio Code for nevne noen få.

Spesielt, bruk et verktøy slik som lualint or luacheck. Det siste er noe bedre. Sjekk også om det er verktøy for deteksjon av rot og andre analyser tilgjengelig for ditt programmeringsmiljø.

Husk; konsisten stil er viktigere enn den «riktige» stilen – selv om det er stilen som du foretrekker!

Navn

 * Beskrivende navn
 * Velg beskrivende navn, unngå alt for generiske navn slik som  hvis ikke din kode virkelig er generisk. Ikke repeter en beskrivelse over flere nivåer, slik som et metodenavn som er satt til det samme som et klassenavn, hvis ikke metoden faktisk returnerer en klasse av den typen. Tenk fargerike ord, som er mer beskrivende ved større scope, men fjern unødige ord.


 * Kortnavn
 * Kryptiske kortnavn bør unngås. Skriv ut navnene, men vær konsistent. Ikke skriv, si isteden   eller  . Du kan ofte reformulere kortnavn og fortsatt gjøre dem korte, slik som   og.


 * Iteratornavn
 * Iteratorer har vanligvis kortnavn i Lua, og navnene har spesiell mening. Dette er i motsetning til korte navn, og kan skape problemer hvis flere nøstede løkker skal bruke de samme navnene. En vanlig løsning er å legge til en ekstra del som prefiks eller suffiks til navnet, vanligvis fra flertallsformen brukt på samlingen, eller å bruke en entallsform av navnet på samlingen.


 * Navn med type
 * Lua har et ganske svakt typesystem, selv om det kan se sterkt ut på noen områder. Argumenter må enten bli tvunget til riktig type, eller så må funksjonen kaste en feilmelding. Hvis funksjonen finnes i spesielle utgaver for å håndtere forskjellige typer, så bør det være del av funksjonens navn.


 * Akronymer som navn
 * Akronymer er skremmende for de som ikke kjenner deres mening. Ikke bruk dem med mindre det er helt enkle og åpenbare tilfeller. I et bibliotek for å lage HTML-markup kan  være akseptabelt, men i et bibliotek for å lage infobokser kan det samme være uønsket.


 * Format for navn
 * Formatering av navn bør følge konvensjonen på det faktiske prosjektet. Lua bruker flere formateringsregler, men i Wikimedia virker det som UpperCamelCase for klassenavn, og lowerCamelCase for fuksjoner, metoder og variabelnavn. Modulnavn ser ut som de blir tolket som variabelnavn. Det er ikke noen klar praksis for konstanter, men UPPER_CASE_EMBEDDED_UNDERSCORE ser ut som et godt forslag.


 * Enkel understrek
 * I Lua-kode brukes en enkelt understreking som navn når et må angis, men ikke blir brukt. Dette er en placeholder som ellers blir ignorert. Dette respekteres av noen lintverktøy, og bør også respekteres i ordinær kode.


 * Innledende understrek
 * Ved konvensjon så brukes det en innledende understreking for navn som skal være private, men som av en eller annen grunn må være tilgjengelige fra utsiden. Variable med slike navn bør behandles som private uansett hva som har definert dem, hvis ikke de har en veldig klar forklaring som sier at du kan utføre spesifikke operasjoner på dem.

Formatering

 * Begrens linjelengde
 * Linjer bør begrenses til en rimelig lengde, typisk rundt 80 tegn. Årsaken er at lange linjer er vanskelige å lese, og når de blir lengre, så har de en tendens til å innkludere flere sammenblandede konsepter, og redigering av dem vil lett skape nye feil.


 * Innrykk av nye linjer
 * Programmerere har meninger om hvordan innrykk av nye linjer skal gjøres. Uansett hva slags mening du har, husk at dugnadsprosjekter bør følge noen felles standarder. Vær oppmerksom på at mens en tab ser ut som 4 mellomrom i online-editoren, vises den ikke slik i normal visning. Fordi nettverktøyet gjør innrykk på bestemte måter, bør du sette ditt programmeringsmiljø på samme måte.


 * Binære og linjebrekk
 * Noen ganger er det nødvendig å sette inn et linjeskift i et uttrykk, vanligvis et if-clause. Dette skaper et spesielt problem, da det åpner for kopi-lim induserte feil. For å unngå problemer kan et enkelt formateringstriks brukes, sett den binære logiske operatøren foran uttrykket på en ny linje.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Mellomrom
 * Mellomrom er vanligvis en GodTing™, men mennesker bruker på å bli uenige om hvordan det skal brukes. Gjort riktig så øker det vanligvis lesbarhetene til din kode, men gjort feil så blir din kode vanskelig å lese. Finn en stilguide og hold deg til den. Eller bruk et verktøy.
 * Mellomrom
 * Mellomrom er vanligvis en GodTing™, men mennesker bruker på å bli uenige om hvordan det skal brukes. Gjort riktig så øker det vanligvis lesbarhetene til din kode, men gjort feil så blir din kode vanskelig å lese. Finn en stilguide og hold deg til den. Eller bruk et verktøy.

Dokumentasjon

 * Grensesnitt&shy;dokumentasjon
 * Grensesnittet er de tilgjengelige funksjonene fra modulen, det vil si de funksjonene du kan kalle opp fra parserfunksjonen. Som et minimum dokumenter hvilke argumenter grensesnittsfunksjonen tar, og hvilke verdier den returnerer. Parserfunksjonen vil bare bruke en enkelt returverdi, uansett hva funksjonen returnerer. Husk å dokumentere om og hvordan metafunksjonen  vil omdanne returverdien.


 * Oversiktsdokumentasjon
 * Dokumentasjonen skal ha en oversikt som gir en generell forklaring på hvorfor og hvordan modulen, funksjonen eller variabelen er slik den er. Dette er ikke bare den tiltenkte oppførselen, det er hvorfor funksjonen er slik den er.


 * Annotering av parametre
 * Hver parameter skal være korrekt beskrevet. Det vil si, den forventede typen skal angis, og en kort beskrivende streng. Skriv som om LDoc eller et lignende verktøy er tilgjengelig, vanligvis som.


 * Annotering av retur
 * Hver returverdi skal være korrekt beskrevet. Det vil si, den forventede typen skal angis, og en kort beskrivende streng. Skriv som om LDoc eller et lignende verktøy er tilgjengelig, vanligvis som.

Kommentarer
Inline kommentarer for selve koden.


 * Hvorfor-form på kommentarer
 * Kommentarer er ikek for deg som koder en eller annen algoritme, de er for den som leser din kode. I kode-stien bør det være svar på alle hvordan-spørsmålene, og i kommentarene bør det være svar på alle hvorfor-sprørsmålene. Ikke gjør feilen å gjenta kode-stien i kommentarene, gode kommentarer skal gi ny innsikt i koden.


 * Fortell din hensikt
 * Si hva som er formålet med koden, med et klart og presist språk. Ikke bare skriv en masse ord, tenk på leseren, hva hun trenger for å forstå din kode.


 * Refaktor utfra kommentarer
 * Når kode har blitt for komplisert, så er det ikke uvanlig å starte å forklare koden for deg selv. Hvis du trenger dine egne kommentarer, da har noe blitt for vanskelig og du bør refaktorere koden.


 * Kommentarer om dårlige navn
 * En kommentar som sier at et navn er dårlig på noe vis hjelper ikke. Ikke kommenter på dårlige navn, rett dem!


 * «Todo» kommentarer
 * Markøren todo er en av flere vanlig markører, og kan tolkes som "kode som programmereren ikke har nådd å fikse enda". Vanligvis bør du skrive dette som.


 * «Fixme» kommentarer
 * Markøren fixme er en av flere vanlig markører, og kan tolkes som "kode som andre enn programmereren har identifisert som feilende". Vanligvis bør du skrive dette som . Dette er en invitasjon til andre om å forsøke å rette koden.


 * «Hack» kommentarer
 * Markøren hack er en av flere vanlig markører, og kan tolkes som "kode som andre enn programmereren har identifisert som feilende og har forsøkt rettet på en uelegant måte". Vanligvis bør du skrive dette som . Dette er en invitasjon til andre om å forsøke å rette koden.


 * «XXX» kommentar
 * Markøren xxx er en av flere vanlig markører, og kan tolkes som "kode er identifisert som farlig ødelagt". Vanligvis bør du skrive dette som . Denne markøren skal ikke være i produksjonskode, koden bør fikses asap.


 * Kommenter magiske tall
 * Konstanter og andre magiske tall bør ha kommentarer som forklarer hvorfor de har et spesifikt innhold. Hvorfor er linjelengden satt til 80 tegn? Hvorfor er π forkortet til 3,14?

Kode
Små mønstre og kodepraksis.


 * Programvaremønstre
 * Mye arbeid har gått i å identifisere felles programvaremønstre, og utvikle gode generelle løsninger for disse mønstrene. Hvis du mistenker at du forsøker å gjøre noe som har et felles mønster, så gjør et søk og sjekk ut hvordan du implementerer mønsteret. Likevel, vær klar over at mønstre for språk med closure kan være svært forskjellige fra de uten closure. Vanligvis brukes det tabeller i Lua for å lage objekter, men de kan også skapes med closures. If you suspect you are attempting to do something that has a common pattern then do a search and check out how to implement the pattern. Still, know that patterns for languages with closures can be very different from those without closures. Usually tables are used in Lua to create objects, but they can also be created as closures.


 * Sitattegn for strenger
 * I Lua finnes det flere typer anførselstegn for strenger. Velg en av dem og hold deg til den. Hvis du trenger flere typer anførselstegn, kan du enten bruke det vanligste anførselstegnet på det ytre nivået eller det innerste, og jobbe deg utover. Innenfra og ut enkelt anførselstegn som det primære anførselstegnet og doble anførselstegn som det sekundære synes å være vanlig, men det kan være tilfeldig. Hvis flere anførselstegn er nødvendige, så begynn å bruke doble firkantparenteser på ternært nivå.


 * Tidlig retur
 * Returner så tidlig som mulig, spesielt hvis noe feiler. Vanligvis er programmerere fortalt at de skal bruke et enkelt returpunkt, men på grunn av språkkonstruksjonene i Lua så virker det som om dette skaper dypt nøstet kode. Det er derfor bedre å returnere tidlig.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Unngå «else»
 * Alle betingelser kan bli skrevet slik at eksplisitte else-betingelser forsvinner. Alle av dem. Men noen ganger gjør else-betingelser at koden enklere å lese eller gjør at doble sett av if-betingelser kan unngås. I de tilfellene så er det akseptabelt å beholde, ellers bør den fjernes. Vær alltid mistenksom med else-betingelser.
 * Unngå «else»
 * Alle betingelser kan bli skrevet slik at eksplisitte else-betingelser forsvinner. Alle av dem. Men noen ganger gjør else-betingelser at koden enklere å lese eller gjør at doble sett av if-betingelser kan unngås. I de tilfellene så er det akseptabelt å beholde, ellers bør den fjernes. Vær alltid mistenksom med else-betingelser.


 * Sanne uttrykk først
 * Vanligvis er du fri til å ordne then- og else-betingelser slik det passer best, og da bør du organisere dem slik at if-betingelsen har en positiv test. Dette gjør at at koden blir enklere å lese. Hvis du kan unngå else-betingelsen så er det imidlertid viktigere.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Spør først
 * Vanligvis plasseres den spurte verdien først i et logisk uttrykk, da dette er mer naturlig å lese og dermed er mindre utsatt for feil. Den omvendte formen kalles noen ganger for Yoda-formen. Noen ganger (men sjeldent) fungerer ikke den naturlige formen som forventet, og koden terminerer. Dette kan skyldes at Lua feiler i å finne den riktige hale-rekursive formen til uttrykket, og deretter får en stack overflow.
 * {| class="wikitable mw-collapsible mw-collapsed"
 * Vanligvis plasseres den spurte verdien først i et logisk uttrykk, da dette er mer naturlig å lese og dermed er mindre utsatt for feil. Den omvendte formen kalles noen ganger for Yoda-formen. Noen ganger (men sjeldent) fungerer ikke den naturlige formen som forventet, og koden terminerer. Dette kan skyldes at Lua feiler i å finne den riktige hale-rekursive formen til uttrykket, og deretter får en stack overflow.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Angi standardverdi
 * På språk med en  operator som i Lua, er det veldig enkelt å angi standardverdier. Dette er fint da noen vanlige konstruksjoner feiler grovt hvis de får en uinitialisert verdi. Dette skjer for eksempel når en tabell er uinitialisert og koden forsøker å indeksere nil-verdien.
 * {| class="wikitable mw-collapsible mw-collapsed"
 * På språk med en  operator som i Lua, er det veldig enkelt å angi standardverdier. Dette er fint da noen vanlige konstruksjoner feiler grovt hvis de får en uinitialisert verdi. Dette skjer for eksempel når en tabell er uinitialisert og koden forsøker å indeksere nil-verdien.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Binær betingelse
 * Lua har ikke en binær betinget operator, men du kan likevel gjøre det samme med en . Det som skjer er nok litt litt merkelig for nybegynnere i Lua. Operatorene   og   overfører sannhetsverdier (mmaterielle verdier), og dermed kan de være en del av andre uttrykk enn bare logiske.
 * {| class="wikitable mw-collapsible mw-collapsed"
 * Lua har ikke en binær betinget operator, men du kan likevel gjøre det samme med en . Det som skjer er nok litt litt merkelig for nybegynnere i Lua. Operatorene   og   overfører sannhetsverdier (mmaterielle verdier), og dermed kan de være en del av andre uttrykk enn bare logiske.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Trinær betingelse
 * Lua har ikke en trinær betinget operator, men du kan likevel gjøre det samme med en  og en  . Det som skjer er nok litt litt merkelig for nybegynnere i Lua. Operatorene   og   overfører sannhetsverdier (mmaterielle verdier), og dermed kan de være en del av andre uttrykk enn bare logiske.
 * {| class="wikitable mw-collapsible mw-collapsed"
 * Lua har ikke en trinær betinget operator, men du kan likevel gjøre det samme med en  og en  . Det som skjer er nok litt litt merkelig for nybegynnere i Lua. Operatorene   og   overfører sannhetsverdier (mmaterielle verdier), og dermed kan de være en del av andre uttrykk enn bare logiske.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Note that the form  where b is falsy will give c as outcome. That may not be the expected behavior.
 * }
 * Note that the form  where b is falsy will give c as outcome. That may not be the expected behavior.


 * Unngå repeat…until
 * Loop-konstruksjonen  forsinker testen til etter loopen. Dette medfører lett feil og bør unngås. De eneste gangene dette er akseptabelt, er når testen selv er kostbar i forhold til den utførte blokken, eller hvis man ved å unngå repetisjonsklausulen vil utløse ytterligere kode for opprydding eller avslutning.


 * Test argumenter
 * Det er et lite verktøy libraryUtil for å teste typen til argumenter, og dette bør brukes for å unngå enkle misforståelser. Ofte er argumentene gyldige når andre koder er korrekte, men i grensetilfeller skaper noe et kall utenfor det forventede typeområdet, og koden feiler på mystiske vis. Riktig testing kan fange en feil tidlig, og øke sannsynligheten for å oppdage den virkelige årsaken. Vær oppmerksom på at type testing er en test for fail, og ikke en test for korrekthet. Often the arguments are valid when other code is correct, but in fringe cases something creates a call outside the expected type range and the code fails in mysterious ways. Proper testing might catch an error early, and increase the probability of discovering the real root cause. Still note that type testing is a test for failure, and not a test for correctness.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * }
 * }

Mønstre
Noen få veldig vanlige programmeringsmønstre.


 * Kommandomønster
 * Det vanligste programvaremønsteret i Lua-moduler, det vil si det som vanligvis mangler, er command pattern. Noen data er tilgjengelige, og en aksjon bør velges gitt disse dataene. En typisk smell (lukt) som om at et command pattern mangler er lange kjeder av if-then-elseif-end -tester. Den vanligste varianten har ikke navngitte kommandoer, men en aksept-kvalifiseringsfunksjon. Begge versjonene er svært vanlige når en analyserer argumenter fra "invoke" parserfunksjonen.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example
 * }
 * }
 * }
 * }
 * }

Testbarhet
Om testing og hvordan du gjør koden testbar. Vær oppmerksom på at den opprinnelige boken fra firergjengen har programmeringsmønstre for sterkt typede språk, som ikke passer svakt typede språk særlig godt. Hvorvidt Lua er sterkt typet, eller svakt, kan debatteres.


 * Kompleksitet
 * Det er vanligvis flere kjøreveier gjennom en gitt kode, og dette gjør koden vanskelig å forstå. Desto flere kodeveier desto vanskeligere blir koden. Dette kan måles som cyclomatic complexity, og gir et tall på veier ved å telle grenpunkter. Dette gir et rettferdig, men ikke veldig godt mål på kodekvalitet.


 * Unngå globale
 * Funksjoner med globale er vanskelige å teste, uansett hvordan globalene er inkludert i koden. For å unngå denne uheldige feilen så kan biblioteker inkluderes for å sjekke modulen, slik som . Vær oppmerksom på at requiring kode er som å importere en global, så vær forsiktig så du ikke skaper et større problem.
 * {| class="wikitable mw-collapsible mw-collapsed"

!colspan="2"|Example !Good !Bad
 * - valign="top"
 * }
 * Unngå å endre scope
 * I Lua er det mulig å sjekke omfanget av en funksjon. Ikke gjør det, da funksjonen blir avhengig av «mini-globals», som er nesten like ille som globals. Hvis alt fungerer som det skal, så vil mini-globalene trolig være semi-konstante, men det er ikke garantert.
 * Unngå å endre scope
 * I Lua er det mulig å sjekke omfanget av en funksjon. Ikke gjør det, da funksjonen blir avhengig av «mini-globals», som er nesten like ille som globals. Hvis alt fungerer som det skal, så vil mini-globalene trolig være semi-konstante, men det er ikke garantert.

Sikkerhet
Lua kjører i en form for sandkasse-miljø, du kan si at Lua-koden eksekveres i en demilitarisert sone på utsiden av den vanlige tjeneren, hvor kun noen få kall passerer gjennom veggen og disse bør grundig valideres av den interne koden. Generelt bør det ikke være noen grunn til å ta spesielle forhåndsregler for å gjøre koden sikker, fordi resultatet fra utførelsen av koden vil passere gjennom grundig vasking og escaping før det blir inkludert på siden.

Programmeringsmiljø
Noen råd om hvordan du konfigurerer ditt eksterne programmeringsmiljø.

Visual Studio Code
Bruk noe ala de følgende utvidelsene.


 * Lua
 * vscode-luacheck
 * Denne trenger en fil  med en enkelt linje , ellers vil den klage mye på den globale   variablen.
 * Lua snippets for Wikimedia

Andre verktøy
Dette er verktøy du kan finne nyttig.
 * GitHub: LuaDist/luametrics

Lesing

 * Kerievsky, Joshua; Refactoring to Patterns
 * Boswell, Dustin; Foucher, Trevor; The Art of Readable Code
 * Stefanov, Stoyan; JavaScript Patterns
 * Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John; Design Patterns: Elements of Reusable Object-Oriented Software
 * Programming in Lua (5.0)
 * Lua 5.1 Reference Manual
 * LuaUsers: Sample Code
 * PEP 8 -- Style Guide for Python Code
 * LuaUsers: Lua Style Guide
 * The Power of Ten – Rules for Developing Safety Critical Code