在匆忙推出產(chǎn)品的過(guò)程中,程序員經(jīng)常忽略應(yīng)用程序的一個(gè)關(guān)鍵方面——代碼維護(hù)。
對(duì)于生命周期較短的應(yīng)用程序,這種匆忙可能不會(huì)造成嚴(yán)重問(wèn)題,因?yàn)橐坏┎渴穑瑳](méi)有人會(huì)再次接觸代碼。
然而,嵌入式系統(tǒng)應(yīng)用程序的生命周期可能長(zhǎng)達(dá)數(shù)十年,早期的編碼錯(cuò)誤可能會(huì)導(dǎo)致日后重大的錯(cuò)誤修復(fù)和更新成本。
在為嵌入式應(yīng)用程序設(shè)計(jì)和實(shí)現(xiàn)軟件期間,您必須考慮代碼的可維護(hù)性。以下的10個(gè)建議可能不是關(guān)于代碼易維護(hù)的全部,但是遵守了這幾個(gè)建議應(yīng)該可以避免被看你代碼的人“罵”:
01避免匯編代碼
在低端的一些微控制器(MCU)上可能只能用匯編語(yǔ)言,但是在高端的處理器上(如ARM),可能就不需要匯編語(yǔ)言。
我們?cè)谶@里不能否認(rèn)匯編語(yǔ)言的好處,在一些情況下,許多程序員可能會(huì)使用匯編語(yǔ)言來(lái)提高性能或減少代碼大小。但是使用匯編語(yǔ)言代碼可能會(huì)使您的項(xiàng)目延期,關(guān)鍵的,會(huì)讓不懂匯編的人“看懵”。
當(dāng)然了,有些位置或者情況你是不能避免使用匯編語(yǔ)言的,如果必須使用匯編語(yǔ)言,請(qǐng)包含詳細(xì)的注釋,這樣可以節(jié)省時(shí)間并減少有人遇到問(wèn)題時(shí)檢查你的代碼的挫敗感。
02代碼注釋要清晰
? 代碼注釋的作用應(yīng)該就不需要解釋了,好的注釋確實(shí)可以很好的保證代碼的可讀和可維護(hù)性,但是相反;不好的代碼注釋反而會(huì)增大代碼的誤解; 如下面的注釋:
//?This?function?adds?two?numbers?and?returns?the?result int multiply(int a, int b) { return a*b; }上面的代碼明明是返回兩個(gè)數(shù)字的乘積,但是注釋中注釋為范圍兩個(gè)數(shù)的和;讓你說(shuō),后人看到這樣的代碼,會(huì)不會(huì)罵人?? ? ?
?
?03不要隨意優(yōu)化代碼
?隨意優(yōu)化代碼可能會(huì)導(dǎo)致維護(hù)噩夢(mèng),因?yàn)閮?yōu)化后的代碼通常難以理解,并且,優(yōu)化后的代碼可能執(zhí)行的效果與未優(yōu)化前的效果天壤之別;若考慮到代碼大小,內(nèi)存空間限制等因素,請(qǐng)?zhí)崆按_定好代碼的優(yōu)化等級(jí);? ?
04保持中斷函數(shù)盡可能簡(jiǎn)單
簡(jiǎn)單的中斷服務(wù)程序 (ISR) 可提高性能并簡(jiǎn)化維護(hù)。 因?yàn)橹袛喾?wù)函數(shù)的運(yùn)行是異步地,它們本質(zhì)上很難調(diào)試;所以盡量減少他們的任務(wù)。 嘗試將任何數(shù)據(jù)處理或任務(wù)處理從 ISR 移到主程序中。然后,ISR 只負(fù)責(zé)從硬件獲取數(shù)據(jù),將其放入緩沖區(qū),置位數(shù)據(jù)就緒標(biāo)志并重新啟用中斷。 在主程序中通過(guò)判斷就緒標(biāo)志來(lái)執(zhí)行數(shù)據(jù)的處理。? ?
05將調(diào)試代碼留在源文件中
在程序開發(fā)過(guò)程中,我們可能會(huì)添加一些專門用于調(diào)試的代如:詳細(xì)輸出、斷言、LED閃爍等。 在項(xiàng)目結(jié)束時(shí),刪除調(diào)試代碼以“清理”源代碼可能很“爽”。但是,刪除調(diào)試代碼可能會(huì)在以后產(chǎn)生問(wèn)題。 任何試圖維護(hù)應(yīng)用程序代碼的人都可能必須重新創(chuàng)建原始代碼中包含的許多調(diào)試步驟。所以,將調(diào)試代碼保留在源文件中可以簡(jiǎn)化維護(hù)。 如果您必須在生產(chǎn)版本中刪除調(diào)試代碼,可以使用條件編譯的方式保證在產(chǎn)生生產(chǎn)版本時(shí)不編譯相關(guān)的調(diào)試代碼。? ?
06將底層和應(yīng)用層區(qū)分開
如果應(yīng)用程序的代碼中涉及到太多硬件相關(guān)的操作可能會(huì)使移植到新平臺(tái)變得非常困難。 所以,為了簡(jiǎn)化編程和應(yīng)用層的維護(hù),為硬件API或底層硬件操作封裝自己的HAL層接口。 當(dāng)你的程序需要移植到新單片機(jī)上時(shí),僅僅需要更改底層的代碼就可以,定義的HAL層接口不需要改變,相對(duì)應(yīng)的,應(yīng)用層的代碼也就不需要改變。
關(guān)于如何進(jìn)行軟件分層,我們會(huì)專門推出一系列的文章進(jìn)行講解;歡迎儲(chǔ)蓄關(guān)注。? ??
07功能拆分需要合理
與 PC軟件不同,嵌入式應(yīng)用程序代碼更多的依賴于硬件一起工作。因此,您可以選擇將代碼的功能單元分成不同的小塊。 將不同的功能拆分成不同的功能塊,確實(shí)可以提高代碼的易讀和易維護(hù)性; 但是進(jìn)行功能拆分也不能太多;一般保持在單個(gè)作用域內(nèi)的函數(shù)調(diào)用次數(shù)控制在5個(gè)或6個(gè)以內(nèi),并使軟件中的功能單元與特定的硬件功能相對(duì)應(yīng)。 ? 如果一個(gè)程序被分成太多的小塊,調(diào)用圖就會(huì)像蜘蛛網(wǎng)一樣,代碼將很難調(diào)試和理解。? ?
08保留所有代碼相關(guān)的文檔和流程圖
我們?cè)谶M(jìn)行程序開發(fā)時(shí),肯定會(huì)有一些功能說(shuō)明、軟件流程圖等文檔性質(zhì)的內(nèi)容,這些文檔類的資料應(yīng)盡可能與源文件放到一起,或直接添加到源代碼工程中。 如果您必須將文檔分開,需要保證在代碼中有相關(guān)的說(shuō)明,說(shuō)明文件的相關(guān)信息:如文件名、路徑等信息。因?yàn)槿绻皇褂迷创a找到文檔,則很容易丟失文檔。 理想情況下,將完整應(yīng)用程序的所有文檔和源代碼同一個(gè)工程目錄下。保證后來(lái)人可以通過(guò)你的文章很快的熟悉你的代碼。? ?
09避免使用一些巧妙的技巧
聰明的程序員可以想出極其緊湊和優(yōu)雅的方法來(lái)使用模板、繼承、goto 語(yǔ)句和三元運(yùn)算符(“?”)等工具。 但是這樣聰明的編碼方式可能會(huì)導(dǎo)致一些不必要的麻煩。因?yàn)榭赡苤挥性谧约壕帉懘a時(shí)才知道他們是怎么工作的,等過(guò)幾天或者讓后來(lái)人看你的代碼時(shí),肯定會(huì)一頭霧水。 因此,還是盡量減少使用這種深?yuàn)W的語(yǔ)言功能。? ?
?10將所有定義放在一處
如果您的代碼包含許多常量定義或條件定義,請(qǐng)將它們保存在一個(gè)位置,例如單個(gè)文件或源代碼目錄。如果您在代碼中藏著很多變量的定義,別人看到后可能會(huì)感覺(jué)代碼太亂,變量隨便定義,毫無(wú)規(guī)劃。(當(dāng)然了,不罵人最好了)
?
評(píng)論
查看更多