1. 程式人生 > 實用技巧 >Lua程式碼規範

Lua程式碼規範

  每個語言都有他自己的程式碼規範,如何寫好一個易懂又美觀的程式碼,下面我們來學習一下。

空行

加空行:

  • 函式之間都要加空行;

  • 函式內部程式碼概念與邏輯之間,邏輯段落小節之間,都應該加空行;

  • 註釋行之前。

不加空行:

  • 在一個函式體內,邏揖上密切相關的語句之間不加空行;

  • 多行註釋解釋引數的時候,註釋之間不加空行。

空格

加空格:

  • ”and“,”or“等關鍵字前後留一個空格,便於辨析;

  • 逗號”,“後面要留一個空格;

  • 賦值操作符、比較操作符、算術操作符如”=“、 “==“、”~=“、”>=“、”<=“、”>“、”<“、”+“、”-“、”*“、”/“、”%“、”^“,等二元操作符的前後應當加空格;

  • if、for、while等關鍵字之後如果要加左括號”(“,關鍵字與左括號之間應留一個空格,以突出關鍵字;

不加空格:

  • 函式名之後不要留空格,緊跟左括號”(“;

  • 左括號”(” 向後緊跟,緊跟處不留空格;

  • 右括號”)“、逗號”,“、分號”;“,向前緊跟,緊跟處不留空格;

  • 字串連線符”..“前後不加空格;

  • “:“,”.“,”[“,”]“這類操作符前後不加空格;

程式碼示例

  1. a > b and a or b -- 良好的風格

  2. a > b and a or b -- 不良的風格

  3. local a, b, c, max -- 良好的風格

  4. local a,b,c,max -- 不良的風格

  5. if a > b then -- 良好的風格

  6. max = a

  7. end

  8. if a>b then max=a end -- 不良的風格

  9. data = dataTable[index] -- 良好的風格

  10. data = dataTable [ index ] -- 不良的風格

  11. function(posX, posY) -- 良好的風格

  12. function (posX,posY) -- 不良的風格

長行拆分

  • 程式碼行最大長度宜控制在70至80個字元以內。程式碼行不要過長,否則眼睛看不過來,也不便於列印;

  • 長表示式要在低優先順序操作符處拆分成新行,操作符放在新行之首(以便突出操作符)。

  1. -- 良好的風格

  2. local newBuindingBtn = UI.newButton({

  3. text = btnName,

  4. x = self.x,

  5. y = self.y,

  6. parent = self,

  7. style = {

  8. normal = ResConfig.png.commonBtnBlue

  9. }

  10. })

  11. -- 不良的風格

  12. local newBuindingBtn = UI.newButton({text = btnName,x = self.x,y = self.y,parent = self, style = {normal = ResConfig.png.commonBtnBlue}})

  13. -- 良好的風格

  14. if veryLongerVariable1 >= veryLongerVariable2

  15. and veryLongerVariable3 <= veryLongerVariable5

  16. and veryLongerVariable4 <= veryLongerVariable6 then

  17. doo()

  18. end

  19. -- 不良的風格

  20. if veryLongerVariable1 >= veryLongerVariable2 and veryLongerVariable3 <= veryLongerVariable5 and veryLongerVariable4 <= veryLongerVariable6 then

  21. doo()

  22. end

命名規則

共性規則

  • 命名應當直觀且可拼讀,可望文知意;

  • 識別符號的長度應當符合“min-length && max-information”原則;

  • 採用英文單詞或單詞組合,英文單詞不要複雜,但用詞需準確,切忌使用漢語拼音命名;

  • 切勿為了避免命名過長而隨意擷取單詞,以丟失可讀性;

  • 所有命名都不要與-x已有的命名風格衝突,例如不要以CC,UI開頭;

檔案命名

  • 所有Lua檔案的命名時使用大駝峰法;

  • 根據檔案的特性,一般以檔案裡的模組名或者類名作為同名檔名;

  • 確定命名前,請檢查下,不要跟其他檔案同名;

  • CCArmature.lua -- 不良的風格

  • UILayout.lua -- 不良的風格

類的命名

  • 所有類命名時使用大駝峰法;

  • 類名一般由”名詞”或”多名詞”組成,不要簡寫;

  • 根據類的特性,加上相關的字尾或者字首;

  • 管理類 Manager

  • 快取類 Cache

  • 控制類 Controller

  • 模組 Module

  • 網路類 Proxy

變數命名

  • 使用 “名詞” 或是 “形容詞+名詞” 命名;

  • 使用小駝峰法命名;

  • 為了可讀性,儘量避免變數名中出現標號,如value1, value2;

  • 不要出現僅靠部分字母大小寫區分的相似的變數;

  • 除非是區域性變數功能等價全域性變數,不然區域性變數不要與已有的全域性變數同名;

  • 儘量不要使用已有的類名作為變數名;

  1. local data -- 良好的風格

  2. local oldData -- 良好的風格

  3. local newData -- 良好的風格

  4. local pairs = pairs -- 良好的風格

  5. local posx,posX -- 不良的風格

  6. local btn1,btn2 -- 不良的風格

  7. local TABLE = {} -- 不良的風格

  8. local uILabel -- 不良的風格

類的成員變數

  • 類的成員變數以”self.”開頭,以區分於區域性變數;

例如:

  1. function init()

  2. self.mainPanel = false -- 常用格式

  3. topPanel = false -- 這樣是全域性變數,佔用全域性資源,而且難以區分於區域性變數

  4. ...

  5. end

全域性變數

全域性變數使用雙下劃線(““)開頭以及結尾,中間的命名以名詞拼接,或”形容詞+名詞”拼接,不同單詞之間用(”“)隔開; 例如: _VERSION_CODE = "1.0.0.0"

區域性變數

M常用做模組裡面表示模組本身

  1. module("MainGame.Module.IntegrationTest.MapModule",package.seeall)

  2. local M = class(SceneView,"MapScene")

  • 資料的初始化

  1. function M:init()

  2. ...

  3. end

  4. ...

  5. return M

  • 引用進來的類或模組,用大駝峰法命名,引用路徑統一帶括號;

  1. module(“MainGame.Module.IntegrationTest.MapModule”,package.seeall)

  2. local M = class(SceneView,”MapScene”)

  3. local Surface = require(“xx.xx”)

  4. local TestButtonPanel = require(“xx”)

臨時變數

  • 常用下劃線”_”作為可以忽略的變數

  1. for _,v in ipairs(t) do print(v) end

  2. i,k,v,t --常做臨時變數

  3. for k,v in pairs(t) ... end

  4. for i,v in ipairs(t) ... end

  5. mt.__newindex = function(t, k, v) ... end

常量,事件名的命名

常量,事件名所用單詞均大寫,單詞用下劃線(‘_‘)分割;

例如:

  1. -- 常量 預設寬度

  2. LIST_DEFAULT_WIDTH = 100

  3. -- 事件 新增到場景

  4. ADDED_TO_STAGE = getId()

列舉的命名

  • 列舉名命名,與類名命名一致;

  • 列舉值命名,與常量,事件名的命名一致;

例如:

  1. ControllerViewType = {

  2. SCENE = "SCENE",

  3. PANEL = "PANEL",

  4. POP = "POP",

  5. }

檔案組織

檔案描述

  • 檔案開頭加上此檔案的簡要功能作用描述;

  1. -- MapModule.lua

  2. --Author:xx

  3. --Email:xx@flamingo-inc.com

  4. --20xxxx xx:xx

  5. --Using:建立地圖

  6. module("MainGame.Module.IntegrationTest.MapModule",package.seeall)

  7. ...

檔案中變數的定義

如果在檔案中需要多次使用的某些匯入檔案,可以在檔案開頭用區域性變數儲存匯入資訊,而不是在每次使用的時候都重新匯入一次;

  1. ...

  2. local Surface = require("xx.xx")

  3. local TestButtonPanel = require("xx")

  4. function M:xx()

  5. local testBtn = TestButtonPanel.newCC()

  6. ...

  7. end

  8. function M:yy()

  9. local panel = TestButtonPanel.newCC()

  10. local surface = Surface.newCC()

  11. ...

  12. end

  13. ...

類變數的定義

  • 類中的成員變數需要在init中先宣告,並賦予初始值,不允許不宣告直接使用;

函式引數的定義

  • 所有函式的引數都用統一的params做引數,並加入如下格式的註釋:

  1. --[[

  2. 普通按鈕 可縮放 scale9

  3. @param #string text 按鈕名稱

  4. @param #table style 按鈕樣式

  5. ]]

  6. function UI.newButtonScale9(params)

  7. ...

  8. end

函式的定義規則

  • 函式的行數過長(大於 100 行)時,儘量拆分為多個子函式;

  • 函式中一些晦澀的部分,一定要加上註釋;

註釋的使用

  • 短小的註釋用–;

  • 長註釋用–[[]];

編碼技巧

應該儘量使用local變數而非global變數

  • 全域性變數實際是放入全域性表中,每次呼叫是用傳入變數名作為key去獲取,而local變數是直接通過lua的堆疊訪問的;

  • 在能用區域性變數解決的地方,不要使用全域性變數,這點很容易被忽略;

  • 多次重複使用的全域性介面,可以用區域性變數儲存下再使用;

  • 比如需要多重遍歷操作一個大表:

  1. for k1,v1 in pairs(tbl) do

  2. for k2,v2 in pairs(v1) do

  3. ...

  4. end

  5. end

  1. do

  2. local pairs = pairs

  3. for k1,v1 in pairs(tbl) do

  4. for k2,v2 in pairs(v1) do

  5. ...

  6. end

  7. end

  8. end

由於pairs是一個全域性變數應用的函式,所以寫法2在這裡有稍微效率上的提升,但要是單層遍歷的沒有這個效果了。

臨時變數的處理

  • 字串的連線 .. 由於字串的管理機制,字串在使用..連線時,會產生新的物件。由於lua在VM內對相同的string永遠只保留一份唯一copy。

例如:

  1. local description ""

  2. for i = 1,20 do

  3. description = description.."xxx"

  4. end

這樣會生成21份string的copy,但實際上我們只需要最後那一份 如果是輕量級的簡單連線還是可以使用的,因為影響不大,但要是大量的類似拼接,推薦使用string.format

類似於字串的管理機制,表也存在類似的臨時變數copy:

函式傳引數

  1. function func({x,y})

  2. ...

  3. end

這種傳參方式,每次都會生成一份copy,所以推薦以下的用法:

  1. function func(x,y)

  2. ...

  3. end

  4. function func({posX = x, posY = y})

  5. ...

  6. end

利用邏輯運算的短路效應

  • and or 的返回值是表示式中的左值或者右值,可用來簡化程式碼

  1. function foo(arg)

  2. arg = arg or "default"

  3. ...

  4. end

但要注意當賦值為bool值時候,容易出bug

  • a = a or true -- 錯誤的寫法,當 a 明確寫為 false 的時候,也會被改變成 true 。

  • a = a ~= false -- 正確的寫法,當 a 為 nil 的時候,被賦值為 true ;而 false 則不變。

另外,巧妙使用 and or 還可以實現類似 C 語言中的 ?: 三元操作:

  1. function max(a,b)

  2. return a > b and a or b

  3. end

這裡相當於 return (a > b) ? a : b;

程式碼建議

程式碼的除錯

用Luastudio工具除錯,代替Sublime除錯Lua程式碼;

複雜度和效能問題

寫程式碼時儘可能寫的簡單,考慮效能時先做好推斷,看看能提升多少,增加的複雜度以及造成的程式碼晦澀有多嚴重,然後再決定如何做;

函式的優化思考

  • 開銷大的函式,呼叫次數低的話,可以不做優化;

  • 開銷較小的函式,但呼叫頻率很高,則從如何降低呼叫頻率以及減少函式的開銷兩個角度去思考優化;

提交程式碼的檢查

提交程式碼前,在svn commit中驗證提交的程式碼,去掉或註釋掉無關的程式碼,保證提交的程式碼無誤;

表結構的引用

儘量減少表中的成員是另個表的引用;