代碼之丑(九)——退讓的縮進
這是一個讓我糾結了很久的話題:縮進。
Attr *attr = attributes.get(j);
if (attr == NULL ) {
continue;
}
int IsCallFunc = -1;
if(attr->status() == STATUS_NEW || attr->status() == STATUS_MODIFIED) {
if(strcmp(attr->attrID(), "CallFunc") == 0) {
if(0 == strcmp(attr->attrValue(), "1")) {
IsCallFunc = 1;
} else if(0 == strcmp(attr->attrValue(), "0")) {
IsCallFunc = 0;
}
}
} else if (attr->status() == STATUS_DELETED) {
IsCallFunc = 0;
}
...
}
不是因為它不夠“丑”,而是表現它不那么容易。找出一段能表現它特點的代碼輕而易舉,但放到一篇文章里,大片的代碼還是容易讓人懷疑我在偷懶。
咬咬牙,我還是拿出了一段。就是這樣一段已經縮進很多層的代碼,實際上,也只不過是一個更大縮進中的一小段。而且,省略號告訴我們,后面還有。
回到這段代碼上,能出現多層縮進,for循環功不可沒。出現這種循環,很多情況下,都是對一個集合進行處理,而循環里的內容,就是對集合里的每一個元素進行處理。這里也不例外。所以,我們先做一次提取:
processAttr(attributes.get(j));
}
void processAttr(Attr *attr) {
if (attr == NULL ) {
return;
}
int IsCallFunc = -1;
if(attr->status() == STATUS_NEW || attr->status() == STATUS_MODIFIED) {
if(strcmp(attr->attrID(), "CallFunc") == 0) {
if(0 == strcmp(attr->attrValue(), "1")) {
IsCallFunc = 1;
} else if(0 == strcmp(attr->attrValue(), "0")) {
IsCallFunc = 0;
}
}
} else if (attr->status() == STATUS_DELETED) {
IsCallFunc = 0;
}
...
}
至此,我們去掉了一層縮進,而且因為這個提取,語義也變得很清晰:這個新函數只是處理集合里的一個元素。
接下來,這個函數里面長長的代碼是對IsCallFunc進行設值,后面省略的部分會根據這里求出的結果進行處理。所以,這里把processAttr進一步分拆:
if (attr == NULL ) {
return;
}
int IsCallFunc = isCallFunc(attr);
......
}
int isCallFunc(Attr *attr) {
if(attr->status() == STATUS_NEW
|| attr->status() == STATUS_MODIFIED) {
if(strcmp(attr->attrID(), "CallFunc") == 0) {
if(0 == strcmp(attr->attrValue(), "1")) {
return 1;
} else if(0 == strcmp(attr->attrValue(), "0")) {
return 0;
}
}
} else if (attr->status() == STATUS_DELETED) {
return 0;
}
return -1;
}
縮進還有,如果有興趣,還可以繼續分解。這里就到此為止吧!
多層縮進是那種放在代碼海一眼就可以認出來的代碼,用一條簡單的規則就可以限制它:
- 不允許出現多層縮進。
按照我的喜好,3就意味著“多”了。對于switch,我會給予特別的關照,因為switch一旦出場,條件少了,你都不好意思和人打招呼,再縮進就找不到北了。于是,對switch而言,我以為2就是多了,也就是說,switch里面就別再縮進了。
寫代碼,千萬別退讓太多。
作者簡介:
鄭曄,ThoughtWorks公司咨詢師,擁有多年企業級軟件開發經驗,熱衷于探索各種程序設計語言在真實軟件開發中所能發揮的威力,致力于探尋合理的軟件開發方式,加入ThoughtWorks公司后,投入到敏捷開發方法的實踐之中,為其他公司提供敏捷開發方法方面的咨詢服務。他的blog是夢想風暴。
查看原文:代碼之丑(九)