良好記錄的源代碼可以通過(guò)提供對(duì)軟件的深入了解來(lái)減少設(shè)計(jì)成本和上市時(shí)間,否則需要時(shí)間和實(shí)驗(yàn)來(lái)喚起嵌入式開發(fā)人員對(duì)代碼行為的內(nèi)容和原因的記憶。如果失去了這些洞察力,還會(huì)增加成本,并通過(guò)將錯(cuò)誤引入代碼庫(kù)來(lái)推遲上市時(shí)間。
在繁忙的開發(fā)周期中,注釋C代碼落到優(yōu)先級(jí)列表的底部并不罕見(jiàn)。在將產(chǎn)品發(fā)布出去的壓力下,紀(jì)律通常會(huì)失效,捷徑會(huì)導(dǎo)致糟糕的代碼庫(kù)。這里有10個(gè)簡(jiǎn)單的技巧,你可以遵循它們來(lái)確保軟件不僅被文檔化,而且還包含有用的信息。
1、解釋為什么,而不是如何
在開發(fā)軟件時(shí),人們似乎傾向于解釋一行代碼在做什么,而不是首先解釋代碼為什么會(huì)在那里。一個(gè)最受歡迎的例子是將文字移位x位。代碼和注釋通常看起來(lái)像這樣
// Shift bit by 8 and store in PortB
*Gpio_PortB |= (1UL<<8);
這個(gè)評(píng)論本身就有很多不盡人意的地方。任何對(duì)C語(yǔ)言有基本了解的人通過(guò)觀察都知道代碼行在做什么,但是為什么我們要移動(dòng) 8 位呢? 為什么我們要將移位的位模式存儲(chǔ)到 PortB 中? 如果嵌入式開發(fā)人員在編寫這行代碼六個(gè)月或一年后閱讀這行代碼,如果不調(diào)查這一行代碼到底在做什么,他將會(huì)一無(wú)所知。
更合適的情況可能如下所示:
// Port B bit 8 controls the motor relay that needs to be turned off during the
// emergency stop procedure. Setting bit 8 high will disengage the motor through a relay.
*Gpio_PortB |= (1UL<<8);
這個(gè)評(píng)論可能并不完美,但它解釋了為什么開發(fā)人員將移位和按位或運(yùn)算到PortB中。哪個(gè)評(píng)論更受歡迎?
2、編碼前注釋
注釋代碼的常識(shí)總是建議在編寫代碼的同時(shí)編寫注釋。這種見(jiàn)解很有道理;當(dāng)編寫軟件時(shí)為什么開發(fā)人員對(duì)此記憶猶新。開發(fā)人員可以等到軟件寫完之后,但是推向市場(chǎng)的壓力和其他優(yōu)先考慮的事情通常使得注釋很可能無(wú)法傳達(dá)最初的意思。
在代碼期間或之后編寫注釋的另一種方法是在編寫軟件之前編寫注釋,這有一個(gè)獨(dú)特的優(yōu)勢(shì),允許嵌入式開發(fā)人員在編寫一行代碼之前考慮他們將要編碼的內(nèi)容和原因,它可以被認(rèn)為是將軟件架構(gòu)和開發(fā)的設(shè)計(jì)階段轉(zhuǎn)化為源代碼,這種方法將軟件設(shè)計(jì)放在開發(fā)人員的首要位置,并允許他們清楚地思考他們將要編寫的代碼是為了什么。
3、使用Doxygen標(biāo)簽
網(wǎng)上有許多不同的免費(fèi)工具可以將代碼注釋轉(zhuǎn)換成有用的文檔格式。能夠掃描源代碼并生成html、rtf和/或pdf的工具應(yīng)該是開發(fā)人員的夢(mèng)想。為什么?許多開發(fā)團(tuán)隊(duì)不僅要維護(hù)他們的源代碼,還要維護(hù)各種描述代碼實(shí)際工作的設(shè)計(jì)文檔。這些文檔經(jīng)常追蹤程序中實(shí)際發(fā)生的事情。
使用工具,例如Doxygen可以自動(dòng)將代碼注釋翻譯成符合這些設(shè)計(jì)文檔清單的文檔。最終結(jié)果是,開發(fā)人員現(xiàn)在只需要維護(hù)一個(gè)源代碼和文檔鏈,這將減少他們創(chuàng)建“漂亮”文檔所需的時(shí)間。(也希望確保文檔和源代碼彼此保持同步)。
Doxygen已經(jīng)被廣泛接受,以至于編譯器和芯片供應(yīng)商在其自動(dòng)生成的代碼中包含了Doxygen標(biāo)簽。他們將Doxygen構(gòu)建到工具鏈中,以使開發(fā)人員更容易生成文檔。作為開發(fā)人員,難道我們不應(yīng)該接受這個(gè)讓文檔變得如此簡(jiǎn)單的免費(fèi)工具嗎?
4、采用代碼風(fēng)格指南
編碼風(fēng)格指南包含了開發(fā)人員正確創(chuàng)建標(biāo)識(shí)符所需的所有信息,以及如何記錄軟件。風(fēng)格指南有助于為嵌入式開發(fā)人員或開發(fā)團(tuán)隊(duì)提供以統(tǒng)一方式開發(fā)軟件的方法。這種一致性有助于開發(fā)人員消除由于風(fēng)格差異而可能存在的對(duì)軟件的干擾。結(jié)果是代碼評(píng)審更容易,因?yàn)榇a的風(fēng)格是統(tǒng)一的,評(píng)審可以集中在實(shí)際的代碼上,而不是注釋位置的表面細(xì)節(jié)。
5、使用文件頭
強(qiáng)烈推薦使用版本控制系統(tǒng),但是在代碼庫(kù)發(fā)生變化時(shí)總是參考版本控制系統(tǒng)會(huì)變得很乏味。有時(shí)可能會(huì)令人困惑或不清楚特定模塊的目的是什么。基于這些原因,建議頭文件和源文件包含一個(gè)注釋頭,描述模塊的功能和用途。
標(biāo)題中可以包含許多信息,但至少應(yīng)包括:
文件名
作者
起始日期
模塊版本號(hào)
用于編譯代碼的編譯器版本
預(yù)期目標(biāo)
版權(quán)信息
雜項(xiàng)說(shuō)明
修訂信息
……
6、創(chuàng)建評(píng)論模板
確保代碼注釋一致并遵守Doxygen語(yǔ)法的最佳方法之一是創(chuàng)建一個(gè)注釋模板。嵌入式開發(fā)人員需要兩個(gè)模板:一個(gè)用于頭文件,另一個(gè)用于源文件。編碼模板將包含遵循編碼風(fēng)格所需的所有標(biāo)準(zhǔn)注釋塊。
注釋模板將包含一個(gè)文件頭以及注釋標(biāo)簽和注釋塊,用于結(jié)構(gòu)、枚舉,類型定義、和函數(shù)。
7、一致的評(píng)論位置
減少與軟件項(xiàng)目相關(guān)的錯(cuò)誤和成本的最有效的方法之一是執(zhí)行代碼評(píng)審。開發(fā)人員通常執(zhí)行代碼評(píng)審,但是如果注釋結(jié)構(gòu)不一致,這個(gè)過(guò)程會(huì)變得更加困難。使用不同格式并放在不同位置的注釋會(huì)分散注意力,降低代碼評(píng)審的效率。
推薦使用編碼風(fēng)格指南,因?yàn)樗粌H規(guī)定了應(yīng)該使用的注釋格式,還規(guī)定了注釋應(yīng)該出現(xiàn)在哪里,這將有助于保持注釋結(jié)構(gòu)的統(tǒng)一,并允許代碼審查者關(guān)注代碼及其行為,而不是被注釋中包含的位置或信息分散注意力。
8、不要注釋每一行
老實(shí)說(shuō),開發(fā)者真的不想評(píng)論他們的軟件。這既費(fèi)時(shí)又不令人愉快。旋轉(zhuǎn)位、控制硬件以及幾乎做任何其他事情要有趣得多。然而,通常認(rèn)為是文檔記錄良好的每一行代碼都要有一個(gè)注釋,這可能太多了。
注釋代碼的目的是為未來(lái)的嵌入式開發(fā)人員或維護(hù)人員提供關(guān)于軟件是什么和為什么的洞察力。冗長(zhǎng)的文章既不需要也不想要。創(chuàng)建一個(gè)注釋塊來(lái)描述這個(gè)塊在做什么通常就足夠了。對(duì)塊進(jìn)行注釋的一個(gè)很大的好處是,如果代碼需要更改,但是塊描述仍然適用,那么描述可以保持不變,從而節(jié)省了開發(fā)時(shí)間,否則這些時(shí)間將會(huì)花費(fèi)在更新注釋上。
9、以類型開始數(shù)學(xué)類型標(biāo)識(shí)符
當(dāng)開發(fā)執(zhí)行數(shù)學(xué)運(yùn)算的軟件時(shí),以標(biāo)識(shí)符的類型開始非常有用。例如,創(chuàng)建一個(gè)名為ui8_Velocity或si32_Acceleration的變量可以讓開發(fā)人員立即了解變量的類型。
以這種方式命名標(biāo)識(shí)符有很多優(yōu)點(diǎn)。首先,不需要引用變量聲明來(lái)獲取類型。這可以節(jié)省時(shí)間,因?yàn)殚_發(fā)人員不必不斷刷新變量的類型和大小,以及是否需要在計(jì)算中進(jìn)行強(qiáng)制轉(zhuǎn)換。第二,這種命名方式更容易發(fā)現(xiàn)轉(zhuǎn)換錯(cuò)誤,比如兩個(gè)8位數(shù)字相乘而不進(jìn)行轉(zhuǎn)換。
10、進(jìn)行代碼更新時(shí)更新注釋
如果使用得當(dāng),將模板與Doxygen結(jié)合使用會(huì)是一個(gè)非常強(qiáng)大的工具。這些模板和工具的正確使用部分來(lái)自于軟件的更新和維護(hù)。只有當(dāng)嵌入式開發(fā)人員足夠自律,能夠隨著軟件的變化更新他們的注釋時(shí),這些工具才有效。
在開發(fā)過(guò)程中,需求、設(shè)計(jì)和實(shí)現(xiàn)無(wú)疑會(huì)發(fā)生變化。作為這些變更的一部分,開發(fā)人員需要確保注釋總是隨著軟件的實(shí)現(xiàn)而更新。即使事實(shí)并非如此感覺(jué)就像有足夠的時(shí)間來(lái)實(shí)現(xiàn)代碼更改和更新注釋一樣,開發(fā)人員仍然應(yīng)該花時(shí)間來(lái)更新注釋。一個(gè)原因是,在產(chǎn)品的整個(gè)生命周期中,它的成本將受到開發(fā)人員保持紀(jì)律的極大影響,盡管他們可能面臨時(shí)間壓力。
結(jié)論
評(píng)論軟件通常被認(rèn)為是開發(fā)周期中優(yōu)先級(jí)最低的任務(wù)之一。快速實(shí)施和部署嵌入式軟件的壓力讓工程師們不得不忙于設(shè)計(jì)、實(shí)施和部署他們的固件。但事實(shí)是,注釋代碼并闡明代碼的原因可以使未來(lái)的維護(hù)工作甚至最初的開發(fā)工作花費(fèi)更少。在適當(dāng)?shù)那闆r下甚至?xí)p少上市時(shí)間。
這些技巧只是改進(jìn)嵌入式軟件設(shè)計(jì)周期的幾個(gè)簡(jiǎn)單例子,通過(guò)使用模板、標(biāo)準(zhǔn)和自動(dòng)化工具,并花時(shí)間解釋軟件的原因,減輕嵌入式開發(fā)人員的負(fù)擔(dān)。