好的lua代码风格
寫代碼也有風格?
當然,寫代碼就跟寫文章一樣,每個人或多或少都有自己的風格。不同的語言也就像不同的文體一樣,也有自己的獨特的風格。Lua是一門腳本語言,寫起來輕松愜意,但不代表它沒有屬于自己的風格指南。
好的代碼風格基于可讀性和一致性。代碼更多的時間是給人看的,如果思考好了結構和邏輯,寫代碼的過程其實很快。風格的一致性也很重要,這樣可以減少復雜度和理解成本。養成一種良好的代碼風格會形成一種良好寫代碼習慣,這種習慣會使編碼事半功倍。
下文將從命名,作用域,模塊,注釋和慣用法(精巧用法)等方面來說明Lua的代碼風格,文章的最后會附上一些參考資料的鏈接以供讀者拓展閱讀。
命名
最好的代碼是自說明代碼,這種代碼不需要多余的注釋,其本身便具備了描述作者意圖的信息。一種好的命名風格是自說明代碼的基礎。
命名法
駝峰命名法
小駝峰式命名法:第一個單字以小寫字母開始;第二個單字的首字母大寫,例如:firstName、lastName。
大駝峰式命名法:每一個單字的首字母都采用大寫字母,例如:FirstName、LastName、CamelCase,也被稱為Pascal命名法。
下劃線命名法
小下劃線命名法:所有字母均為小寫,例如登錄按鈕:login_btn。
大下劃線命名法:所有字母均為大寫,常見于常量,例如:最小間隔時間MIN_GAP_TIME。
采用駝峰法或者下劃線法都不太重要,重要的是你采用了自己喜歡的一種命名法,然后一直保持下去。
變量名長度
通常作用域范圍更大的變量名要比作用域范圍更小的變量名具有更多的描述信息。例如:i經常用于循環中充當計數變量,而將其作為全局變量使用容易導致諸多問題。
變量命名
對于變量(包括函數),小駝峰式命名法或小下劃線命名法是一個好選擇。比如:curSpeed表示當前速度,canDrop表示是否能掉落等等。
對于布爾值型的變量,通常前綴加上is可以方便理解,比如isRemoved比Removed更加能表示這是一個布爾值變量。
Lua中有一種特殊的變量名:_,常用來表示可以被忽略的、不會使用到的變量,常使用在循環中。
– _表示表的鍵可以被忽略,只在循環內使用表中的值v
在表的循環中和函數參數列表中,i常表示ipairs下的數組下標,k常表示pairs下的鍵,v常表示對應的值,t則表示表。
for k,v in pairs(t) do ... end for i,v in ipairs(t) do ... end mt.__newindex = function(t, k, v) ... end常數命名
Lua里沒有嚴格的常數定義標識符,所以對于常數的命名格外重要。
常數一般采用大下劃線命名法。這樣每個字母都大寫,十分醒目,且各個單詞都用下劃線分割,便于閱讀。
比如:MAX_SPEED表示最大速度,IS_SHOW_DEBUG_ERROR_MSG表示是否顯示報錯消息等等。
類名
為了不與變量名和常數名混淆,類名通常使用大駝峰式命名法,即首字母大寫。比如:TouchManager表示觸摸管理器類。
包和模塊名
包名和模塊名通常很短,并且全部小寫,單詞間并沒有下劃線區分。比如:文件讀取庫名為lfs,表示Lua File System;XML解析庫名為lxp,表示Lua XML Parser等等。
文件名
通常為了不與類名混淆,對于文件名,經常使用小駝峰式命名法或小下劃線命名法。
作用域
Lua的作用域以關鍵字end進行標識。
對于變量,有一條原則:在一切能使用local修飾的情況下,使用local進行修飾。
因為不用local修飾的變量會自動變成全局變量。全局變量十分危險,很容易被篡改而不知道在哪里被篡改了,這很容易導致頑固的bug出現。并且全局變量的處理速度也比局部變量的速度要慢很多。
所以,盡可能的用local來修飾變量。
有時候,用do .. end可以用來明確限定局部變量的作用域。
local v dolocal x = u2*v3-u3*v2local y = u3*v1-u1*v3local z = u1*v2-u2*v1v = {x,y,z}`這里寫代碼片` end -- x,y,z的作用域結束,被系統清理 local count dolocal x = 0count = function() x = x + 1; return x end end -- x的作用域結束,被系統清理 模塊Lua中有一個叫module的公有函數,此函數的作用是將一組變量和函數打包在一個模塊名下,便于其他文件require。但是這個函數受到了諸多的指責,原因是其會創建一個公共變量,并且這個公共變量中的所有細節都會暴露出來。這其實十分不符合面向對象的規范。
以下有一種辦法可以避免這個問題,即不采用module函數進行打包。
-- hello/mytest.lualocal M = {} -- 私有變量local function test() print(123) end function M.test1() test() end function M.test2() M.test1(); M.test1() endreturn M -- 關鍵以下是導入此模塊的方法。
local MT = require "hello.mytest" MT.test2()Lua內沒有類這個變量類型,但是通過Lua的metatable可以輕松實現類的繼承,多態等等特性。關于Lua中類的實現原理,請參考我之前寫的這篇博客:Lua中實現類的原理。
注釋
通常在–前加上一個空格。
return nil -- not found (建議) return nil --not found (不建議)注釋通常用在函數接口,或者復雜,精巧的邏輯上。
對于接口的注釋,可以按照javadoc類似的來寫。
-- Deletes a session. -- @param id Session identification. ------------------------------------- function delete (id) assert (check_id (id)) remove (filename (id)) end慣用法(精巧用法)
盡可能使用local修飾變量(重要的事情要說三遍!)
原因:
使用local的變量會在作用域結束時釋放其內存
使用local的變量會比全局變量的存取更快
全局變量會污染全局的命名空間,可能會導致詭異的bug出現
直接判斷真假值
原因:Lua在邏輯判斷時將所有false和nil的邏輯判斷視為假,反之則全部視為真,不需要再與布爾值和nil進行顯式比對。
但是,在需要對false和nil進行區分時,需要寫明==:obj == nil和obj == false。
默認參數的實現
范式:param = param or defaultValue function setName(name)name = name or 'noName'-- ... end原因:or會在第一次為true的時候斷路,返回其判斷的最后一個值。所以當name為空時,name or ‘noName’返回為’noName’,這會將name的值自動設置為noName。
一行代碼實現表的拷貝
u = {unpack(t)}需要注意的是此法在表內條目大于2000時會失效。
一行代碼判斷表是否為空
用#t == 0并不能判斷表是否為空,因為#預算符會忽略所有不連續的數字下標和非數字下標。
正確做法是:
if next(t) == nil then -- 表為空-- ... end因為表的鍵可能為false,所以必須與nil比較,而不直接使用~next(t)來判斷表是否空。
更快的插入代碼
– 更慢,不推薦
– 更快,推薦
t[#t+1] = value原因:[]和#避免了高層的函數調用開銷。
參考資料
這篇文章是基于Lua Style Guide而來。
語言的風格大致是通用的,在Python里,有一種叫pythonic的代碼風格,詳見:讓你的python代碼更加pythonic。
對于任何程序員,我都力薦《代碼大全》這本書。在里面,你可以找到十分完備的從設計,架構到具體編碼,注釋,到團隊協作等等相關的引導。
還有幾本書:《程序員修煉之道》,《高效程序員的45個習慣》,《重構》。它們可以作為《代碼大全》的補集存在。
關于《高效程序員的45個習慣》這本書,我進行了總結和提煉,閱讀之前不妨看看這篇讀書筆記。
文章轉自:(http://wuzhiwei.net/lua_style_guide/)
總結
- 上一篇: cocos工程里面“”invalid '
- 下一篇: lua cocos 中对FNT字体的使用