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 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
 * The interface is the exposed functions from the module, that is the functions you can invoke from the parser function. As a minimum document whatever arguments the interface function takes, and whatever value it returns. Only a single value is used from whatever the function returns. Remember to document if and how the metafunction  will transform the value.


 * 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.


 * Sitattegn for strenger
 * In Lua there are several types of string quotes. Pick one of them and stick with it. If you need several types of quotes, either use your typical quote at the outermost level or at the innermost, and work your way out. Inside out with single quote as the primary quote and double quotes as secondary seems to be common, but could simply accidental. If more quotes are necessary, then start using double square brackets at the ternary level.


 * 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
 * In languages with an  operator like in Lua it is very easy to provide defaults. This is nice as some common constructs fails badly if given an uninitialized value. This happen for example when a table is unitialized and the code tries to index the nil value.
 * {| class="wikitable mw-collapsible mw-collapsed"
 * In languages with an  operator like in Lua it is very easy to provide defaults. This is nice as some common constructs fails badly if given an uninitialized value. This happen for example when a table is unitialized and the code tries to index the nil value.
 * {| 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"
 * }
 * Unngå repeat…until
 * The loop construct  delays the test until after the loop. This is error prone and should be avoided. The only times this is acceptable is when the test itself is costly compared to the executed block, or avoiding the repeat-clause would imply additional cleanup or finalize code.
 * Unngå repeat…until
 * The loop construct  delays the test until after the loop. This is error prone and should be avoided. The only times this is acceptable is when the test itself is costly compared to the executed block, or avoiding the repeat-clause would imply additional cleanup or finalize code.


 * Test argumenter
 * There is a small utility libraryUtil to test arguments types, and it should be used to avoid simple mistakes. 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
 * The single most common software pattern in Lua modules, that is most commonly missing, is the command pattern. Some data is available, and some action should be chosen given this data. A typical smell that a command pattern is missing is long chains of if-then-elseif-end tests. The most common variant does not have named commands, but an accept-qualifier function. Both versions are very common in parsing arguments from the "invoke" parser function.
 * {| 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
 * There are usually several execute paths through a given code, and this makes the code difficult to understand. The more code paths the more difficult the code become. This can be measured as cyclomatic complexity, and is a count of paths by counting branch points. This gives a fair, but not very good measure on code quality.


 * 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.

Se også

 * Lua referansemanual

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