lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 29 August 2016 at 10:57, tyrondis <tyrondis@icloud.com> wrote:
> Hey *,
>
> I would like to get your experiences on how you write and maintain code that goes beyond a simple script and make sure that it is stable, bug-free (ideally) and does not break from any chances.
>
> I chose Corona SDK as a game engine for a game I want to write and it uses Lua as its scripting language. I really like the language, however, coming from a mostly statically typed language background (Java, C++, C#) I always feel a bit insecure about my Lua code. There is this constant feeling of uncertainty about whether I broke something with a change and I will not discover it because I do not happen to bring the interpreter to that exact spot to trigger the issue.
>
> By no means I want to start a debate about dynamically vs statically typed languages. I like both approaches and I enjoy Lua a lot. I simply want to get some best practices on how to write great quality Lua code on a larger scale.
>
> Having a great coverage of unit tests would be a great start, however, it is a bit difficult with Corona, as most of its APIs (Graphics, Audio, etc.) are only available inside the embedded system and I do not want to mock everything.
>
> Looking forward to a great discussion.
> Tyrondis

I use luacheck (https://github.com/mpeterv/luacheck) on all commits
and in my editor
(https://github.com/SublimeLinter/SublimeLinter-luacheck).
I also run unit tests on every commit. I use busted
(http://olivinelabs.com/busted/) to structure my tests.
See http://daurnimator.com/post/134519891749/testing-pre-commit-with-git

Otherwise the best thing I can recommend is to use fewer abstractions.
Less abstractions leads to fewer broken assumptions, and hence less
broken code.
I advocate an extremely simple 'object' style for lua code,
implementing from primitives on each use
Usually I place one 'class' per file, hence my lua files often look like:


local somelib = require "somedependency"

local function someutilfunction(x)
   return x + 1
end

local methods = {}
local mt = {
    __name = "mytype";
    __index = methods;
};

local function new(options)
   return setmetatable({foo = options.foo or "default"}, mt)
end

local function otherconstructor()
   return new({foo="special"})
end

function methods:bar()
    return someutilfunction(somelib.afunction(self.foo))
end

return {
    someutilfunction = someutilfunction;

    new = new;
    otherconstructor = otherconstructor;
}