[inBuilder x UBML]關于開發規范,一些可能要說的點(一)
開發規范(Development Standards)是軟件開發過程中至關重要的指導性文件,它定義了團隊在編碼、設計、測試、部署等環節的統一規則。對于這個詞而言,很多人可能只會將其與代碼規范劃為等號,簡單的理解為代碼風格一致,正確縮進,正確注釋等內容,但其作用不僅限于代碼風格的一致性,還涉及項目管理、質量保障、團隊協作等多個維度。在做項目時如果沒法做到開發規范,人員之間的相互對接就會出現困難,導致項目人月成本上升,成果交付困難。低代碼雖然在使用上涉及的代碼不是很多,如果只是短期簡單投入使用,開發規范確實不是特別重要,但在開發新模塊,版本維護等方面,開發規范依然是需要著重注意的點。
UBML開源社區官網內有20多個倉庫,涉及社區、文檔、項目代碼等方面。其中每一個區域的提交,維護等方面都涉及到規范,本篇文章主要談談這個開源社區的一些規范,順便進行宣傳與啟發——如何良好的規定規范。
1.代碼方面
1.1前端代碼規范
1.1.1 適用對象
適用對象為研發部門的設計人員、開發人員、測試人員、項目管理人員
1.1.2 適用范圍
適用于采用Angular + TypeScript技術開發的前端應用、以及基于inBuilder開發平臺開發的Web應用。
Angular Style Guide:https://angular.io/guide/styleguide
ECMA-262, Edition 5:http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf,http://www.ecma-international.org/publications
1.1.3 代碼書寫規范
1.1.3.1 注釋風格
推薦使用JSDoc注釋風格。JSDoc Toolkit是一個把Java Script代碼注釋格式化成文檔的工具。開發者只需按JSDoc的規范寫好注釋就可以很方便導出文檔。JSDoc Toolkit是google 推薦的 JSDoc生成工具。
1.1.3.1.1 文件注釋
文件注釋用于告訴不熟悉這段代碼的開發者這個文件中包含哪些內容。應該提供文件的概述、作者、依賴關系和兼容性信息。 如下:
/**
-
@fileoverview 處理Text Area 的工具類。
-
@author chenshj@inspur.com
*/
1.1.3.1.2 變量注釋
代碼中的變量要有必要的注釋,用來說明變量的類型以及變量的意義。
標記變量類型:
@type Type
@type {Type}
如:
/**
-
消息ID。
-
@type
*/
var messageId = messageId;
標記私有變量:
@private
如:
/**
-
日志監聽對象。
-
@type Array.
-
@private
*/
this.handlers_ = [];
定義枚舉值:
@enum {Type}
如:
/**
-
狀態值枚舉。
-
@enum
*/
project.TriState = {
TRUE: 1,
FALSE: -1,
MAYBE: 0
};
定義常量:
@const
如:
/**
-
最喜歡的啤酒。
-
@const
-
@type
*/
mynamespace.MY_BEER = ‘stout’;
1.1.3.1.3 類注釋
每個類的定義都要附帶一份注釋,描述類的功能和用法。也需要說明構造方法的參數,如果該類繼承自其它類,應該使用 @extends 標記。如果該類是對接口的實現,應該使用 @implements 標記。
標記構造函數:
@constructor
如:
/**
-
矩形區域。
-
@constructor
*/
Function Rect() {
…
}
標記類繼承:
@extends Type
@extends {Type}
如:
/**
-
空節點列表
-
@constructor
-
@extends BasicNodeList
*/
Function EmptyNodeList () {
…
};
標記實現接口:
@implements Type
@implements {Type}
如:
/**
-
圖形接口。
-
@interface
*/
function Shape() {};
Shape.prototype.draw = function() {};
/**
-
@constructor
-
@implements
*/
function Square() {};
Square.prototype.draw = function() {
…
};
1.1.3.1.4 方法與函數的注釋
方法與函數的注釋應提供參數的說明,使用完整的句子,并用第三人稱來書寫方法說明。
變量注釋:
@param {Type} 變量名 描述
如:
/**
-
查詢項目信息
-
@param {number} 分組ID
-
@param {string|number|null} 項目名稱或者ID,傳入null值查詢全部項目。
*/
function query (groupNum, term) {
// …
};
方法返回值:
@return {Type} 描述
如:
/**
- @return {string} 最后一個項目的ID。
*/
function getLastId () {
// …
return id;
};
標記保護方法:
@protected
如:
/**
-
設置組件的根元素。
-
@param {Element} 組件根元素
-
@protected
*/
function setElementInternal (element) {
// …
};
1.1.3.2 注釋規范
代碼注釋需要包含以下內容:
版權和著作權的信息。
文件注釋中應該寫明該文件的基本信息,如:這段代碼的功能摘要,如何使用,與哪些東西相關。
類,函數,變量要有必要的注釋。
1.1.3.2.1 單行注釋與多行注釋
單行注釋,即形式為“//”的注釋。單行注釋用于方法內的代碼注釋。如對局部變量聲明的注釋或代碼行、代碼段的注釋。單行注釋可單獨一行,如果僅僅針對一句注釋,且不影響換行,可放于代碼行后部;也可以用于臨時屏蔽不用的代碼行,在開發完畢后應及時清理。行內代碼的注釋應該使用單行注釋。
多行注釋,即形式為“/* */”的注釋。行內代碼注釋不要使用多行注釋。
1.1.3.2.2 縮進
如果在@param,@return, @supported, @this或@deprecated中斷行,需要像在代碼中一樣,使用4個空格作為一個縮進層次。
不要在@fileoverview標記中進行縮進。雖然不建議,但也可對說明文字進行適當的排版對齊。不過,這樣帶來一些負面影響,就是當你每次修改變量名時,都得重新排版說明文字以保持和變量名對齊。
1.1.3.3 書寫風格
包括分號(遺漏分號有時會出現很奇怪的結果,所以確保語句以分號結束)、大括號(分號會被隱式插入到代碼中,開發者務必在同一行上插入大括號)、數組和對象初始化(如果初始值不是很長,就保持寫在單行上;初始值占用多行時,縮進2個空格;不要為了讓代碼好看些而手工對齊)函數參數(盡量讓函數參數在同一行上,否則每個參數獨占一行,并以4個空格縮進,或者與括號對齊,以提高可讀性,盡可能不要讓每行超過80個字符)、傳遞匿名參數(如果參數中有匿名函數,函數體從調用該函數的左邊開始縮進2個空格,而不是從 function 這個關鍵字開始,可以讓匿名函數更加易讀)、多行字符串(盡量不要寫多行字符串)、塊內函數聲明(盡量不要在塊內聲明一個函數,因為不屬于ECMAScript規范,防止出現實現相互不兼容)
1.1.4 命名規范
1.1.4.1 大小寫規則
使用下面的三種標識符約定:
1.Pascal 大小寫規則:將標識符的首字母和后面連接的每個單詞的首字母都大寫。可以對三字符或更多字符的標識符使用 Pascal 大小寫。如:BackColor。
2.Camel 大小寫規則:標識符的首字母小寫,而每個后面連接的單詞的首字母都大寫。如:backColor
3.大寫規則:標識符中的所有字母都大寫,單詞之間用下劃線分隔。如:EFAULA_LANGUAGE。
標識符 大小寫規則 示例
命名空間 Pascal System.Drawing
類 Pascal AppDomain
常量 大寫 SECONDS_IN_A_MINUTE
枚舉 Pascal LoginState
屬性 Camel backColor
方法 Camel parseFloat
方法參數 Camel typeName
局部變量 Camel var index = 0;
1.1.4.2 命名空間
除非是枚舉類型,否則不要訪問別名變量的屬性。
/* @enum {string} /
some.long.namespace.Fruit = {
APPLE: ‘a’,
BANANA: ‘b’
};
myapp.main = function() {
var Fruit = some.long.namespace.Fruit;
switch (fruit) {
case Fruit.APPLE:
…
case Fruit.BANANA:
…
}
};
myapp.main = function() {
var MyClass = some.long.namespace.MyClass;
MyClass.staticHelper(null);
};
不要在全局范圍內創建別名,而僅在函數塊作用域中使用。
1.1.4.3 文件名
文件名應該使用小寫字符,以避免在有些系統平臺上不識別大小寫的命名方式。文件名以.js結尾,不要包含除“-”和“”外的標點符號(使用“ –” 優于“ ”)。
1.1.4.4 命名空間規范
Java Script 不支持包和命名空間。
不容易發現和調試全局命名的沖突,多個系統集成時還可能因為命名沖突導致很嚴重的問題。為了提高 JavaScript 代碼復用率,我們遵循下面的約定以避免沖突。
在全局作用域上,使用一個唯一的,與工程/庫相關的名字作為前綴標識。比如,你的工程是 “Project GSP Aries UI”,那么命名空間前綴可取為gsp.*。
var gsp= {};
gsp.aries= function() {
…
};
不要對命名空間創建別名。
myapp.main = function() {
var namespace = some.long.namespace;
namespace.MyClass.staticHelper(new namespace.MyClass());
};
1.1.4.5 類命名規范
使用名詞或名詞短語命名類;使用 Pascal 大小寫規則;少用縮寫。
1.1.4.6 常量字段命名規范
常量的形式如: NAMES_LIKE_THIS, 即使用大寫字符, 并用下劃線分隔。
你也可用 @const 標記來指明它是一個常量;但請永遠不要使用 const 關鍵詞;對于基本類型的常量, 只需轉換命名;對于非基本類型, 使用 @const 標記來告訴編譯器它是常量。
1.1.4.7 屬性命名規范
使用名詞或名詞短語命名屬性。
使用描述性名稱,且名稱應含義清晰,不要使用描述其類型的名稱。
使用 Pascal 大小寫規則。
考慮用與屬性的基礎類型相同的名稱創建屬性。例如,如果聲明名為 Color 的屬性,則屬性的類型同樣應該是 。
1.1.4.8 方法命名規范
使用動詞或動詞短語命名方法;使用camel大小寫規則。
1.1.4.9 方法參數命名規范
對方法參數名稱使用Camel大小寫規則;使用描述性名稱,且名稱應含義清晰,不要使用描述其類型的名稱。
1.1.4.10 局部變量命名規范
聲明變量必須加上 var 關鍵字。當你沒有寫 var,變量就會暴露在全局上下文中,這樣很可能會和現有變量沖突。另外,如果沒有加上,很難明確該變量的作用域是什么, 變量也很可能像在局部作用域中,很輕易地泄漏到 Document 或者 Window 中,所以務必用 var 去聲明變量。
1.1.5 基本代碼開發規范
包含變量(使用前必須通過 var 定義,不通過 var 定義變量將導致變量污染全局環境;必須即用即聲明,不得在函數或其它形式的代碼塊起始位置統一聲明所有變量;應該根據編程中的意圖,縮小變量出現的距離空間)、條件(在等于判斷中使用類型嚴格的===以避免等于判斷中隱式的類型轉換,僅當判斷 null 或 undefined 時,允許使用 == null;且盡可能使用簡潔的表達式;按執行頻率排列分支的順序;對于相同變量或表達式的多值條件,用 switch 代替 if)、循環(不要在循環體中包含函數表達式,事先將函數提取到循環體外;對循環內多次使用的不變值,在循環外用變量緩存;對有序集合進行遍歷時,緩存 length以提升部分瀏覽器程序性能;對有序集合進行順序無關的遍歷時,使用逆序遍歷來節省變量,以優化代碼)、類型(類型檢測優先使用 typeof。對象類型檢測使用 instanceof。null 或 undefined 的檢測使用 == null)、類型轉換(轉換成 string 時,使用 + ‘’;轉換成 number 時,通常使用 +;string 轉換成 number,要轉換的字符串結尾包含非數字并期望忽略時,使用 parseInt;使用 parseInt 時,必須指定進制。如果十進制數包含前導0,那么最好采用基數10,防止意外得到八進制的值;轉換成 boolean 時,使用 !!;number 去除小數點,使用 Math.floor / Math.round / Math.ceil,不使用 parseInt)、字符串(字符串開頭和結束使用單引號;使用數組或 + 拼接字符串;靜態字符串建議使用 + 拼接;在現代瀏覽器下,使用 + 拼接字符串,性能較數組的方式要高;如需要兼顧老舊瀏覽器,應盡量使用數組拼接字符串;復雜的數據到視圖字符串的轉換過程,推薦選用模板引擎)、浮點計算(在運算前把參加運算的浮點數先升次到整數,等運算完后再進行降次)、對象(使用對象字面量 {} 創建新 Object;對象創建時,如果一個對象的所有屬性均可以不添加引號,則所有屬性不得添加引號,反之則所有屬性必須添加單引號;如果屬性不符合 Identifier 和 Number Literal 的形式,就需要以 String Literal 的形式提供;不允許修改和擴展任何原生對象和宿主對象的原型;屬性訪問時,盡量使用 .,若屬性名符合 Identifier 的要求,就可以通過 . 來訪問,否則就只能通過 [expr] 方式訪問。)、數組(使用數組字面量 [] 創建新數組,除非想要創建的是指定長度的數組;遍歷數組不使用 for in,因為可能存在數字以外的屬性;不因為性能的原因自己實現數組排序功能,盡量使用數組的 sort 方法;需要穩定的排序算法,達到嚴格一致的排序結果;清空數組使用 .length = 0)、函數(一個函數的長度控制在 50 行以內;一個清晰易懂的函數應該完成單一的邏輯單元;復雜的操作應進一步抽取,通過函數的調用來體現流程,特定算法等不可分割的邏輯允許例外;一個函數的參數控制在 6 個以內。除去不定長參數以外,函數具備不同邏輯意義的參數建議控制在 6 個以內,過多參數會導致維護難度增大)

浙公網安備 33010602011771號