繼前一篇後,又過了一段時間

想說來寫寫Part 2吧

補一補把之前沒寫到的東西

 

最近換了公司

發現新的公司跟前公司在Code的處理上有些的差別

 

一個就是Code style沒有在管理

前公司剛進去,我老闆是有給Code style (編程風格) 的規範文件的

Coding時是要照著做的

 

這一家是完全沒有

所以我在這家公司看了好幾份令人汗顏的Code...

我都不敢相信這是Firmware做超過3年的人寫出來的...

跟另一個FW工程師討論後

才發現他之前的公司也都沒有在Care Code style

推測是 Firmware 比較多是電機系畢業的人在做的

對Code 的要求就是動作符合就好

沒人教過他們要怎麼寫Code才會好看、好懂、好維護

所以才會看到那麼多奇形種的Code (每次看都頭大....)

 

反過來說,如果你入職的公司有在Care Code style的話

恭喜你!這公司有高手!好好學!

沒有的話,至少你現在知道有這件事了!

請在你接下來的職業生涯中注意到這件事!!可以幫助你少走很多彎路

 

Code style ,編程風格,也可以去搜 "C Code Convention"

就可以找到很多相關的文章

具體來說,是講一些變數命名、函數命名的規則等的東西

照著這套方法做的話,可以讓你一看到一個變數時,就知道它的相關資訊

 

以下列出幾點作法,因為是做FW的,以下都是C的一些實踐規範:

 

A.

最基礎的,就是變數的 prefix

例如:

在多個.c中都會用的全域變數,前面應該加上 g_   ,像是  g_AAAA

如果是僅在一個 .c 內使用的全域變數

前綴應該加上 m_,像是 m_BBBBB

在函數中的變數則不加

如果是 static 變數,前綴則使用 s_,像是 s_CCCCC

(函數中的static 才加 s_,在外面的static則依照上面的命名原則處理)

 

以上的作法,可以讓你一看到前綴就知道這個變數的作用範圍

這個是最基礎版本的,也建議所有的初心者都能採用這種作法

(不然看到沒加的Code,實在是增加看Code的人的麻煩,ZZZ)

 

然後是表示變數型別的Prefix

這邊直接給例子

前綴 -> 型別

b -> u8,表示Byte

c -> s8,signed char

l -> u16

i -> s16

ul -> u32

s -> s32

f -> double,float

sz -> char* ,表示是字串

p -> 表示是指標(這個強烈建議要加!會讓你看Code的時候方便很多!)

舉例來說:

u8* pbPtr;

double* pfValue;

char* szString;

 

那如果又加上全域變數或靜態變數的情況,則變數命名寫成如下的寫法:

u8 m_bAAA;

u32 g_ulBBBBB;

static u16 s_lCCCC;

 

B.

如果是Struct

型別則命名為  AAAA_t

變數宣告則為前面加 t:

AAAA_t   tBBB;

 

同理,global則為:

AAAA_t    g_tCCC;

 

另外,Macro的命名,若為常數

則使用全大寫

例如:

#define PI_VALUE    (3.14)

 

但Macro若為函數,則採用一般函數的命名方法,有大小寫

例如:

#define CalculateSum(a, b)       ((a)+(b))

 

C.

Enum的命名:

這個有看過定義的後綴用 _t 的,宣告變數的前綴用 t

跟 struct一樣

但這樣是有點混淆,會變成你也不知道這個變數到底是struct 還是 enum

 

為了區隔,我有查到後綴改用 _e 的,宣告前面用e

目前我是採用後面的這種寫法

 

另外enum的命名方面

可以寫成

typedef enum

{

  kTYPE_NONE,

  kTYPE_1,

  kTYPE_2,

} Type_e;

注意,因為裡面都是常數,所以都用大寫命名

然後,為了跟#define 定義的常數區別

前面都加上一個小寫的 k,表示是Constant

這樣可以一看就知道它是enum定義的常數

 

D.

關於 if 語句、for、 while 後面的括號

就算只有一行Code

建議也不要省略

雖然會有點占版面

但可以避免手殘改到,或是看錯 Code 的情況

所以強力建議就是給它加上去就對了!

不要省這個版面~免得Debug花了你更多時間~!

 

E.

函數命名的一些眉角:

函數的前綴,如果是定義在 header中,要給外面使用的

函數名稱前面記得寫上Prefix

例如現在我們的header檔叫做Command.h

那裏面的函數宣告建議寫成:

void CMD_XXX();

void CMD_YYY();

很清楚的告訴看到這個函數的人,這個函是來自哪裡

 

至於Command.c 中如果有一些本地的函式

沒有要給外部使用的

則不用加上前綴

 

 

F.

函式的命名可以長,儘量看到名字就可以猜出這個函式的動作

譬如:

(X) CRC();    // 太短,不好猜

(O) Calc_CRC() // better

 

可是變數的命名儘量短一點,免得在解碼流程時看得頭昏眼花

例如:

1. (X)u8 bCounterOfTrigger    // 太長,頭昏眼花

2. (O) u8 bTriggerCnt   // 短一點,好看多了

3. (O) u8 bCnt      // 夠短!Good

 

後面的兩種比較推薦

然後,如果該變數頻繁被使用,則建議使用第3種

能有效減少你看 Code 時腦力的消耗

 

 

G.

指標的使用 & 容易讓人看懂的Code:

 

有的時候,你會看到下面這種Code

AAA_t    tAAA;

tAAA.tBBBB.tCCCC.bDDD = 5;

tAAA.tBBBB.tCCCC.bEEE = 10;

tAAA.tBBBB.tCCCC.bXXX = tAAA.tBBBB.tCCCC.bYYY;

看了很頭大

 

像這種Code,你在看的時候

其實腦袋都在比對前面的tAAA.tBBBB.tCCCC 是不是一樣

這時候如果用指標來改寫,就可以大幅減少腦力的消耗

讓Code 一下子就變得很明瞭

改寫如下:

CCC_t*  ptC;   

ptC = &tAAA.tBBBB.tCCCC;

ptC.bDDD = 5;

ptC.bEEE = 10;

ptC.bXXX = ptC.bYYY;

 

大致改過就會變成上面的樣子,要做什麼事一下就變得很清楚

之後維護Code也會變得很方便

這點請務必要用起來!

 

 

H.

自己做的函式,記得註解要加啊啊啊~

 

通常一個Code你寫了多久會忘掉?

根據我四處調查 & 自己的經驗,大約半年都會記憶模糊,超過一年基本上都忘了

這時候沒寫註解,真的很麻煩~

還有一種情況是你去問原作者

他當初寫了這一行Code 是要幹嘛的?

結果本人完全忘記了 T_T

真的很靠北

 

像是有一些參數的由來 & 用途、特殊的演算法等,都建議加在Comment

免得後來沒人知道這個東西是怎麼來的

變成一個坑

 

 

I.

不要再出現魔法數字啦!!

 

就是Code 裡面有時候會有一些莫名其妙的參數值出現在那

可是你也不能很確定那個值的功用是什麼

也不知道它的前因後果是啥

就很尷尬

 

譬如:

double fValue = 0.4588;

這樣就很討厭,完全猜不透0.4588是啥,當大家都是通靈王就是了

 

建議至少加上comment,像是:

double fValue = 0.4588;    //  臨界電壓值

 

再進一步的做法,參數用macro包起來:

#define VOLTAGE_THRESHOLD_VOLTAGE      (0.4588)

double fValue = VOLTAGE_THRESHOLD_VOLTAGE;

 

這樣抽象性就更好了,還可以防止有人把註解偷刪掉的情況
(真的聽過有人把同事的Code偷改掉的... 沒職業道德...)

 

 

 

====

目前想到的大概這些,之後想到什麼再補充吧)))

 

 

 

arrow
arrow

    迷途工程師 發表在 痞客邦 留言(0) 人氣()