寫在前面:HiBlock區塊鏈社區成立了翻譯小組,翻譯區塊鏈相關的技術文檔及資料,本文爲Solidity文檔翻譯的第十部分《風格指南》,特發佈出來邀請solidity愛好者、開發者作公開的審校,您能夠添加微信baobaotalk_com,驗證輸入「solidity」,而後將您的意見和建議發送給咱們,也能夠在文末「留言」區留言,有效的建議咱們會採納及合併進下一版本,同時將送一份小禮物給您以示感謝。python
本指南旨在約定 solidity 代碼的編碼規範。本指南是不斷變化演進的,舊的、過期的編碼規範會被淘汰, 而新的、有用的規範會被添加進來。api
許多項目會實施他們本身的編碼風格指南。如遇衝突,應優先使用具體項目的風格指南。數組
本風格指南中的結構和許多建議是取自 python 的 pep8 style guide(https://www.python.org/dev/peps/pep-0008/) 。安全
本指南並 不是 以指導正確或最佳的 solidity 編碼方式爲目的。本指南的目的是保持代碼的 一致性。 來自 python 的參考文檔 pep8 。 很好地闡述了這個概念。微信
風格指南是關於一致性的。重要的是與此風格指南保持一致。但項目中的一致性更重要。一個模塊或功能內的一致性是最重要的。 但最重要的是:知道何時不一致 —— 有時風格指南不適用。若有疑問,請自行判斷。看看其餘例子,並決定什麼看起來最好。並應堅決果斷地詢問他人!app
縮進ide
每一個縮進級別使用4個空格。函數
製表符或空格學習
空格是首選的縮進方法。區塊鏈
應該避免混合使用製表符和空格。
空行
在 solidity 源碼中合約聲明之間留出兩個空行。
正確寫法:
contract A { ... } contract B { ... } contract C { ... }
錯誤寫法:
contract A { ... } contract B { ... } contract C { ... }
在一個合約中的函數聲明之間留有一個空行。
在相關聯的各組單行語句之間能夠省略空行。(例如抽象合約的 stub 函數)。
正確寫法:
contract A { function spam() public; function ham() public; } contract B is A { function spam() public { ... } function ham() public { ... } }
錯誤寫法:
contract A { function spam() public { ... } function ham() public { ... } }
代碼行的最大長度
基於 PEP 8 recommendation ,將代碼行的字符長度控制在 79(或 99)字符來幫助讀者閱讀代碼。
折行時應該聽從如下指引:
第一個參數不該該緊跟在左括號後邊
用一個、且只用一個縮進
每一個函數應該單起一行
結束符號 ); 應該單獨放在最後一行
函數調用
正確學法:
thisFunctionCallIsReallyLong( longArgument1, longArgument2, longArgument3 ); No: thisFunctionCallIsReallyLong(longArgument1, longArgument2, longArgument3 ); thisFunctionCallIsReallyLong(longArgument1, longArgument2, longArgument3 ); thisFunctionCallIsReallyLong( longArgument1, longArgument2, longArgument3 ); thisFunctionCallIsReallyLong( longArgument1, longArgument2, longArgument3 ); thisFunctionCallIsReallyLong( longArgument1, longArgument2, longArgument3);
賦值語句
正確寫法:
thisIsALongNestedMapping[being][set][to_some_value] = someFunction( argument1, argument2, argument3, argument4 ); No: thisIsALongNestedMapping[being][set][to_some_value] = someFunction(argument1, argument2, argument3, argument4);
事件定義和事件發生
正確寫法:
event LongAndLotsOfArgs( adress sender, adress recipient, uint256 publicKey, uint256 amount, bytes32[] options ); LongAndLotsOfArgs( sender, recipient, publicKey, amount, options ); No: event LongAndLotsOfArgs(adress sender, adress recipient, uint256 publicKey, uint256 amount, bytes32[] options); LongAndLotsOfArgs(sender, recipient, publicKey, amount, options);
源文件編碼格式
首選 UTF-8 或 ASCII 編碼。
Imports 規範
Import 語句應始終放在文件的頂部。
正確寫法:
import "owned"; contract A { ... } contract B is owned { ... }
錯誤寫法:
contract A { ... } import "owned"; contract B is owned { ... }
函數順序
排序有助於讀者識別他們能夠調用哪些函數,並更容易地找到構造函數和 fallback 函數的定義。
函數應根據其可見性和順序進行分組:
構造函數
fallback 函數(若是存在)
外部函數
公共函數
內部函數和變量
私有函數和變量
在一個分組中,把 view 和 pure 函數放在最後。
正確寫法:
contract A { function A() public { ... } function() public { ... } // External functions // ... // External functions that are view // ... // External functions that are pure // ... // Public functions // ... // Internal functions // ... // Private functions // ... }
錯誤寫法:
contract A { // External functions // ... // Private functions // ... // Public functions // ... function A() public { ... } function() public { ... } // Internal functions // ... }
表達式中的空格
在如下狀況下避免無關的空格:
除單行函數聲明外,緊接着小括號,中括號或者大括號的內容應該避免使用空格。
正確寫法:
spam(ham[1], Coin({name: "ham"}));
錯誤寫法:
spam( ham[ 1 ], Coin( { name: "ham" } ) );
除外
function singleLine() public { spam(); }
緊接在逗號,分號以前:
正確寫法:
function spam(uint i, Coin coin) public;
錯誤寫法:
function spam(uint i , Coin coin) public ;
賦值或其餘操做符兩邊多於一個的空格:
正確寫法:
x = 1; y = 2; long_variable = 3;
錯誤寫法:
x = 1; y = 2; long_variable = 3;
fallback 函數中不要包含空格:
正確寫法:
function() public { ... } 錯誤寫法: function () public { ... }
控制結構
用大括號表示一個合約,庫、函數和結構。 應該:
開括號與聲明應在同一行。
閉括號在與以前函數聲明對應的開括號保持同一縮進級別上另起一行。
開括號前應該有一個空格。
正確寫法:
contract Coin { struct Bank { address owner; uint balance; } }
錯誤寫法:
contract Coin { struct Bank { address owner; uint balance; } }
對於控制結構 if, else, while, for 的實施建議與以上相同。
另外,諸如 if, else, while, for 這類的控制結構和條件表達式的塊之間應該有一個單獨的空格, 一樣的,條件表達式的塊和開括號之間也應該有一個空格。
正確寫法:
if (...) { ... } for (...) { ... }
錯誤寫法:
if (...) { ... } while(...){ } for (...) { ...;}
對於控制結構, 若是 其主體內容只包含一行,則能夠省略括號。
正確寫法:
if (x < 10) x += 1;
錯誤寫法:
if (x < 10) someArray.push(Coin({ name: 'spam', value: 42 }));
對於具備 else 或 else if 子句的 if 塊, else 應該是與 if 的閉大括號放在同一行上。 這一規則區別於 其餘塊狀結構。
正確寫法:
if (x < 3) { x += 1; } else if (x > 7) { x -= 1; } else { x = 5; } if (x < 3) x += 1; else x -= 1;
錯誤寫法:
if (x < 3) { x += 1; } else { x -= 1; }
函數聲明
對於簡短的函數聲明,建議函數體的開括號與函數聲明保持在同一行。
閉大括號應該與函數聲明的縮進級別相同。
開大括號以前應該有一個空格。
正確寫法:
function increment(uint x) public pure returns (uint) { return x + 1; } function increment(uint x) public pure onlyowner returns (uint) { return x + 1; }
錯誤寫法:
function increment(uint x) public pure returns (uint) { return x + 1; } function increment(uint x) public pure returns (uint){ return x + 1; } function increment(uint x) public pure returns (uint) { return x + 1; } function increment(uint x) public pure returns (uint) { return x + 1;}
你應該嚴格地標示全部函數的可見性,包括構造函數。
正確寫法:
function explicitlyPublic(uint val) public { doSomething(); }
錯誤寫法:
function implicitlyPublic(uint val) { doSomething(); }
函數的可見性修飾符應該出如今任何自定義修飾符以前。
正確寫法:
function kill() public onlyowner { selfdestruct(owner); }
錯誤寫法:
function kill() onlyowner public { selfdestruct(owner); }
對於長函數聲明,建議將每一個參數獨立一行並與函數體保持相同的縮進級別。閉括號和開括號也應該 獨立一行並保持與函數聲明相同的縮進級別。
正確寫法:
function thisFunctionHasLotsOfArguments( address a, address b, address c, address d, address e, address f ) public { doSomething(); }
錯誤寫法:
function thisFunctionHasLotsOfArguments(address a, address b, address c,address d, address e, address f) public { doSomething(); } function thisFunctionHasLotsOfArguments(address a, address b, address c, address d, address e, address f) public { doSomething(); } function thisFunctionHasLotsOfArguments( address a, address b, address c, address d, address e, address f) public { doSomething(); }
若是一個長函數聲明有修飾符,那麼每一個修飾符應該下沉到獨立的一行。
正確寫法:
function thisFunctionNameIsReallyLong(address x, address y, address z) public onlyowner priced returns (address) { doSomething(); } function thisFunctionNameIsReallyLong( address x, address y, address z, ) public onlyowner priced returns (address) { doSomething(); }
錯誤寫法:
function thisFunctionNameIsReallyLong(address x, address y, address z) public onlyowner priced returns (address) { doSomething(); } function thisFunctionNameIsReallyLong(address x, address y, address z) public onlyowner priced returns (address) { doSomething(); } function thisFunctionNameIsReallyLong(address x, address y, address z) public onlyowner priced returns (address) { doSomething(); }
多行輸出參數和返回值語句應該聽從 代碼行的最大長度 一節的說明。
正確寫法:
function thisFunctionNameIsReallyLong( address a, address b, address c ) public returns ( address someAddressName, uint256 LongArgument, uint256 Argument ) { doSomething() return ( veryLongReturnArg1, veryLongReturnArg2, veryLongReturnArg3 ); }
錯誤寫法:
function thisFunctionNameIsReallyLong( address a, address b, address c ) public returns (address someAddressName, uint256 LongArgument, uint256 Argument) { doSomething() return (veryLongReturnArg1, veryLongReturnArg1, veryLongReturnArg1);}
對於繼承合約中須要參數的構造函數,若是函數聲明很長或難以閱讀,建議將基礎構造函數像多個修飾符的風格那樣 每一個下沉到一個新行上書寫。
正確寫法:
contract A is B, C, D { function A(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { // do something with param5 } }
錯誤寫法:
contract A is B, C, D { function A(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { // do something with param5 } } contract A is B, C, D { function A(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { // do something with param5 } }
當用單個語句聲明簡短函數時,容許在一行中完成。
容許:
function shortFunction() public { doSomething(); }
這些函數聲明的準則旨在提升可讀性。 由於本指南不會涵蓋全部內容,做者應該自行做出最佳判斷。
映射
待定
變量聲明
數組變量的聲明在變量類型和括號之間不該該有空格。
正確寫法:
uint[] x;
錯誤寫法:
uint [] x;
其餘建議
正確寫法:
str = "foo"; str = "Hamlet says, 'To be or not to be...'";
錯誤寫法:
str = 'bar'; str = '"Be yourself; everyone else is already taken." -Oscar Wilde';
正確寫法:
x = 3; x = 100 / 10; x += 3 + 4; x |= y && z;
錯誤寫法:
x=3; x = 100/10; x += 3+4;x |= y&&z;
正確寫法:
x = 2**3 + 5; x = 2*y + 3*z; x = (a+b) * (a-b);
錯誤寫法:
x = 2** 3 + 5; x = y+z; x +=1;
當徹底採納和使用命名規範時會產生強大的做用。 當使用不一樣的規範時,則不會當即獲取代碼中傳達的重要 元 信息。
這裏給出的命名建議旨在提升可讀性,所以它們不是規則,而是透過名稱來嘗試和幫助傳達最多的信息。
最後,基於代碼庫中的一致性,本文檔中的任何規範老是能夠被(代碼庫中的規範)取代。
命名方式
爲了不混淆,下面的名字用來指明不一樣的命名方式。
b (單個小寫字母)
B (單個大寫字母)
lowercase (小寫)
lower_case_with_underscores (小寫和下劃線)
UPPERCASE (大寫)
UPPER_CASE_WITH_UNDERSCORES (大寫和下劃線)
CapitalizedWords (駝峯式,首字母大寫)
mixedCase (混合式,與駝峯式的區別在於首字母小寫!)
Capitalized_Words_With_Underscores (首字母大寫和下劃線)
..注意:: 當在駝峯式命名中使用縮寫時,應該將縮寫中的全部字母都大寫。 所以 HTTPServerError 比 HttpServerError 好。
當在混合式命名中使用縮寫時,除了第一個縮寫中的字母小寫(若是它是整個名稱的開頭的話)之外,其餘縮寫中的字母均大寫。 所以 xmlHTTPRequest 比 XMLHTTPRequest 更好。
應避免的名稱
l - el的小寫方式
O - oh的大寫方式
I - eye的大寫方式
切勿將任何這些用於單個字母的變量名稱。 他們常常難以與數字 1 和 0 區分開。
合約和庫名稱
合約和庫名稱應該使用駝峯式風格。好比:SimpleToken,SmartBank,CertificateHashRepository,Player。
結構體名稱
結構體名稱應該使用駝峯式風格。好比:MyCoin,Position,PositionXY。
事件名稱
事件名稱應該使用駝峯式風格。好比:Deposit,Transfer,Approval,BeforeTransfer,AfterTransfer。
函數名稱
函數名稱不一樣於結構,應該使用混合式命名風格。好比:getBalance,transfer,verifyOwner,addMember,changeOwner。
函數參數命名
函數參數命名應該使用混合式命名風格。好比:initialSupply,account,recipientAddress,senderAddress,newOwner。 在編寫操做自定義結構的庫函數時,這個結構體應該做爲函數的第一個參數,而且應該始終命名爲 self。
局部變量和狀態變量名稱
使用混合式命名風格。好比:totalSupply,remainingSupply,balancesOf,creatorAddress,isPreSale,tokenExchangeRate。
常量命名
常量應該全都使用大寫字母書寫,並用下劃線分割單詞。好比:MAX_BLOCKS,TOKEN_NAME,TOKEN_TICKER,CONTRACT_VERSION。
修飾符命名
使用混合式命名風格。好比:onlyBy,onlyAfter,onlyDuringThePreSale。
枚舉變量命名
在聲明簡單類型時,枚舉應該使用駝峯式風格。好比:TokenGroup,Frame,HashStyle,CharacterLocation。
避免命名衝突
當所起名稱與內建或保留關鍵字相沖突時,建議照此慣例在名稱後邊添加下劃線。
通常建議
待定
延伸閱讀:智能合約-Solidity官方文檔(1)
根據例子學習Solidity-Solidity官方文檔(3)
深刻理解Solidity之源文件及合約結構——Solidity中文文檔(4)
應用二進制接口(ABI) 說明——Solidity中文文檔(7)
點擊「閱讀原文」便可查看完整中文文檔
注:本文爲solidity翻譯的第十部分《風格指南》,特發佈出來邀請solidity愛好者、開發者作公開的審校,您能夠添加微信baobaotalk_com,驗證輸入「solidity」,而後將您的意見和建議發送給咱們,也可在文末「留言」區留言,或經過原文連接訪問咱們的Github。有效的建議咱們會收納並及時改進,同時將送一份小禮物給您以示感謝。
本文內容來源於HiBlock區塊鏈社區翻譯小組,感謝全體譯者的辛苦工做。點擊「閱讀原文」便可查看完整中文文檔。
線上課程推薦
線上課程:《8小時區塊鏈智能合約開發實踐》
培訓講師:《白話區塊鏈》做者 蔣勇
課程原價:999元,現價 399元
更多福利: