難說(shuō) | 程序員的品味
緣起
代碼里有很多值得商榷的寫法。今天來(lái)發(fā)點(diǎn)牢騷。
寫法1
bool?bShouldModifyData?=?false;
if?(condition1?&&?condition2)
{
??bShouldModifyData?=?true;
}
else
{
??bShouldModifyData?=?false;
}
好吧,這種寫法邏輯上沒問(wèn)題,但是我覺得可以一行代碼更好:
bool?bShouldModifyData?=?(condition1?&&?condition2);
寫法2
//?如果?map?中找到了?key?對(duì)應(yīng)的數(shù)據(jù),就用?map?中的數(shù)據(jù),否則用?normalData
//?if?和?else?中,只有?Method?的參數(shù)傳遞的不一樣,其它一模一樣
int?normalData?=?0;
auto?it?=?map.find(key);
if?(it?!=?map.end())
{
??//?lots?of?code??
??result?=?Method(it->second);
}
else
{
??//?lots?of?code?(same?with?if)??
??result?=?Method(normalData);
}
這樣的寫法在業(yè)務(wù)代碼中比較多。猜測(cè)應(yīng)該是寫好了 if 部分的代碼,else 部分的代碼直接復(fù)制粘貼的。我認(rèn)為上面代碼最致命的問(wèn)題是:如果業(yè)務(wù)邏輯發(fā)生變化,那么需要同時(shí)修改 if 和 else 兩個(gè)語(yǔ)句塊中的代碼。
寫代碼的時(shí)候有一個(gè)最基本的原則:DRY (Don't Repeat Yourself)??梢愿某上旅娴臉幼?,代碼量不僅少了一半兒,邏輯也更加清晰了。
//?如果?map?中找到了?key?對(duì)應(yīng)的數(shù)據(jù),就用?map?中的數(shù)據(jù),否則用?someNormalData
//?if?和?else?中,只有?Method?的參數(shù)傳遞的不一樣,其它一模一樣
int?normalData?=?0;
auto?it?=?map.find(key);
auto?funcParam?=?(it?!=?map.end())???it->second?:?normalData;
//?lots?of?code??
result?=?Method(funcParam);
寫法 3
struct?HugeStruct
{
??//?lots?of?members
};
void?DoSomething(HugeStruct?data)
{
??//?...
}
作為一個(gè)有強(qiáng)迫癥的 c++ 程序員,看到上面的代碼,我的直覺告訴我,寫這段代碼的人或者是不小心,或者是其它語(yǔ)言轉(zhuǎn)過(guò)來(lái)的。在 c++ 里,默認(rèn)是值拷貝,上面的寫法,在調(diào)用函數(shù)時(shí)會(huì)把 data 對(duì)應(yīng)的內(nèi)存在棧上拷貝一份。這會(huì)導(dǎo)致兩個(gè)問(wèn)題:1. 效率低(沒必要拷貝整個(gè)結(jié)構(gòu)體)。2. 可能爆棧(之前在項(xiàng)目中遇到過(guò)的)。
如果我們不打算修改 data 的內(nèi)容,那么應(yīng)該使用 const & 修飾。代碼改成下面這樣,既高效又安全。
void?DoSomething(const?HugeStruct&?data)
{
??//?...
}
寫法 4
int?GetMoney(BankAccount&?account)
{
??return?account.money;
}
通過(guò)函數(shù)名判斷,上面的函數(shù)只是獲取一些值,不會(huì)修改參數(shù)。但是參數(shù)只用了引用修飾,沒加 const,意味著參數(shù)可能在函數(shù)內(nèi)部被修改。讓人迷惑。
如果不需要修改參數(shù),那么需要加上 const。改成下面這樣就沒有任何歧義了。
int?GetMoney(const?BankAccount&?account)
{
??return?account.money;
}
注意: 不需要對(duì)
int,char,short,double這種基礎(chǔ)類型加const &修飾。加了效率也沒什么提高,反而很別扭。
寫法 5
class?Wall
{
??public:
????std::vector?GetHole()? {?return?m_holeVec;?}
??private:
????std::vector?m_holeVec;
};
上面這段代碼中規(guī)中矩。但是 GetHole() 的效率很低,可以優(yōu)化一下。改成返回引用。
class?Wall
{
??public:
????std::vector&?GetHole()? {?return?m_holeVec;?}
????const?std::vector&?GetHole()?const? {?return?m_holeVec;?}
??private:
????std::vector?m_holeVec;
};
有的小伙伴兒就有疑問(wèn)了,返回引用,被別人改了怎么辦?當(dāng) Wall 實(shí)例是 const 的,那么會(huì)調(diào)用帶 const 的函數(shù),返回的是 const &,不會(huì)被意外修改。當(dāng) Wall 實(shí)例是非 const 的,那么會(huì)調(diào)用不帶 const 的函數(shù),返回的是引用,可以被修改。但是,這大概率是調(diào)用者所期待的。
寫法 6
void?ReallyComplexFunction()
{
??//?start?by?xxx1?[2022-01-01]
??//?start?by?xxx2?[2022-02-01]
??//?start?by?xxx3?[2022-03-01]
??//?idx?=?0;
??//?idx?=?1;
??//?idx?=?2;
??idx?=?0;
??//?end?by?xxx3?[2022-03-01]
??//?end?by?xxx2?[2022-02-01]
??//?end?by?xxx1?[2022-01-01]
}
上面的代碼片段是非常典型的,三個(gè)同事改了三次,留下了三次改動(dòng)記錄,但是只是為了修改一個(gè)小小的地方。放眼望去,全是注釋,真正有用的就一句話。
Taste
之前看 ?Linus 大神的演講視頻時(shí),他提到了一個(gè)觀點(diǎn):品味對(duì)科技人員非常重要。原話如下:
I personally consider most important when it comes to technical people is this notion of taste.
我特意截取了關(guān)鍵視頻,并做了中英文字幕,發(fā)到視頻號(hào)上了。
我覺得每個(gè)人的水平,背景,閱歷不同,品味有差異是正常的,甚至同一個(gè)人在不同時(shí)期的品味也不盡相同。希望您也覺得以上幾個(gè)例子是反面教材。關(guān)于代碼的品味,您想說(shuō)些什么的呢?快來(lái)視頻號(hào)留言吧。
p.s. 新注冊(cè)了一個(gè)視頻號(hào),歡迎大家關(guān)注,留言交流。
