最佳实践

       本节系统总结Lua在大型项目中的工程规范、性能优化黄金法则、可维护性策略以及Android平台特有的开发准则。

1. 代码组织

1.1 模块设计原则

-- 模块模板示例
local M = {}
local privateVar = "内部状态"

-- 公有API注释格式
--- 计算两个数的和
-- @param a number 第一个加数
-- @param b number 第二个加数
-- @return number 和
function M.add(a, b)
    validateNumber(a)
    validateNumber(b)
    return a + b
end

-- 私有方法
local function validateNumber(n)
    assert(type(n) == "number", "参数必须是数字")
end

return M

模块化准则:

1.2 目录结构

-- 推荐Android项目结构
/*
├── assets/
│   ├── lua/
│   │   ├── core/       # 核心库
│   │   │   ├── math.lua
│   │   │   └── stringx.lua
│   │   ├── app/        # 业务模块
│   │   │   ├── ui/
│   │   │   └── network/
│   │   └── main.lua    # 入口
├── res/
│   └── raw/
│       └── config.lua  # 静态配置
*/

目录规范:

2. 性能优化

2.1 热点优化

-- 性能关键代码示例
local function fastJoin(t, sep)
    local n = #t
    if n == 0 then return "" end
    local buf = {}
    buf[1] = t[1]
    for i = 2, n do
        buf[i] = sep
        buf[i+1] = t[i]
    end
    return table.concat(buf)
end

-- 预计算优化
local sqrt = math.sqrt  -- 缓存函数引用
local function distance(x1, y1, x2, y2)
    return sqrt((x2-x1)^2 + (y2-y1)^2)
end

优化法则:

2.2 内存管理

-- 对象池实现
local pool = {
    objects = {},
    get = function(self)
        return table.remove(self.objects) or {}
    end,
    recycle = function(self, obj)
        for k in pairs(obj) do obj[k] = nil end
        table.insert(self.objects, obj)
    end
}

-- 大内存使用提示
local ByteBuffer = luajava.bindClass("java.nio.ByteBuffer")
local buffer = ByteBuffer:allocateDirect(1024*1024)  -- 堆外内存

内存准则:

3. 错误处理

3.1 防御式编程

-- 参数验证模板
local function safeCall(fn, ...)
    local args = {...}
    return xpcall(fn, function(err)
        local trace = debug.traceback(err, 2)
        logError(trace)
        return Error:new("CALL_FAILED", trace)
    end, unpack(args))
end

-- 类型检查
local function checkType(val, typ, name)
    if type(val) ~= typ then
        error(string.format("%s应为%s类型,实际为%s",
              name, typ, type(val)), 3)
    end
end

健壮性原则:

3.2 日志策略

-- 分级日志系统
local Log = {
    LEVEL = {DEBUG=1, INFO=2, WARN=3, ERROR=4},
    threshold = 2,
    log = function(self, level, tag, msg)
        if level < self.threshold then return end
        local logMsg = string.format("[%s] %s: %s", 
            os.date("%H:%M:%S"), tag, msg)
        android.util.Log:println(level, "LUA/"..tag, msg)
    end
}

-- 使用示例
Log:log(Log.LEVEL.INFO, "Network", "请求开始")

日志规范:

4. Android集成

4.1 线程模型

-- 线程安全调用模板
local function runOnUiThread(fn)
    if isUiThread() then
        return fn()
    else
        local latch = java.util.concurrent.CountDownLatch(1)
        local result
        activity.runOnUiThread(luajava.createProxy("java.lang.Runnable", {
            run = function()
                result = {fn()}
                latch:countDown()
            end
        }))
        latch:await()
        return unpack(result)
    end
end

-- 后台任务执行器
local bgExecutor = java.util.concurrent.Executors.newFixedThreadPool(4)

线程准则:

4.2 资源管理

-- 自动释放模板
local function withResource(res, fn)
    local ok, result
    if type(res.open) == "function" then res:open() end
    ok, result = pcall(fn, res)
    if type(res.close) == "function" then res:close() end
    if not ok then error(result) end
    return result
end

-- 使用示例
withResource(openDatabase(), function(db)
    return db:query("SELECT * FROM users")
end)

资源规范:

5. 测试与维护

5.1 单元测试

-- 测试框架示例
local Test = {
    cases = {},
    add = function(self, name, fn)
        self.cases[name] = fn
    end,
    run = function(self)
        local pass, fail = 0, 0
        for name, test in pairs(self.cases) do
            local ok, err = pcall(test)
            if ok then
                pass = pass + 1
                print("✓ "..name)
            else
                fail = fail + 1
                print("✗ "..name..": "..err)
            end
        end
        print(string.format("通过%d, 失败%d", pass, fail))
    end
}

-- 测试用例
Test:add("math.add", function()
    assert(math.add(1,2) == 3)
end)

测试原则:

5.2 代码分析

-- 静态检查配置(.luacheckrc)
return {
    read_globals = {"android", "luajava"},
    globals = {"ARGV", "MODULE"},
    unused_args = false,
    redefined = false,
    max_line_length = 120
}

-- 常见Lint规则
local rules = {
    "避免使用全局变量",
    "函数长度不超过50行",
    "嵌套层次不超过4层",
    "圈复杂度小于10"
}

质量指标:

6. 团队协作

6.1 编码规范

-- 命名约定示例
local namingConventions = {
    variables = "lowerCamelCase",
    constants = "UPPER_SNAKE_CASE",
    functions = "lowerCamelCase",
    classes = "UpperCamelCase",
    modules = "lower_snake_case",
    private = "_prefixWithUnderscore"
}

-- 文件头模板
--- @module core.utils
-- @description 通用工具函数
-- @author 张三
-- @license MIT
-- @copyright 2023

规范要点:

6.2 版本控制

-- 语义化版本控制
local version = {
    major = 1,  -- 不兼容的API修改
    minor = 2,  -- 向下兼容的功能新增
    patch = 3   -- 向下兼容的问题修正
}

-- 变更日志示例
local changelog = [[
## [1.2.3] - 2023-06-01
### Added
- 新增网络超时配置
### Changed
- 优化内存使用
### Fixed
- 修复Android 13兼容问题
]]

协作准则:

7. 发布部署

7.1 构建优化

-- 编译脚本示例(build.lua)
local files = {
    "src/core/*.lua",
    "src/app/**/*.lua"
}

local function minify(code)
    -- 移除注释和空白
    return code:gsub("%-%-[^\n]*", ""):gsub("%s+", " ")
end

for _, pattern in ipairs(files) do
    for _, file in ipairs(glob(pattern)) do
        local minified = minify(readFile(file))
        writeFile("build/"..file, minified)
    end
end

构建原则:

7.2 热更新方案

-- 差分更新实现
local Hotfix = {
    VERSION = "1.2.3",
    checkUpdate = function(self)
        local remote = httpGet("https://api.example.com/version")
        if remote.version > self.VERSION then
            return remote.changes
        end
    end,
    applyPatch = function(self, patch)
        local loader, err = load(patch.code, "=(hotfix)")
        if not loader then
            error("加载补丁失败: "..err)
        end
        package.loaded[patch.module] = loader()
    end
}

-- 安全验证
local signature = verifySignature(patch.code, patch.sig)
if not signature then error("补丁签名无效") end

热更新准则: