參見原文:如何高效編寫可維護代碼?函數
在代碼中找到一個放錯地方而且沒有用的註釋是否是頗有趣呢?
怎麼樣才能作到寫不多的註釋但仍能讓代碼易於理解呢?
一個主要的方式就是讓代碼自我文檔化。當代碼自我文檔化的時候,就不須要註釋去它的做用或者目的,而且也能使代碼變得很是容易維護。this
在這篇文章中,我將提供一些讓你的代碼自我文檔化的方式。下面就是三種使得代碼自文檔化的基本方法:spa
這可能看上去很簡單,但在實際操做過程當中會讓人以爲有點棘手。首先你得明白哪些地方有問題以及哪些地方適用這些方法。code
此外,除了上述三種,還有一些應用比較普遍的方式:對象
接下來咱們將經過實例,具體講一講如何在實際應用中運用上述5個方法。接口
首先,看幾個如何利用命名時代碼變得清晰和自我文檔化的例子。
1) 重命名函數
給函數命名不是很難,你能夠遵照如下規則:ip
2) 重命名變量文檔
接下來,看幾個如何將代碼封裝成函數的例子。封裝函數的一個好處就是避免代碼重複,或者說改進代碼結構。get
1) 將代碼封裝成函數
這是最基本的:將代碼封裝成函數以明確其目的。猜猜下面這行代碼是幹什麼的:it
1
|
var width = (value - 0.5) * 16;
|
好像不是很清楚,固然有註釋就一清二楚了,可是咱們徹底能夠封裝成函數以實現自文檔化……
1
2
3
4
5
|
var width = emToPixels(value);
function emToPixels(ems) {
return (ems - 0.5) * 16;
}
|
惟一改變的是計算過程被轉移到了一個函數裏。該函數名明確地表達了它要作什麼,這樣一來就沒必要寫註釋了。並且,若是有須要後面還能夠直接調用此函數,一箭雙鵰,減小了重複勞動。
2) 用函數代替條件表達式
If語句若是包含多個運算對象,不寫註釋的話理解起來就比較難
1
2
|
if(!el.offsetWidth || !el.offsetHeight) {
}
|
知道上面這代碼的目的不?
1
2
3
4
5
6
|
function isVisible(el) {
return el.offsetWidth && el.offsetHeight;
}
if(!isVisible(el)) {
}
|
最後再講講如何引入變量。相較於上面兩個方法,這個可能沒那麼有用,可是不管如何,知道比不知道好
1) 用變量代替表達式
看看上面的例子
1
2
|
if(!el.offsetWidth || !el.offsetHeight) {
}
|
這下不封裝成函數,用引入變量代替
1
2
3
|
var isVisible = el.offsetWidth && el.offsetHeight;
if(!isVisible) {
}
|
2) 用變量代替方程式
咱們也能夠用來清楚說明覆雜程式:
1
|
return a * b + (c / d);
|
用變量來代替
1
2
3
|
var divisor = c / d;
var multiplier = a * b;
return multiplier + divisor;
|
類和模塊的接口——也是面向公共的方法和屬性——有點像說明如何使用的文檔。
看下面的例子:
1
2
3
4
5
6
7
8
|
class Box {
public
function setState(state) {
this.state = state;
}
public
function getState() {
return this.state;
}
|
這個類也能夠包含其餘代碼。我特地舉這個例子是想說明公共接口如何自文檔化。
你能說出這個類是如何被調用的嗎?很顯然,這並不明顯。
這兩個函數都應該換個合理的名字以表述它們的目的。但即使作到這一點,咱們仍是不怎麼清楚如何使用。而後就須要閱讀更多的代碼或者翻閱文檔。
可是若是咱們這樣改一下呢……
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Box {
public
function open() {
this.state = open;
}
public
function close() {
this.state = closed;
}
public
function isOpen() {
return this.state == open;
}
}
|
是否是清晰多了?注意:咱們只是改動了公共接口,其內部表達與原先的this.state狀態相同。
用組來區分不一樣的代碼片斷也是自文檔化的一種形式。例如,像這篇文章中說的那樣,咱們應該儘量將變量定義在靠近使用它的地方,而且儘量將變量分門別類。這也能夠用來指定不一樣代碼組之間的關係,這樣更加方便其餘人知道他們還須要瞭解哪些代碼組。
看下面的例子:
1
2
3
4
5
6
7
8
|
var foo = 1;
blah()
xyz();
bar(foo);
baz(
1337);
quux(foo);
|
與下面的比較:
1
2
3
4
5
6
7
8
|
var foo = 1;
bar(foo);
quux(foo);
blah()
xyz();
baz(
1337);
|
將foo的全部使用組合放在一塊兒,一眼望去就能知道各類關係。可是有時候咱們不得不在中間調用一些其餘函數。因此若是能夠那就儘可能使用代碼分組,若是不能夠,那就不要強求。
1
2
3
4
5
|
imTricky && doMagic();
if(imTricky) {
doMagic();
}
|
顯而後者比較好。語法技巧並無帶來什麼好處。