Modulmönster och bästa praxis
Använd mönstret local M = {} och exponera ett offentligt API på ett tydligt sätt.
Modulmönster och bästa praxis är en gratis lektion i Lua Academy på CoddyKit. Detta är lektion 4 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Lua Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Lua Academy innehåller totalt 4 lektioner.
Mönstret M = {}
Det universella Lua-mönstret för moduler: deklarera en lokal tabell, fyll den med innehåll och returnera den. Alla publika symboler läggs i M; alla privata hjälpfunktioner är vanliga lokala variabler. Detta är tydligt, minimalt och fungerar överallt.
-- The canonical module pattern
local M = {}
-- Private helper (not exported)
local function validate(x)
return type(x) == "number" and x >= 0
end
-- Public API
function M.sqrt(x)
assert(validate(x), "expected non-negative number")
return math.sqrt(x)
end
M.PI = math.pi
return MSjälvrefererande modul
Inuti en modul kan funktioner anropa andra modulfunktioner antingen via namn (M.foo()) eller som lokala funktioner. Lokala funktioner är något snabbare; med M.foo() kan användare skriva över M.foo och få det interna anropet att använda ersättningen (monkey patching).
local M = {}
-- Option A: use M.foo inside (allows override)
function M.double(n) return M.multiply(n, 2) end
function M.multiply(a, b) return a * b end
-- Option B: use local function (faster, no override)
local function mul(a, b) return a * b end
function M.triple(n) return mul(n, 3) end
return MSingletonmönstret
En modul kan fungera som en singleton: den har ett förändringsbart internt tillstånd som delas av alla anropare. Eftersom require cachelagrar modulen får alla anrop av require("mod") samma objekt med samma tillstånd.
-- config.lua (singleton)
local M = {}
local _config = {env="dev", logLevel="info"}
function M.set(key, val)
_config[key] = val
end
function M.get(key)
return _config[key]
end
function M.load(t)
for k,v in pairs(t) do _config[k]=v end
end
return M
-- All callers share the same config:Modul som namnrymd
Använd en modul enbart som namnrymd för att undvika att förorena den globala tabellen. Gruppera relaterade konstanter och hjälpverktyg under ett namn, ungefär som ett paket i andra språk.
-- constants.lua
local M = {
HTTP = {
OK=200, CREATED=201, NO_CONTENT=204,
BAD_REQUEST=400, UNAUTHORIZED=401,
NOT_FOUND=404, SERVER_ERROR=500,
},
COLORS = {RED="#FF0000", GREEN="#00FF00", BLUE="#0000FF"},
MAX_RETRIES = 3,
TIMEOUT_SEC = 30,
}
return M
-- local C = require("constants")
-- if status == C.HTTP.NOT_FOUND then ...Fabrikmodul
En modul som exporterar en fabriksfunktion i stället för en vanlig tabell. Fabriken skapar och returnerar nya instanser med eget privat tillstånd. Detta är klassmönstret på modulnivå.
-- logger.lua
local M = {}
function M.new(name, level)
level = level or "info"
local levels = {debug=1,info=2,warn=3,error=4}
local self = {}
function self.log(msgLevel, msg)
if levels[msgLevel] >= levels[level] then
print(string.format("[%s][%s] %s", name, msgLevel:upper(), msg))
end
end
function self.info(msg) self.log("info", msg) end
function self.warn(msg) self.log("warn", msg) end
function self.error(msg) self.log("error", msg) end
return self
end
return MModulens initieringsfunktion
Vissa moduler kräver konfiguration innan de kan användas. Tillhandahåll en funktion M.init(config) som lagrar konfigurationen i modulens privata tillstånd. Detta möjliggör beroendeinjektion och testbarhet.
-- db.lua
local M = {}
local pool = nil
function M.init(config)
pool = {
host = config.host or "localhost",
port = config.port or 5432,
connections = {},
}
print("DB initialized:", pool.host, pool.port)
end
function M.query(sql)
assert(pool, "call db.init() first")
-- ... execute query
return {}
end
return MOföränderlig modul
Förhindra att användare av misstag ändrar modulens API genom att använda __newindex för att blockera alla skrivningar. Detta är särskilt användbart för biblioteksmoduler där oavsiktlig monkey patching kan orsaka problem.
local function freeze(t)
return setmetatable({}, {
__index = t,
__newindex = function(_, k, _)
error("module is read-only, cannot set: " .. tostring(k), 2)
end
})
end
local M = {}
function M.add(a, b) return a + b end
function M.sub(a, b) return a - b end
return freeze(M)Dokumentera med LDoc
En vanlig konvention för att dokumentera Lua-moduler är kommentarer i LDoc-stil med prefixet ---. Även om språket inte kräver detta kan kommentarerna göra det möjligt för verktyg för dokumentationsgenerering att automatiskt skapa API-dokumentation.
--- A utility module for string operations.
-- @module stringutils
local M = {}
--- Trim leading and trailing whitespace.
-- @param s string The input string.
-- @return string The trimmed string.
function M.trim(s)
return s:match("^%s*(.-)%s*$")
end
--- Count occurrences of a substring.
-- @param str string The string to search.
-- @param sub string The substring to count.
-- @return number Count of occurrences.
function M.count(str, sub)
local _, n = str:gsub(sub, "")
return n
end
return MTesta moduler
Testa en modul genom att kräva den och köra varje funktion. Använd en enkel testrunner eller busted (testramverket för Lua). Förvara testerna i en separat fil som speglar modulens sökväg.
-- test/test_stringutils.lua
local su = require("stringutils")
local function test(name, fn)
local ok, err = pcall(fn)
if ok then print("[PASS] " .. name)
else print("[FAIL] " .. name .. ": " .. err)
end
end
test("trim removes spaces", function()
assert(su.trim(" hello ") == "hello")
end)
test("trim empty string", function()
assert(su.trim("") == "")
end)
test("count occurrences", function()
assert(su.count("banana", "a") == 3)
end)Sammansätta moduler
Komplexa system sätts samman av flera moduler. En huvudingång kräver och kopplar samman undermodulerna. Denna ansvarsfördelning håller varje modul fokuserad och möjliggör oberoende testning.
-- app.lua (main entry point)
local config = require("config")
local db = require("db")
local server = require("server")
-- Configure from environment
config.load({
dbHost = os.getenv("DB_HOST") or "localhost",
port = tonumber(os.getenv("PORT")) or 8080,
})
-- Wire modules together
db.init({host=config.get("dbHost"), port=5432})
server.init({port=config.get("port"), db=db})
server.start()Snabbkontroll
Vad är huvudsyftet med modulmönstret local M = {} ... return M?
Sammanfattning: bästa praxis för moduler
Sammanfattning:
- Använd alltid
local M = {} ... return M - Privat = lokala variabler på filnivå; publikt = M-fält
- Singleton: require cachelagrar modulinstansen
- Använd fabriksfunktioner för tillstånd per instans
- Frys moduler med __newindex för att förhindra ändringar
- Testa i separata filer; dokumentera med ---- kommentarer
Lär dig Lua med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 40
- Lektioner
- 159
Vanliga frågor
Är lektionen ”Modulmönster och bästa praxis” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Lua Academy, inklusive ”Modulmönster och bästa praxis”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Lua Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Modulmönster och bästa praxis”?
Använd mönstret local M = {} och exponera ett offentligt API på ett tydligt sätt. Ni övar på Lua Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Lua Academy?
Du behöver inga förkunskaper. Utbildningen i Lua Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.
Hur lång tid tar lektionen ”Modulmönster och bästa praxis”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Lua Academy-lektionen?
Ja. Varje Lua Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Funktionen require
- Skriva en modulfilsfil
- package.path och package.cpath
- Modulmönster och bästa praxis