Last active
January 4, 2018 07:59
-
-
Save czlc/4eb8d65eea94d2dbba6d534367e6e436 to your computer and use it in GitHub Desktop.
Revisions
-
czlc renamed this gist
Jan 4, 2018 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
czlc created this gist
Jan 4, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,361 @@ # Lua 代码风格指南 ## 格式化 * 行首使用4字母缩进(Lua 推荐的是2字母) * 行长度不要超过80个字符 * 不要用分号避免换行 ```lua -- bad local whatever = 'sure'; a = 1; b = 2 -- good local whatever = 'sure' a = 1 b = 2 ``` * 不要因为代码块较短,就写成一行 ```lua -- bad local print_table = function(t) for _,v in ipairs(t) do print(v) end end -- good local print_table = function(t) for _,v in ipairs(t) do print(v) end end ``` * `{`,`}`,及所有运算符前后应留一个空格 ```lua -- bad local test={one=1} local thing=1 thing = thing-1 thing = thing*1 thing = 'string'..'s' --good local test = { one = 1 } local thing = 1 thing = thing - 1 thing = thing * 1 thing = 'string' .. 's' ``` * `(`, `)` 前后不留空格 * 逗号后空一格 * 代码块之间留一个空行 ```lua -- bad if thing then -- ...stuff... end function derp() -- ...stuff... end local wat = 7 -- good if thing then -- ...stuff... end function derp() -- ...stuff... end local wat = 7 ``` * 字符串推荐使用双引号(") ## 命名规则 * 作用范围越大的变量、函数,名字应该越具体(即越长) * 文件、变量、函数名称遵循`snake_case`规则 >> https://en.wikipedia.org/wiki/Snake_case ```lua -- bad local OBJEcttsssss = {} local thisIsMyObject = {} local this-is-my-object = {} local c = function() -- ...stuff... end -- good local this_is_my_object = {} local function do_that_thing() -- ...stuff... end ``` * 常量名称使用全大写字母,单词之间用下划线分隔 ```lua --good local MAX_COUNT = 200 ``` * 下划线开头的变量名保留给lua内部使用,如`_G` 和 `_ENV` * 使用单下划线表示忽略的变量 ```lua --good for _, name in pairs(names) do -- ...stuff... end ``` * 类、模块名称遵循`PascalCase`规则 >> https://en.wikipedia.org/wiki/PascalCase ```lua -- bad local date = require('date') local mongo_obj = require "mongo_obj" -- good local Date = require('date') local MongoObj = require "mongo_obj" ``` ## 特性 * 不要使用隐式类型转换 ```lua local input_value = '4' -- bad local total_score = review_score .. '' local val = input_value * 1 -- good local total_score = tostring(review_score) local val = tonumber(input_value) ``` * 除了错误处理分支,尽量不用`debug`库 ## 变量 * 变量声明时总是使用`local`, 避免产生全局变量 * 不要定义不使用的变量;忽略的变量命名为`_`; * 不要使用未定义变量 * 在作用域的顶部给变量赋值,避免随用随取 ```lua -- bad for _, item in ipairs(items) do if item.score > player:get_score() then -- do something end end -- good local score = player:get_score() for _, item in ipairs(items) do if item.score > score then -- do something end end ``` * 合理减小变量的作用域 ```lua -- bad local v, x, y, z if condition then x = u2*v3-u3*v2 y = u3*v1-u1*v3 z = u1*v2-u2*v1 v = {x,y,z} end -- good local v if condition then local x = u2*v3-u3*v2 local y = u3*v1-u1*v3 local z = u1*v2-u2*v1 v = {x,y,z} end ``` ## 函数 * 函数声明时总是使用`local`, 避免产生全局函数 ```lua -- bad function foo() -- stuff end -- good local function foo() -- stuff end ``` * 优先使用函数语法;避免产生匿名函数 ```lua -- bad local nope = function(name, options) -- ...stuff... end -- good local function yup(name, options) -- ...stuff... end ``` * 早失败,早返回; 减少嵌套层次; ```lua -- bad local function is_good_name(name) if #name >= 3 then if #name <= 30 then if not string.match(name, "%u") then return true end end end return false end -- good local function is_good_name(name, options, args) if #name < 3 or #name > 30 or string.match(name, "%u") then return false end return true end ``` * 函数循环复杂度尽量低于10,不应超过15 >> 循环复杂度定义: https://zh.wikipedia.org/wiki/%E5%BE%AA%E7%92%B0%E8%A4%87%E9%9B%9C%E5%BA%A6 ## 类 * 建议优先使用`OOP`模式设计系统 * 类的私有成员函数名字使用下划线开头 * 模块不要直接返回非基类 * 类的对象应使用同一个元表 ```lua -- bad -- foo.lua local mt = {} function mt:_do_foo() -- stuff end function mt:foo() -- stuff self:_do_foo() -- stuff end local M = {} function M.new_obj() local obj = { -- stuff } return setmetatable(obj, {__index=mt}) end return M -- good -- foo.lua local mt = {} mt.__index = mt function mt:_do_foo() -- stuff end function mt:foo() -- stuff self:_do_foo() -- stuff end local M = {} function M.new_obj() local obj = { -- stuff } return setmetatable(obj, mt) end return M ``` * 外部不要直接访问/修改类的成员变量; 如果外部需要频繁访问类的成员变量,需要考虑一下类的内聚性。 ```lua -- bad local obj = new_obj() print(obj.score) obj.score = 5 -- good local obj = new_obj() print(obj:get_score()) obj:set_score(5) ``` ## 模块 * 模块总是返回一个`table` * 建议模块内待返回的`table`使用`local M = {}`声明方式 ## 头文件 * 通过`require`引用的模块,应该按照通用性由高到底排序 * 通用模块、业务模块、服务内模块之间应使用空行分隔 ```lua -- bad local RoomApi = require "room_api" local RoomConst = require "war_room.const" local Env = require "global" local Date = require "date" local Log = require "log" -- good local Log = require "log" local Date = require "date" local RoomApi = require "room_api" local RoomConst = require "war_room.const" local Env = require "global" ``` ## skynet * 不要在循环中调用别的服务;`call`和`send`都应避免 ```lua -- bad for _, item in ipairs(items) do Skynet.call(addr, "lua", "add_item", {item_id=item.item_id}) end -- good local request = {} for _, item in ipairs(items) do table.insert(request, {item_id=item.item_id}) end Skynet.call(addr, "lua", "add_items", request) ``` * 不要在循环中进行`io`操作 ## 参考 1. [Lua Style [email protected]](http://lua-users.org/wiki/LuaStyleGuide) 2. [Lua Style [email protected]/Olivine-Labs](https://github.com/Olivine-Labs/lua-style-guide/blob/master/README.md)