Lua Academy · Les

Modulepatronen en best practices

Gebruik het patroon local M = {} en stel een openbare API overzichtelijk beschikbaar

Les 4 van 412 stappen

Modulepatronen en best practices is een gratis Lua Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Lua Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Lua Academy bevat in totaal 4 lessen.

Het patroon M = {}

Het universele Lua-modulepatroon: declareer een lokale tabel, vul die en geef hem terug. Alle openbare symbolen komen in M; alle privéhulpfuncties zijn gewone lokale waarden. Dit is duidelijk, minimaal en werkt overal.

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

Module met zelfverwijzingen

Binnen een module kunnen functies andere moduelfuncties aanroepen op naam (M.foo()) of als lokale waarden. Lokale waarden zijn iets sneller; met M.foo() kunnen gebruikers M.foo overschrijven, waarna de interne aanroep de overschreven versie gebruikt (monkeypatching).

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 M

Singletonpatroon

Een module kan zich gedragen als singleton: de module heeft een veranderlijke interne status die door alle aanroepers wordt gedeeld. Omdat require de module in de cache opslaat, krijgen alle aanroepen van require("mod") hetzelfde object met dezelfde status.

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

Module als naamruimte

Gebruik een module uitsluitend als naamruimte om vervuiling van de globale tabel te voorkomen. Groepeer gerelateerde constanten en hulpprogramma's onder één naam, zoals een pakket in andere talen.

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

Fabrieksmodule

Een module die een fabrieksfunctie exporteert in plaats van een gewone tabel. De fabriek maakt nieuwe instanties met elk hun eigen privéstatus en geeft die terug. Dit is het klassenpatroon op moduleniveau.

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

Initialisatiefunctie van een module

Sommige modules vereisen configuratie voordat ze kunnen worden gebruikt. Bied een functie M.init(config) aan die de configuratie opslaat in de privéstatus van de module. Dit maakt dependency injection en testbaarheid mogelijk.

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

Onveranderlijke module

Voorkom dat gebruikers de programmeerinterface van de module per ongeluk wijzigen door __newindex te gebruiken om alle schrijfbewerkingen te blokkeren. Dit is vooral nuttig voor bibliotheekmodules waarin per ongeluk monkeypatchen problemen kan veroorzaken.

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)

Documenteren met LDoc

Een veelgebruikte conventie voor het documenteren van Lua-modules zijn opmerkingen in LDoc-stijl met het voorvoegsel ---. Hoewel de taal dit niet afdwingt, kunnen hulpmiddelen voor het genereren van documentatie dankzij deze opmerkingen automatisch documentatie van de programmeerinterface maken.

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

Modules testen

Test een module door hem te vereisen en elke functie te gebruiken. Gebruik een eenvoudige testrunner of busted (het Lua-testframework). Bewaar tests in een apart bestand dat het pad van de module weerspiegelt.

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

Modules samenstellen

Complexe systemen stellen meerdere modules samen. Een hoofdingang vereist submodules en verbindt ze met elkaar. Deze scheiding van verantwoordelijkheden houdt elke module doelgericht en afzonderlijk testbaar.

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

Korte controle

Wat is het belangrijkste doel van het modulepatroon local M = {} ... return M?

Samenvatting: aanbevolen werkwijzen voor modules

Samenvatting:

  • Gebruik altijd local M = {} ... return M
  • Privé = lokale waarden op bestandsniveau; openbaar = velden van M
  • Singleton: require slaat de module-instantie op in de cache
  • Gebruik fabrieksfuncties voor status per instantie
  • Bevries modules met __newindex om wijzigingen te voorkomen
  • Test in afzonderlijke bestanden; documenteer met opmerkingen die beginnen met ---
Gratis beginnen

Leer Lua met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
40
Lessen
159

Veelgestelde vragen

Is de les “Modulepatronen en best practices” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Lua Academy, waaronder “Modulepatronen en best practices”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Lua Academy bevat in totaal 4 lessen.

Wat leer ik in “Modulepatronen en best practices”?

Gebruik het patroon local M = {} en stel een openbare API overzichtelijk beschikbaar Je oefent met Lua Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Lua Academy te beginnen?

Ervaring vooraf is niet nodig. Lua Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Modulepatronen en best practices”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Lua Academy?

Ja. Elke les over Lua Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. De functie require
  2. Een modulebestand schrijven
  3. package.path en package.cpath
  4. Modulepatronen en best practices
← Terug naar Lua Academy