Spring til indhold

Wikipedia:Lua

Fra Wikipedia, den frie encyklopædi
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

[rediger kildetekst]

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

[rediger kildetekst]

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

No globals

[rediger kildetekst]

Undgå forurening af det globale navnerum! Brug local og do … end for at skrive funktioner og variable i en lokal kontekst. For at vise klart og tydeligt at et modul ikke forurener det globale navnerum kan modulet Modul:No globals importeres - alle forsøg på at tilføje globale konstruktioner i modulet, vil derefter give en fejlmeddelelse.

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

[rediger kildetekst]

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

[rediger kildetekst]

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

[rediger kildetekst]

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

[rediger kildetekst]

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

[rediger kildetekst]

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

[rediger kildetekst]

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

[rediger kildetekst]
  • 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

[rediger kildetekst]

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

[rediger kildetekst]

Hvis du ønsker å bytte ut wikikoden med Lua i en mye brukt mal eller modul, og det kun er du selv som er involvert i prosjektet, så kan det være en fordel å prøve seg frem i en privat «sandkasse». Denne kan du opprette som en egen underside under din egen bruker, typisk noe ala (erstatt teksten mellom < > med passende tekst)

Bruger:<Ditt brukernavn>/sandkasse/Modul:<Navnet på din modul>

Merk at du må bruke den lokale formen av navnerom, det vil si «Modul» og ikke «Module» eller «modul». Som oftest må du også endre require slik at koden henter inn riktige biblioteker.

Bruk Special:Prefiksindeks på siden «Bruger:<Ditt brukernavn>/sandkasse/» for en liste over alle dine sider som bruker dette navneskjemaet. Roten du oppgir til TemplateSandbox i dette tilfellet er «Bruger:<Ditt brukernavn>/sandkasse».

Så lenge du gjør endringer på sider i ditt eget brukerrom er det få som vil ha innvendinger. Det er også en ulempe hvis du ønsker tilbakemeldinger.

Felles sandkasse A

[rediger kildetekst]

Hvis det er flere som er involvert i prosjektet, og dere kun trenger en sandkasse, så kan det være lurt å bruke siden som det lenkes til som standard. Mange moduler legger opp til at sandkassen på formen (erstatt teksten mellom < > med passende tekst)

Modul:<modul-navnet>/sandkasse

Bruk Special:Prefiksindeks på siden «Modul:<modul-navnet>/sandkasse» for en liste over alle sider som bruker dette navneskjemaet. Roten du oppgir til TemplateSandbox i dette tilfellet er «Modul:<modul-navnet>». (Er lenka feil, dette impliserer at navnet ikke er tilgjengelig for overstyring?)

Vanligvis blir formen kun brukt for å redigere modulen(?).

Fordelen med denne formen er at andre brukere lett finner frem, og dermed får du tilbakemelding på endringer. Ulempen er at du kan få mye tilbakemeldinger, og de er ikke alltid like velformulert.

Felles sandkasse B

[rediger kildetekst]

Hvis du vil ha en halvåpen sandkasse, eller det er flere som skriver på en mal eller modul som er litt forskjellige, så kan du opprette en sandkasse på dette formatet (erstatt teksten mellom < > med passende tekst)

Modul:Sandkasse/<Ditt brukernavn>/Modul:<Navnet på din modul>

Også her må en bruke den lokale formen av navnerom, det vil si «Modul» og ikke «Module» eller «modul», og endre require slik at koden henter inn riktige biblioteker.

Bruk Special:Prefiksindeks/Modul:Sandkasse for en liste over alle sandkasser som bruker dette navneskjemaet. Roten du oppgir til TemplateSandbox i dette tilfellet er «Modul:Sandkasse/Modul:<Ditt brukernavn».

Modulen «Sandkasse» finnes ikke, det er kun en overenskomst at den brukes som rot i dette navneskjemaet.

Fordelen med denne formen er at andre brukere lett finner frem, slik at du får tilbakemeldinger, og at det er lett å skrive på flere moduler samtidig.

Testing av Lua-moduler/funksjoner

[rediger kildetekst]

Lua er et programmeringsspråk, og som alle slike er det mulig å gjøre feil. Under selve utviklingen av en modul er det viktig å teste på en effektiv måte, ikke minst for å unngå å introdusere feil i kode en har skrevet tidligere. Wikipedia er et stort kjøremiljø for kode, mye større enn det som er vanlig på andre nettstedere. Det er derfor overordentelig viktig at alt fortsetter å fungere som forventet etter endringer. Det er for å forenkle slik testing at det er laget egne testbiblioteker.

Generelt så blir testing gjort etter tre forskjellige paradigmer; enhetstesting, testdrevet utvikling, og oppførelsdrevet utvikling. Dels kan en se på disse tre som separate paradigmer, men de er nok like mye forskjellig tilnærming til hvordan en gjør testing.

Enhetstesting

[rediger kildetekst]

Enhetstesting er helt konkret hvordan en tester en enhet, ofte ved å injisere forskjellige former for «spioner» i den kjørbare koden. Som oftest er enhetstesting tett knyttet til en bestemt implementasjon av en modul, og hvis en bytter modulen så bytter en også testsettet. Ofte er koblingen så tett at testsettet kan låse implementasjonen til en gitt løsning.

Testdrevet utvikling

[rediger kildetekst]

Testdrevet utvikling går ut på at en definerer kontrakten for hvordan en metode skal oppføre seg før en skriver selve koden. Dette er en god løsning der en har en klar kravspesifikasjon på forhånd, eller hvor en kan utlede en slik kravspesifikaasjon. Problemet med dette er at når en skal løse et problem så er kravspesifikasjonen utenfor det en er mest fokusert på, dermed blir testspesifikkasjonen ufullstendig.

Oppførselsdrevet utvikling

[rediger kildetekst]

Oppførelsdrevet utvikling er tettere på agile development, men med noen føringer på hvordan løsningen beskrives. Ved å bruke et nokså enkelt språk så tvinges en til å konkretisere nødvendig funksjonalitet og hva den skal utføre. Tradisjonell testing blir ofte gjort i etterkant, selv om dette er suboptimalt, mens ved oppførselsdrevet utvikling så defineres testene som en integrert del av kravspesifikasjonen.

Pragmatisk tilnærming

[rediger kildetekst]

Det vi gjør i Wikipedia er veldig ofte at vi lager en første implementasjon, og deretter legger til tester for å bekrefte (verifisere) våre antakelser om koden. Etter hvert legges det til mer kode, og det legges til mer tester. Slik itererer vi oss fremover. Vi har ofte ikke en helt klar formening om hva vi gjør først, testing eller utvikling, og det finnes ingen klar bestiller av funksjonaliteten. Ulempen med dette er at vi kan ende opp med metoder og tester som ikke er optimale i fordi vi ikke har en klar kravspesifikasjon.

Tilgjengelige bibliotek

[rediger kildetekst]

Hvordan vi tester er mer et metodevalg enn et valg av testbibliotek. Noen biblioteker lener seg litt mer til ett av paradigmene enn til de andre, men de som er tilgjengelig kan brukes for alle de tre skisserte. Modul:UnitTests er tett på overfladisk enhetstesting, hvor det essensielle er å ha noen primitiver for å teste likhet mellom input og output til og fra funksjoner. Modul:ScribuntoUnit er nok noe tettere på testdrevet utvikling, hvor en setter opp et testharness og itererer seg frem i vekselvirkning med koden som testes. Modul:BDD (under utvikling) har mest til felles med oppførselsdrevet utvikling og bruker elementer fra domenedrevet design. Denne modulen har noe støtte for tettere iterasjoner med koden som utvikles enn de to foregående modulene.

Modulene TestUnits er importert fra enwiki, mens ScribuntoUnit opprinnelig kommer fra huwiki. Modulen BDD er lokal her på nowiki. Testtilfellene skrives på en underside «Moduldiskusjon:modulename/testtilfeller» hvor modulename er modulen som testes. Resultatene vises på undersidens diskusjonsside, «Modul:modulename/testtilfeller», eller ved integrasjon i testmodulens dokumentasjon, eller ved å bruke tilleggsfunksjonen Hjelp:Integrert testing. Denne viser testene på samme side som modulen når den åpnes for redigering.

Kategoriserte testresultat

[rediger kildetekst]
Merk at koden for å kategorisere moduler på bakgrunn av feilede tester er fjernet.

Det er to typer kategoriserte resultat som følge av feil. En type feil gir kategorisering i sider med skriptfeil, og kategorisering utløses som følge av inkludering av script med feil fra kompilering eller kjøremiljøet. Feilen kan skje i selve kallet på siden, eller i selve modulen, eller i en inkludert modul. Disse feilene vil vanligvis bli synlig med en stor rød feilmelding på siden. For å påvise hvor feilen er så klikker en på den røde lenken og får da opp ytterligere informasjon, med hvor feilen oppstod og linjenummer. I noen få tilfeller blir det ikke påvist noen klar og entydig kilde, og da er ofte feilen i forbindelse med invoke eller oversettelsen til modulens eksporterte tabell.

En annen type kategorisering plasserer modulene i category-all-tests, og underkategoriene category-good-tests og category-failed-tests. Moduler kategorisert i category-failed-tests er de som av noen grunn har tester som feiler. Kategorisering av modulene skjer via en eksportert metode fra testmodulene. Denne metoden legger til kategorier for moduler med testtilfeller, og hvorvidt resultatene er gode eller feiler. Det er ingen ytterligere detaljering utover kategorisering.

De andre språkprosjektene bruker ikke slik kategorisering, så skal modulene oppdateres så må ekstra kode legges til modulene. For å få kategorisering til å fungere er det nødvendig å gjøre en mindre endring i hvordan require skrives. Tidligere er den gjerne skrevet require('Module:modulename'), men for å få installert de ekstra metodene må det legges til et kall på resultatet fra require, typisk skrives dette som require 'Module:modulename'().