Jump to content

Help:Lua/Lua best practice/nl

From mediawiki.org
This page is a translated version of the page Help:Lua/Lua best practice and the translation is 100% complete.

Zoals elke beste aanpak, wordt deze Lua beste aanpak sterk beïnvloed door de indruk van individuele bijdragers over wat een goede aanpak in de praktijk zou zijn. Gebruik wat u denkt dat belangrijk is voor uw specifieke project, maar weet ook dat deze regels werken!

De voorbeelden in het volgende zijn voor Lua, maar ze zouden makkelijk te herformuleren moeten zijn voor JavaScript, PHP en Python. De reden om voorbeelden voor Lua te geven is dat modules voor deze taal veel worden gebruikt, vaak door niet-programmeurs die de gevolgen van hun keuzes niet zien.

Een algemeen advies is dat het erg helpen om de code te importeren in een goede programmeeromgeving en daar te controleren op duidelijke fouten. Er bestaan verschillende gratis opties, waaronder Eclipse, TextMate, en Visual Studio Code om er een paar te noemen.

Gebruik vooral een lint hulpmiddel zoals lualint of luacheck. De laatste is iets beter. Controleer ook of er voor uw programmeringsomgeving hulpmiddelen voor het detecteren van storingen of andere analyses beschikbaar zijn.[1][2]

Onthoud: een consistente stijl is belangrijker dan de "juiste" stijl - zelfs als die stijl de beste is![3]

Namen

Beschrijvende namen
Kies beschrijvende namen, vermijd te generieke namen zoals get() tenzij uw code echt generiek is. Herhaal een beschrijving niet op meerdere niveaus, zoals een methodenaam die op hetzelfde is gezet als de naam van een class, tenzij de methode daadwerkelijk een class van dat type teruggeeft. Denk aan 'kleurrijke' woorden, meer beschrijvend voor grotere scopes, maar gooi overbodige woorden weg.[4]
Korte namen
Cryptische korte namen moeten worden vermeden. Schrijf de namen uit, maar blijf beknopt. Gebruik niet tmp_t, zeg in plaats daarvan temporaryTable of temporary_table. Vaak kan men de korte namen opnieuw formuleren en ze nog steeds kort houden, zoals entiteitenen categories. Gebruik bijvoorbeeld een naam met meervoud voor tabellen met verschillende waarden.[5]
Iterator namen
Iterators hebben meestal korte namen in Lua, en de namen hebben een speciale betekenis. Dit gaat in tegen korte namen en kan problemen veroorzaken als meerdere geneste lussen dezelfde namen gebruiken. Een veelgebruikte oplossing is het voorvoegen of achtervoegsel van een extra deel aan de naam, meestal uit de meervoudsvorm die door de collectie wordt gebruikt, of om een enkelvoud van de naam van de collectie te gebruiken.[6]
Namen met types
Lua heeft een vrij zwak type systeem, zelfs al lijkt het dat het sterk is op sommige delen. Argumenten moeten ofwel worden gedwongen tot het juiste type, of de functie moet een fout geven. Als de functie bestaat in speciale incarnaties om verschillende soorten te behandelen, dan moet dat onderdeel zijn van de functienaam.[7]
Acroniemen als namen
Acroniemen zijn intimiderend voor degenen die hun betekenis niet weten. Gebruik ze niet tenzij het de eenvoudigste en meest voor de hand liggende geval is. In een bibliotheek voor het maken van HTML-markering kan td() aanvaardbaar zijn, maar in een bibliotheek voor het maken of het maken van infoboxen kan hetzelfde niet aanvaardbaar worden.[8]
Formaat namen
De opmaak van namen moet de conventie van het daadwerkelijke project volgen. Lua gebruikt als zodanig verschillende opmaakstijlen, maar in Wikimedia-projecten lijkt het UpperCamelCase voor class-namen, en lowerCamelCase voor functie-, methode- en variabelenamen. Modulenamen lijken te worden geïnterpreteerd als variabelenamen. Er is geen duidelijke praktijk voor constanten, maar UPPER_CASE_EMBEDDED_UNDERSCORE lijkt me een verstandige keuze.[9]
Enkel liggend streepje
In Lua-code wordt een naam met een enkel liggend streepje gebruikt waar een naam moet worden opgegeven, maar deze wordt niet gebruikt. Dat wil zeggen, het is een placeholder die anders genegeerd wordt. Dit wordt erkend door sommige lint hulpmiddelen en moet ook worden gerespecteerd in gewone codes.[10][11]
Liggend streepje vooraan
Bij conventie wordt een liggend streepje vooraan gebruikt voor namen die enigszins privé zijn, maar om een of andere reden moeten worden geplaatst zodat het van buitenaf toegankelijk is. Variabelen met dergelijke namen moeten worden behandeld als privé voor wat ze ook definieert, tenzij ze een zeer duidelijke verklaring hebben die zegt dat u bepaalde specifieke operaties kunt doen op hen.[12][13]

Opmaak

Limiet regellengte
Regels moeten beperkt worden tot een redelijke lengte, meestal rond de 80 tekens. De reden is dat lange regels moeilijk te lezen zijn, en naarmate ze langer worden, bevatten ze vaak meer verstrengelde concepten, en het bewerken ervan zal nieuwe bugs veroorzaken.[14]
Inspringen bij nieuwe regels
Programmeurs hebben meningen over hoe men het inspringen van nieuwe regels kunt doen. Wat u ook van mening bent, onthoud dat projecten die door het publiek worden gedaan, aan enkele gemeenschappelijke normen moeten voldoen. Let op dat hoewel een 'tab' er in de online editor uitziet as 4 ruimtes, het niet zo verschijnt in de normale weergave. Omdat de online editor op specifieke manieren aan inspringing doet, moet u uw programmeeromgeving zo instellen dat ze zich zo gedraagt.[15][16]
Tweedelige componenten en regelafbrekingen
Soms is het nodig om een regelovergang in een expressie te plaatsen, meestal een if-clausule. Dit is een bijzonder probleem, aangezien er fouten ontstaan die door kopie-plak worden veroorzaakt. Om problemen te voorkomen kan een eenvoudige opmaak trucs worden gebruikt, gewoon de logische binaire operator voor het deel op een nieuwe regel.[17]
Example 
Good Bad
if long_statement_A
    and long_statement_B
    and long_statement_C
then
    
if long_statement_A and
    long_statement_B and
    long_statement_C then
    
Witruimte
Witruimte is meestal een goede zaak™, maar mensen zijn het vaak oneens over hoe men het moet gebruiken. Als menhet goed doet, verhoogt het de leesbaarheid van de code, maar als men het fout doet, kan de code erg moeilijk te lezen zijn. Zoek een stijlgids en houd u eraan. Of gebruik een hulpmiddel.[18]

Documentatie

Interface documentatie
De interface heeft de openbare functies van de module, dat wil zeggen de functies die u kunt invoeren van de parserfunctie. Als minimaal document, welke argumenten de interfacefunctie neemt en welke waarde het teruggeeft. De parserfunctie zal slechts één waarde teruggeven, ongeacht wat de functie teruggeeft. Vergeet niet om te documenteren of en hoe de metafunctie __tostring de waarde zal transformeren.
Overzicht documentatie
De documentatie moet een overzicht hebben om een algemene verklaring te geven van waarom en hoe de module, functie of variabele is zoals ze is. Dit is niet alleen het beoogde gedrag, het is de reden waarom het gedrag is zoals het is.
Parameter uitleg
Elke parameter moet correct worden uitgelegd. Dat is het verwachte type dat gegeven moet worden en een korte beschrijvende tekst. Schrijf het alsLDoc of een vergelijkbaar hulpmiddel beschikbaar is, meestal als -- @param type optionele tekst.
Retourwaarde uitleg
Elke retourwaarde moet correct worden uitgelegd. Dat is het verwachte type dat gegeven moet worden en een korte beschrijvende tekst. Schrijf het als LDoc of een vergelijkbaar hulpmiddel beschikbaar is, meestal als -- @return type optionele tekst.

Commentaar

Inline commentaar voor de code zelf.

Waarom-vorm van commentaar
Commentaar is niet alleen voor u als de persoon die het programma heeft geschreven, maar ook voor degenen die uw code lezen. In het codepad moeten antwoorden staan op de hoe-vragen en in het commentaar moeten antwoorden staan op de waarom-vragen. Maak niet de fout de tekst in het codepad te herhalen in het commentaar, goed commentaar geeft een nieuw inzicht in de code.[19]
Geef uw bedoeling aan
Geef de bedoeling van uw code, in een duidelijke en precieze taal. Voeg niet alleen veel woorden toe, denk aan de lezer, wat moet die weten om de code te begrijpen.[20]
Commentaar opnieuw schrijven
Wanneer de code complex is geworden, is het gebruikelijk om de code te verklaren om uzelf te helpen. Als u uw eigen opmerkingen nodig heeft, is er iets te ingewikkeld geworden en moet u de code refactoren.[21]
Commentaar op slechte namen
Een opmerking dat een naam in zekere zin slecht is, helpt niet. Geef geen commentaar, maar maak ze goed![22]
Commentaar "Todo"
De tekst todo is een van de veelvoorkomende en kan worden geïnterpreteerd als "code die de programmeur nog niet heeft opgelost". Meestal moet u het schrijven als -- @todo optionele string.[23]
Commentaar "Fixme"
De tekst fixme is een van de veelvoorkomende en kan worden geïnterpreteerd als "code die iemand anders dan de programmeur als kapot heeft geïdentificeerd". Meestal moet u het schrijven als -- @fixme optionele string. Dit is een uitnodiging aan anderen om te proberen de code te verbeteren.[24]
Commentaar "Hack"
De tekst hack is een van de veelvoorkomende en kan worden geïnterpreteerd als "code die iemand anders dan de programmeur als kapot heeft geïdentificeerd en op een minder elegante manier heeft proberen te verbeteren". Meestal moet u het schrijven als -- @fhack optionele string. Dit is een uitnodiging aan anderen om te proberen de code te verbeteren.[25]
Commentaar "XXX"
De tekst xxx is een van de veelvoorkomende en kan worden geïnterpreteerd als "code geïdentificeerd als gevaarlijk gebroken". Meestal moet u het schrijven als -- @xxx optionele string. Deze tekst hoort niet in productiecode te staan, de code moet zo snel mogelijk worden verbeterd.[26]
Commentaar op magische getallen
Constanten en andere magische getallen moeten opmerkingen bevatten die uitleggen waarom ze de specifieke inhoud hebben. Waarom is de regellengte ingesteld op 80 karakters? Waarom is π ingesteld als 3,14?[27]


Code

Kleine patronen en het coderen in de praktijk.

Software ontwerppatronen
Er is veel werk gestoken in het identificeren van veelvoorkomende software ontwerppatronen en het ontwikkelen van goede algemene oplossingen voor die patronen. Als u vermoedt dat u iets probeert te doen dat een gemeenschappelijk patroon heeft, doe dan een zoekopdracht en bekijk hoe u het patroon kunt implementeren. Toch moet u weten dat patronen voor talen met closures heel anders kunnen zijn dan die zonder' closures. Meestal worden tabellen in Lua gebruikt om objecten te maken, maar ze kunnen ook als closures worden gemaakt.[28][29][30]
Aanhalingstekens
In Lua zijn er verschillende soorten aanhalingstekens. Kies er een en blijf erbij. Als u verschillende soorten quotes nodig heeft, gebruik dan uw typische aanhalingsteken op het buitenste niveau of op het meest binnen niveau en werk ze uit. Binnen en buiten met een enkele aanhalingsteken als primaire aanhalingsteken en dubbele aanhalingstekens als secundaire lijkt veel te zijn, maar kan gewoon toevallig zijn. Als er meer aanhalingstekens nodig zijn, moet u op het derde niveau met dubbele vierkante haken beginnen.[31][32]
"Return" vroeg
Doe de "return" zo snel mogelijk, vooral als er iets misgaat. Meestal wordt de programmeur verteld om bij een "return" te blijven, maar vanwege de taalconstructies in Lua lijkt dit een diep verneste code te creëren. Het is dus beter snel een "return" te doen.[33]
Example 
Good Bad

if done then
    return done
end


if not done then
    
end

return done
Eerst expressies die waar zijn
Meestal bent u vrij om clausules in then en else te ordenen zoals u dat wil, en u moet de clausules zo ordenen dat de clausule if een positieve test heeft. Dit maakt de code makkelijker leesbaar. Als u de clausule else kunt vermijden, is dat wel belangrijker.[34]
Example 
Good Bad
if a == b then
    
else
    
end
if a ~= b then
    
else
    
end
Eerst vragen
Meestal gaat de gevraagde waarde eerst in een logische expressie, omdat dit natuurlijker te lezen is en daardoor minder foutgevoelig is. De omgekeerde vorm wordt soms de 'Yoda-vorm' genoemd. Soms (maar zelden) werkt de natuurlijke vorm niet zoals verwacht, en eindigt de code. Dit kan komen doordat Lua er niet in slaagt een juiste tail-recursieve vorm van de expressie te vinden, waarna de stack overloopt.[35]
Example 
Good Bad
if length > 10 then
    
if 10 <= length then
    
Standaardwaarden geven
In talen met een of een operator or zoals in Lua is het heel gemakkelijk om in een standaard te voorzien. Dit is mooi, omdat sommige algemene constructies slecht werken als ze een niet-initiale waarde krijgen. Dit gebeurt bijvoorbeeld wanneer een tabel niet is geïnitieerd en de code probeert de nulwaarde te indexen.[36]
Example 
Good Bad

local t = arg or {}

t['foo']

local t = arg

if t then
    t['foo']
else
    
end
Binair conditioneel
Lua heeft geen binaire conditionele operator (??), of "nullish coalescing operator", maar u kunt hetzelfde doen met een or operator. Wat er gebeurt is, hoewel het voor nieuwkomers in Lua een beetje mysterieus is. De logische operatoren and en or geven truthy-waarden door (gematerialiseerde waarden), en kunnen dus deel uitmaken van andere expressies dan alleen logische.[37]
Example 
Good Bad
local area = (length or 0) * (width or 0)
local area = 0
if length and width then
    area = length * width
end
Drie-waarden conditioneel
Lua heeft geen conditionele operator (?ː), maar u kunt hetzelfde doen met een code>and en een or operator. Wat er gebeurt is een beetje mysterieus voor nieuwkomers in Lua. De logische operatoren code>and en or overdragen de ware waarden (materialiseerde waarden), en daarom kunnen ze deel uitmaken van andere expressies dan alleen logische.[38]
Example 
Good Bad
local height = pressure and millibarToMeters(length) or 0
local height = 0
if pressure then
    height = millibarToMeters(pressure)
end
Let op dat de vorm a and b or c waarbij b false is, c als resultaat zal geven. Dat is misschien niet het verwachte gedrag.
Vermijd repeat…until
De loopconstructie repeat…until de test vertraagt tot na de loop. Dit is foutgevoelig en moet worden vermeden. Dit is alleen aanvaardbaar wanneer de test zelf duur is in vergelijking met het uitgevoerde blok, of het vermijden van de herhalingsclausule zou leiden tot extra opruimen of code afronden.[39]
Testargumenten
Er is een kleine utility libraryUtil om de types van argumenten te testen, en die moet worden gebruikt om eenvoudige fouten te voorkomen. Vaak zijn de argumenten geldig wanneer andere code correct is, maar in randgevallen creëert iets een aanroep buiten het verwachte typebereik en loopt de code op een onverklaarbare manier stuk. Een goede test kan een fout vroegtijdig opvangen en de kans vergoten op het ontdekken van de ware oorzaak. Maat het testen van het type is een test op een fout, en geen test op goed.
Example 
Good Bad
local util = require 'libraryUtil'
local checkType = util.checkType

function concat( a, b )
    checkType( 'foo', 1, a, 'string' )
    checkType( 'foo', 1, b, 'number' )
    return a..'='..tostring(b)
end
function foo( a, b )
    return a..'='..tostring(b)
end


Patronen

Een paar gewone software patronen.

Commando patroon
Het meest voorkomende softwarepatroon in Lua-modules, dat het vaakst ontbreekt, is het commando patroon. Sommige gegevens zijn beschikbaar en er moet op basis van deze gegevens een bepaalde actie worden gekozen. Een typische geur die een commandopatroon mist, zijn lange ketens van als-dan-anders-af-testen. De meest voorkomende variant heeft geen benoemde commando's, maar een accept-qualifier functie. Beide versies zijn zeer gebruikelijk bij het parsen van argumenten vanuit de "invoke"-parserfunctie.
Example 
local commands = {}
-- each member of the command table is a simplified "ConcreteCommand"
commands['foo'] = function( val ) return -math.sqrt(-val) end
commands['bar'] = function( val ) return 0 end
commands['baz'] = function( val ) return math.sqrt(val) end

function sqrt( command, value ) -- execute for the "Command"
    return commands[command]( value ) -- execute for the "ConcreteCommand"
end

sqrt( -4 ) --> -2 (Should really be a complex number!)
local commands = {}
-- each member of the command table is a simplified "ConcreteCommand"
table.insert( commands, { function( val ) return value < 0 end, function( val ) return -math.sqrt(-val) end } )
table.insert( commands, { function( val ) return value == 0 end, function( val ) return 0 end } )
table.insert( commands, { function( val ) return value > 0 end, function( val ) return math.sqrt(val) end } )

function sumSqrt( value ) -- execute for the "Command"
    local accumulator = 0
    for _,command in ipairs( commands ) do
        command[1]( value ) then -- accept for the "ConcreteCommand"
            accumulator = accumulator + command[2]( value ) -- execute for the "ConcreteCommand"
        end
    end

end

sumSqrt( -4 ) --> -2 (Should really be a complex number!)

Testbaarheid

Over testen en hoe te zorgen dat de code te testen is. Let op dat het originele boek van the gang of four softwarepatronen bevat voor sterk getypeerde talen, wat niet goed past bij een zwak getypeerde taal.[40] Of Lua sterk of zwak is typehandhaving heeft, is iets waar over gesproken kan worden.[41]

Complexiteit
Er zijn meestal meerdere uitvoerpaden door een bepaalde code, wat de code moeilijk te begrijpen maakt. Hoe meer paden, hoe moeilijker de code wordt. Dit kan worden gemeten als cyclomatische complexiteit, en is een telling van paden door vertakkingspunten te tellen. Dit geeft een eerlijke, maar niet erg goede maatstaf voor de codekwaliteit.[42]
Globale waarden vermijden
Functies met globale waarden zijn moeilijk te testen, ongeacht hoe ze in de code zijn opgenomen. Om dit per ongeluk te voorkomen kunnen "accidental trap" bibliotheken worden toegevoegd om de module soepel te maken. Houd er nog steeds rekening mee dat het vereisen van wat code is als het importeren van een globale waarde, dus wees voorzichtig dat u geen groter probleem binnen haalt. [43][44][45]
Example 
Good Bad
local t = {}
function f( arg, opts )
    do_something( arg, opts )
end
f( 'somevalue', t )
local t = {}
function f( arg )
    do_something( arg, t )
end
f( 'somevalue' )
Veranderen van scope vermijden
In Lua is het mogelijk om de scope van een functie te controleren. Doe dat niet, want de functie zal dan afhankelijk zijn van "mini-global", wat bijna net zo slecht is als globale waarden. Als alles werkt zoals het hoort, dan zijn de mini-globalen waarschijnlijk semi-constant, maar er is geen garantie.

Beveiliging

Lua loopt in een soort zandbak omgeving, men kan zeggen dat de Lua-code wordt uitgevoerd in een dmz aan de buitenkant van de gebruikelijke server, waar slechts een paar aanroepen door de bak gaan en die moeten goed worden gevalideerd door de interne code. In het algemeen zou er geen reden moeten zijn om speciale voorzorgsmaatregelen te nemen om de code veilig te maken, omdat het resultaat van de code-uitvoering door een goede controle en ontsnapping zal gaan voordat het op de pagina wordt opgenomen.

Zie ook

Programmeeromgeving

Enkele tips voor het opzetten van uw externe programmeringsomgeving.

Visual Studio Code

Gebruik iets als de volgende extensies.

Andere hulpmiddelen

Dit zijn hulpmiddelen die u misschien nuttig vindt.

Referenties

  1. LuaUsers: LuaLint
  2. GitHub: mpeterv/luacheck
  3. The Art of Readable Code p. 21,34,43.
  4. The Art of Readable Code pp. 8-11, Choose Specific Words.
  5. The Art of Readable Code pp. 18-19, How Long Should a Name Be?
  6. The Art of Readable Code p. 12, Loop iterators.
  7. The Art of Readable Code pp. 15-17, Attaching Extra Information to a Name.
  8. The Art of Readable Code pp. 19-20, Acronyms and Abbreviations.
  9. The Art of Readable Code pp. 20-21, Use Name Formatting to Convey Meaning.
  10. LuaUsers:LuaStyleGuide
  11. Programming in Lua: 1.3 – Some Lexical Conventions
  12. LuaUsers:LuaStyleGuide
  13. Programming in Lua: 1.3 – Some Lexical Conventions
  14. PEP-8: Maximum Line Length (This style guide use 79 chars.)
  15. PEP-8: Indentation
  16. PEP-8: Tabs or spaces
  17. PEP-8: Should a line break before or after a binary operator?
  18. PEP-8: Whitespace in Expressions and Statements
  19. The Art of Readable Code p. 56. The box has an alternate approach to what-why-how.
  20. The Art of Readable Code pp. 62-63, State the Intent of Your Code.
  21. Refactoring Guru: CodeSmells: Disposables: Comments
  22. The Art of Readable Code p. 49, Don’t Comment Bad Names—Fix the Names Instead.
  23. The Art of Readable Code p. 50, Comment the Flaws in Your Code.
  24. The Art of Readable Code p. 50, Comment the Flaws in Your Code.
  25. The Art of Readable Code p. 50, Comment the Flaws in Your Code.
  26. The Art of Readable Code p. 50, Comment the Flaws in Your Code.
  27. The Art of Readable Code p. 51, Comment on Your Constants.
  28. JavaScript Patterns. p. 2
  29. Programming in Lua: 6.1 – Closures
  30. LuaUsers: Minimising Closures
  31. PEP-8: String Quotes
  32. LuaUsers: StringsTutorial
  33. The Art of Readable Code pp. 75-79, Returning Early from a Function.
  34. The Art of Readable Code pp. 70-73, The Order of Arguments in Conditionals.
  35. The Art of Readable Code pp. 70-73, The Order of Arguments in Conditionals.
  36. Programming in Lua: 3.3 – Logical Operators
  37. LuaUsers: TernaryOperator (This is for ternary conditional, but the binary conditional is pretty similar.)
  38. LuaUsers: TernaryOperator
  39. The Art of Readable Code pp. 74-75, Avoid do/while Loops.
  40. JavaScript Patterns. p. 2
  41. Lua for Python Programmers: Types
  42. Quandary Peak Research: Measuring Software Maintainability
  43. C2Wiki: Global Variables Are Bad
  44. PlayControl Software: Using closures in Lua to avoid global variables for callbacks
  45. JavaScript Patterns, pp. 12-13

Leesvoer