Lua Modules Best Practice (Var, Function Scope)

Which is best?

m = {}

local var = 1

local function func()
    -- whatever
end

function m.do_stuff()
   func()
end

return m

or…

m = {}

m.var = 1

function m.func()
    -- whatever
end

function m.do_stuff()
   m.func() -- Don't know if this is the correct way to reference function of current table
end

return m

I’d use the module in the parent script like

local module = include('lib/module.lua')

I think that either is fine. It depends on whether you want to access var or func from a different file outside of your module (i.e. keep them “public” or “private”).

If only your module cares about referencing those, maybe it’s cleaner to keep them as locals.

you should also focus on readability and not reuse - the software industry became obsessed with reuse & modularity - which barely ever happens. This is often at the cost of the real issue which is when you come back to this code in 6 months time will you be able to figure out what it does? (which happens all the time).

The reason you want to prevent access to internals etc is normally you want the library to be a black box. You want to stop users (& that might include yourself) from doing evil things that might break if you change the implementation etc. All of which is well and good BUT if you are the only user of the module then that likely isn’t your key concern. Always think why you are doing something. That’s not to say you should be sloppy but adding complexity to code is adding bugs to code (in fact adding code to code is adding bugs to code :wink: ). ALWAYS aim for readable, simple and less code in preference to anything else. In this case the second one adds a little extra complexity - you need to think where is the var and function over seeing they are simply local to the module

IF you are making a commercial library then yeah some consideration should be given to reuse but otherwise making life easier for yourself when you are looking for bugs or making modifications should be the primary focus

6 Likes

Both are reasonable. In fact I do a combination of both in any given file. It depends on whether or not you want to expose variables and functions outside of your module. Some elements you might want to expose (second example), some you might want to hide from outside your module (first example).

Cool, thanks for your replies, all!

So a supplementary question or two spring to mind;

Browsing the code of @21echoes Cyrene script, I notice he’s using Lua’s OOP to create a class to handle UI pages.

What are the advantages to a more “pure” OOP, class-based approach over whatever it is I’m doing in my examples?

@junklight I do take your point about keeping things simple. I do like to reuse code in places where I find myself re-writing similar chunks of code multiple times in a given project, though.

By starting with class-style design, it’s easier to modify which parts of your object are public vs private as your app changes. I mean it’s not that hard either way, but… it’s still easier haha. I also wrote Pedalboard first, and there the UI classes really do leverage inheritance rather extensively (technically Lua isn’t “inheritance”, yadda yadda yadda), and they also went through a lot more iteration as I learned the platform (and Lua). It also allows you to distinguish between class methods/variables and instance methods/variables, if that’s useful in your case. Probably the final (and perhaps realest) reason: it’s what I’m comfortable with coming from my industry background :woman_shrugging:

That’s kinda what I expected, really. My background (such as it is) has been in functional, rather than OOP coding, historically, so I guess I’m more comfortable running arrays through functions, rather than creating objects with their own encapsulated properties and methods (though I also understand some of the advantages of this approach).

Any advice on when/if to use modules vs. classes?