Genveje:
WP:LUA
WP:MODUL
WP:MODULER
 Kommentar Burde sammenskrives med Hjælp:Lua --Honymand (diskussion) 16. maj 2021, 12:49 (CEST)[svar]
Wikipedia-navnerum
Grundlæggende
navnerum
Tilhørende
diskussionsnavnerum
0 Artikler Diskussion 1
2 Bruger Brugerdiskussion 3
4 Wikipedia Wikipedia-diskussion 5
6 Fil Fildiskussion 7
8 MediaWiki MediaWiki-diskussion 9
10 Skabelon Skabelondiskussion 11
12 Hjælp Hjælpdiskussion 13
14 Kategori Kategoridiskussion 15
100 Portal Portaldiskussion 101
102 Artikeldata Artikeldatadiskussion 103
828 Modul Moduldiskussion 829
2300 [[Wikipedia:Navnerum/|]] [[Wikipedia:Diskussionssider|]] 2301
2302 [[Wikipedia:|]] [[Wikipedia:Diskussionssider|]] 2303
Virtuelle navnerum
-1 Special
-2 Media

Lua er et programmeringssprog som nu er tilgængelig på dansk Wikipedia via programudvidelsen Scribunto i MediaWiki. Luakoden kan indlejres i Wikipedia-skabeloner ved at bruge {{#invoke:}}-funktionaliteten.

Lua-kildekoden lagres i sider som kaldes moduler, som ligger i navnerummet Modul (for eksempel Modul:Lua banner). Et Lua-modul kaldes normalt fra en skabelonside ved hjælp af {{#invoke:}}, for eksempel {{#invoke:Lua banner|main}}.

Hovedformålet med denne side er at hjælpe dem som vil skrive et Lua-modul til Wikipedia, ved at komme med tips, retningslinjer og give kontakter til andre, som skriver Lua-moduler.

Lua i Wikipedia

redigér

Et Hello World-eksempel er Modul:HelloWorld:

-- Alle Lua-moduler i Wikipedia skal definere en variabel som har
-- eksternt tilgængelige funktioner. Den kan have et valgfrit navn
-- og kan også indeholde data. Variablen kaldes dog traditionelt 
-- for p (for package).
p = {}; 
 
-- Føj en funktion til variablen. Disse funktioner kan kaldes fra Wikipedia med 
-- {{#invoke}}. Parameteren "frame" indeholder de data, som Wikipedia sender til 
-- denne funktion, når den kaldes. Navnet på parameteren kan vælges vilkårligt, 
-- men normalt benyttes navnet "frame".
p.hej = function(frame)

    local str = "Hello World!"  -- Angiv en lokal variabel, og giv den indhold.
 
    return str  -- Afslut udførslen af denne funktion og send indholdet af 'str' 
                -- tilbage til Wikipedia. Det er ikke tilladt at benytte 'print'-
                -- funktionen, så udskrivning foretages ved at sende data tilbage 
                -- på denne måde.
 
end  -- Afslutning af funktionen.

return p  -- Alle moduler afsluttes ved at sende variablen med dens
          -- funktioner tilbage til Wikipedia.

Vi kan nu bruge dette modul og dets funktion med {{#invoke: HelloWorld | hej }}. #invoke-kommandoen begynder med modulets navn, i dette tilfælde HelloWorld. Derefter følger den af modulets funktioner, man ønsker at kalde, i dette tilfælde hej.

Se mw:Extension:Scribunto/Lua reference manual (engelsk) for en mere detaljeret beskrivelse af brugen af Lua på Wikipedia.

Best practice

redigér

Der findes lidt best practice, dvs. alment gode råd og forslag til retningslinjer, men som pt. ikke er ophøjet til officiel standard.

"strict"

redigér

Undgå forurening af det globale navnerum! Brug local og do … end for at skrive funktioner og variable i en lokal kontekst. For at forhindre at et modul forurener det globale navnerum, kan man bruge require ('strict') som vil bevirke at forsøg på oprettelse af variable vil give en fejlmeddelelse. Dette kan ofte også hjælpe med at fange skrivefejl, hvor man skriver et variabelnavn forkert. Modul:No globals brugt til det samme, før 'strict' blev indført i Scribunto.

Det er dog i visse tilfælde nødvendigt at oprette nye globale funktioner - vær i så fald tydelig omkring, hvad der oprettes globalt og hvorfor.

Dokumentation

redigér

Skriv dokumentation for modulets generelle egenskaber. Denne lægges på en underside «Module:navn/dok». Dokumentation skrives på fællessprog (engelsk for da-wiki) eller på lokalsprog (dansk for da-wiki). Vær omhyggelig med at dokumentere funktioner, gerne i JDoc-style, og glem ikke konfigurations-variable. Hvis modulet har manglende eller udeladte kodesekvenser så marker disse med -- @todo, så andre kan finde dem nemt. Husk det er et samarbejdsprojekt.

Informer om scripting

redigér

Tilføj skabelonen {{Lua}} øverst på alle skabelonsiden for alle skabeloner der bruger Lua. Dette gør det nemmere for dem som ikke kender til Lua, og gør det nemmere at få en oversigt over alle skabeloner som bruger Lua. Skabelonen bruges således: {{Lua|Modul:Modulnavn}}. Resultatet af {{Lua|Modul:HelloWorld}} er vist i højre side.

Lav tests

redigér

Lav tests for modulet. Disse lægges på en underside «Module:navn/testcases». Der er tre forskellige biblioteker til dette, med hver sin tilgang. Det er vigtigere at der laves tests, end hvilket test-bibliotek der bruges. Testcases skal dække mest muligt af modulets funktionalitet, men for tiden findes der ikke noget bibliotek der kan profilere et helt modul. Der findes desuden et bibliotek til timing af enkeltfunktioner (w:en:Module:Timing).

Brug biblioteksfunktionerne

redigér

Brug de fælles standardbiblioteker hvor det er muligt, men hav i baghovedet at det i nogen tilfælde kan være fornuftigt at reimplementere funktionalitet. Specielt hvis det giver enklere eller kortere kode, og modulet er meget anvendt, kan det være gunstigt at undgå import af store biblioteker. Vær opmærksom på kodekvalitet, og at denne kan være bedre i de større og mere gennemarbejdede moduler.

Separation of concerns

redigér

Husk på separation of concerns. Dette gælder særligt adskillelse af beskeder fra resten af koden, og ikke mindst anbefales det at lokalisering håndteres adskilt fra logikken. Der findes et standardbibliotek til håndtering af sprogspecifikke forhold (Language library) og et til håndtering af beskeder (Message library). Implementer fall-back mekanismer til håndtering af at nogle tekster kan mangle på visse sprog.

Lokalisering

redigér

Det er altid en god idé at udskille lokalisering af de enkelte sprog på egne sider. For at gøre det enkelt at oversætte fra et sprog til et andet, kan der laves en skabelon. Denne kan placeres på dokumentationssiden for en lokalisering og forenkler kontrollen af overensstemmelse mellem sprogene. For at gøre det enklere for diff-mekanismen (den mekanisme, der automatisk finder forskelle) at synkronisere mellem sprogene (der er ofte mange forskelle mellem dem), så kan der indsættes nogle kommentarer som angiver, hvad de enkelte blokke omhandler. Disse kommentarer skal være på samme sprog.

Husk sikkerhed

redigér

Det er begrænset hvor der kan opstå sikkerhedsproblemer, men generelt skal man arbejde efter de samme regler i Lua som i andre sprog! Filtrer input og escape output; hovedparten af input sendes dog til Lua via serveren og er allerede filtreret. Det som genereres af Lua-scripts kan imidlertid omgå mekanismerne for automatisk escape af output via "rå" HTML kode og derved udgøre en sikkerhedsrisiko. Hvis du bruger "rå" HTML kode som er det dit ansvar at escape relevante elementer! Vær omhyggelig hvor der konkateneres strenge - alle strenge må escapes for et sikkert resultat. Brug standardbiblioteket for HTML hvor det er mulig (HTML library), og returner wikitekst gennem metoden til dette. Strenge er sikre hvis de returneres uden at være mærkede som "rå" tekst, fordi de så bliver behandlet af mediawiki-softwaren som al anden wikitekst.

Hvis der modelleres efter paradigmet Model–view–controller (MVC) så er Lua-script delvist i «model» og «view», men kun i ringe grad i «controller». Den sidste er hovedsageligt drevet af Javascript i browseren. I nogen grad kan Lua blive del af controlleren, men da via serverens API.

Begrænsninger i Wikipedia

redigér
  • Lua-koden køres alene når en side fortolkes – det vil sige når en side gemmes, forhåndsvises, etc. – og Lua kan kun få input som tekststrenge sendt med {{#invoke:}} som det er muligt at hente fra frame.expandTemplate, frame.preprocess, osv.
  • Wikitekst som sendes ud fra Lua bliver ikke bearbejdet yderligere, så i skabeloner og al anden transklusion vil teksten vises som den er.
  • Links av typen [[Wikipedia:Hjælp|]] fungerer ikke som uddata fra Lua – de skal skrives eksplicit som [[Wikipedia:Hjælp|Hjælp]].
  • Der er heller ingen anden behandling af indholdet, for eksempel at erstatte ~~~~ med signaturer.
  • Lua-koden på en side er begrænset til maks 10 sekunder CPU-tid på serveren.
  • For en delvis liste av begrænsinger, se mw:Extension:Scribunto/Lua reference manual#Differences from standard Lua.

Din sandkasse

redigér

Hvis du kun skal teste en enkelt side, så er feltet til forhåndsvisning på redigeringssiden som regel tilstrækkeligt. Hvis du derimod skal override flere skabeloner og moduler, så må du bruge Special:TemplateSandbox og placere alle sider under en fælles rod. Alle sider under denne rod vil override sider i andre navnerum ved processering af artiklen du angiver til forhåndsvisning. Du kan også forhåndsvise en specifik version eller en given wikitekst.

Hvis du er nødt til at rette på en side for at afprøve en specifik funktion eller formatering, så kan du gemme denne version og så rulle tilbage. Så har du en version som du kan referere i Special:TemplateSandbox som udgangspunkt for din ændring.

Når du tester sider i sandkasser kan du bruge nogen af de placeringer som er blevet en de-facto standard.

Hvis du skriver på din egen version af et modul så kan du bruge Special:Diff til at sammenligne ændringerne i dit eget modul med udgangspunktet. Konfiguration af links er afhængig af hvordan du har opsat din sandkasse, men typisk må du indsætte et link a la:

[[Special:Diff/{{REVISIONID:<sideA>}}/{{REVISIONID:sideB}}]]

Hvor den ene side er i din sandkasse og den anden side er modulet, som var udgangspunkt for dine ændringer.

Privat sandkasse

redigér

Hvis du ønsker at udskifte wikikode med Lua i en ofte anvendt skabelon eller modul, og du alene arbejder på projektet, kan det være en fordel at eksperimentere i en privat "sandkasse". Du kan oprette denne som en underside under din egen bruger, typisk i følgende format (erstat teksten mellem < > med relevant indhold):

Bruger:<Dit brugernavn>/sandkasse/Modul:<Navnet på din modul>

Bemærk, at du skal bruge den lokale version af navnerummet, hvilket vil sige "Modul" og ikke "Module" eller "modul". Ofte vil du også skulle ændre require, så koden henter de korrekte biblioteker.

Du kan bruge Special:Prefiksindeks på siden "Bruger:<Dit brugernavn>/sandkasse/" for at få en liste over alle dine sider, der anvender dette navneskema. Den rod, du skal angive til TemplateSandbox i dette tilfælde, er "Bruger:<Dit brugernavn>/sandkasse".

Så længe du foretager ændringer på sider i dit eget brugerområde, vil få have indvendinger. Dette kan dog også være en ulempe, hvis du ønsker feedback.

Fælles sandkasse A

redigér

Hvis flere personer arbejder på projektet, og der kun er behov for én sandkasse, kan det være praktisk at bruge en fælles side. Mange moduler er indrettet således, at sandkassen har følgende format (erstat teksten mellem < > med relevant indhold):

Modul:<modul-navnet>/sandkasse

Du kan bruge Special:Prefiksindeks på siden "Modul:<modul-navnet>/sandkasse" for at se en liste over alle sider, der anvender dette navneskema. Den rod, du skal angive til TemplateSandbox i dette tilfælde, er "Modul:<modul-navnet>". (Hvis linket er forkert, kan det indikere, at navnet ikke er tilgængeligt til overskrivning).

Normalt anvendes denne form primært til redigering af selve modulet.

Fordelen ved denne metode er, at andre brugere nemt kan finde frem til sandkassen, hvilket øger chancen for at modtage feedback på ændringer. Ulempen kan dog være, at man får en stor mængde tilbagemeldinger, som ikke altid er lige præcise eller brugbare.

Fælles sandkasse B

redigér

Hvis du ønsker en delvist åben sandkasse, eller hvis flere personer arbejder på en skabelon eller et modul, men med visse forskelle, kan du oprette en sandkasse i dette format (erstat teksten mellem < > med relevant indhold):

Modul:Sandkasse/<Dit brugernavn>/Modul:<Navnet på din modul>

Også her skal den lokale version af navnerummet anvendes, hvilket vil sige "Modul" og ikke "Module" eller "modul", og require skal justeres, så koden henter de rigtige biblioteker.

Du kan bruge Special:Prefiksindeks/Modul:Sandkasse for at se en liste over alle sandkasser, der bruger dette navneskema. Den rod, du skal angive til TemplateSandbox i dette tilfælde, er "Modul:Sandkasse/Modul:<Dit brugernavn>".

Modulet "Sandkasse" eksisterer ikke i sig selv, men det er en konvention at anvende det som rod i dette navneskema.

Fordelen ved denne metode er, at andre brugere let kan finde frem til sandkassen, hvilket gør det nemt at få feedback. Samtidig giver det mulighed for at arbejde parallelt på flere moduler.

Test af Lua-moduler/funktioner

redigér

Lua er et programmeringssprog, og som med alle programmeringssprog kan fejl forekomme. Når en modul udvikles, er det afgørende at teste koden effektivt for at undgå, at nye fejl opstår i allerede eksisterende funktioner. Wikipedia er et omfattende køremiljø for kode, langt større end det, man normalt ser på andre hjemmesider. Derfor er det ekstremt vigtigt, at alt fortsætter med at fungere korrekt efter ændringer. Af denne grund er der udviklet særlige testbiblioteker for at lette testprocessen.

Generelt set benyttes tre forskellige testparadigmer: Enhedstestning, Testdrevet udvikling og Adfærdsdrevet udvikling. Disse tre metoder kan betragtes som separate tilgange, men de repræsenterer også forskellige måder at strukturere testforløbet på.

Enhedstestning

redigér

Enhedstestning handler helt konkret om, hvordan man tester en enkelt enhed, ofte ved at indsætte forskellige former for "spioner" i den eksekverbare kode. Typisk er enhedstestning tæt forbundet med en specifik implementering af et modul, og hvis modulet udskiftes, må testpakken ofte også tilpasses eller erstattes. Sammenhængen mellem testpakken og implementeringen kan være så stærk, at testpakken låser implementeringen til en bestemt løsning.

Testdrevet udvikling

redigér

Testdrevet udvikling indebærer, at man definerer kontrakten for, hvordan en metode skal opføre sig, før selve koden skrives. Dette er en fordelagtig tilgang i tilfælde, hvor der allerede findes en klar kravspecifikation, eller hvor en sådan kan udledes. Udfordringen ved denne metode er dog, at når man forsøger at løse et problem, ligger fokus sjældent på selve kravspecifikationen, hvilket kan føre til en ufuldstændig testdefinition.

Adfærdsdrevet udvikling

redigér

Adfærdsdrevet udvikling har en tættere tilknytning til agil udvikling, men med en særlig tilgang til, hvordan løsningen beskrives. Ved at anvende et relativt simpelt sprog tvinges udvikleren til at konkretisere den nødvendige funktionalitet og præcisere, hvad koden skal udføre. Traditionel testning udføres ofte efter selve kodningen, selvom dette ikke altid er optimalt. Ved adfærdsdrevet udvikling bliver testene derimod defineret som en integreret del af kravspecifikationen.

Pragmatisk tilgang

redigér

På Wikipedia anvender vi ofte en mere iterativ tilgang, hvor vi først implementerer en løsning og derefter tilføjer tests for at verificere vores antagelser om koden. Efterhånden som vi udvider koden, tilføjes yderligere tests, og på den måde itererer vi os frem. Vi har sjældent en fastlagt plan for, hvad vi gør først – om vi starter med testning eller udvikling – og der findes ingen entydig bestiller af funktionaliteten. Ulempen ved denne metode er, at vi kan ende med metoder og tests, der ikke er optimale, fordi vi ikke har en klart defineret kravspecifikation.

Tilgængelige biblioteker

redigér

Hvordan vi tester, afhænger mere af metodikken end af valg af testbibliotek. Nogle biblioteker er mere tilpasset visse testparadigmer end andre, men de tilgængelige testbiblioteker kan som regel anvendes på tværs af de tre testmetoder. Modul:UnitTests er tæt knyttet til overfladisk enhedstestning og fokuserer primært på at have nogle grundlæggende funktioner til at teste sammenhængen mellem input og output i funktioner. Modul:ScribuntoUnit er mere orienteret mod testdrevet udvikling, hvor der oprettes et testmiljø, og udviklingen sker i en vekselvirkning mellem testene og den kode, der testes. Modul:BDD (under udvikling) er mest relateret til adfærdsdrevet udvikling og benytter elementer fra domænedrevet design. Denne modul har visse funktioner, der understøtter tættere iterationer mellem test og udvikling sammenlignet med de to andre moduler.

Modulet Modul:UnitTests er importeret fra Engelsk Wikipedia, mens Modul:ScribuntoUnit oprindeligt stammer fra Ungarsk Wikipedia. Modul:BDD er en lokal udvikling på Dansk Wikipedia. Testtilfælde skrives som en underside under modulets diskussionsside: "Moduldiskussion:modulnavn/testtilfælde", hvor modulnavn henviser til det modul, der testes. Testresultaterne kan ses på denne undersides diskussionsside, "Modul:modulnavn/testtilfælde", eller de kan integreres direkte i testmodulets dokumentation. Alternativt kan man anvende hjælpefunktionen Hjælp:Integreret testning, der gør det muligt at vise testresultaterne på samme side som modulet, når det åbnes for redigering.

Kategoriserede testresultater

redigér
Bemærk, at koden til at kategorisere moduler baseret på fejlbehæftede tests er fjernet.

Der findes to typer kategoriserede resultater i forbindelse med fejl. Den ene type fejl fører til kategorisering under sider med scriptfejl, hvilket sker, når et script indeholder fejl i enten kompileringsfasen eller køremiljøet. Fejlen kan opstå i selve kaldet på siden, i modulet selv eller i en inkluderet modul. Disse fejl vil typisk blive vist som en stor rød fejlmeddelelse på siden. For at identificere fejlkilden kan man klikke på den røde fejlmeddelelse, hvilket åbner en detaljeret fejlinformation, herunder hvor fejlen opstod samt det specifikke linjenummer. I sjældne tilfælde findes der ingen entydig fejlkilde, hvilket ofte skyldes problemer relateret til invoke eller genereringen af modulets eksporterede tabel.

En anden type kategorisering placerer modulerne i category-all-tests, samt underkategorierne category-good-tests og category-failed-tests. Moduler, der er placeret i category-failed-tests, indeholder mindst én test, der fejler. Kategoriseringen af modulerne sker via en eksporteret metode fra testmodulerne. Denne metode tilføjer moduler med testtilfælde til en af de ovenstående kategorier, afhængigt af om testresultaterne er gode eller fejler. Der foretages ingen yderligere specifikation udover selve kategoriseringen.

Andre sprogprojekter benytter ikke denne form for kategorisering, så hvis moduler skal opdateres for at inkludere denne funktionalitet, skal der tilføjes ekstra kode. For at få kategoriseringen til at fungere er det nødvendigt at foretage en lille ændring i måden, hvorpå require skrives. Normalt skrives det som require('Module:modulename'), men for at aktivere de ekstra metoder skal resultatet fra require kaldes direkte. Typisk skrives dette som require 'Module:modulename'().

Se også

redigér