酷殼中有不少有意思的文章,看起來很帶勁。本來要說大多看看則了,現在終於要學以致用了。
本人最近接手一個項目,縫縫補補幾天下來,實在有點郁悶,但是想想,自己也強不到哪里去。正如下所說:
If builders built buildings the way programmers write programs, then the first woodpecker that came along would destroy civilization.(如果建築師蓋房子就像程序員寫程序一樣,那么,第一只到來的啄木鳥就能毀掉我們的文明)
如何寫出無法維護的代碼
其實好代碼很多,開源的很多,但是往往都是代碼太多,功能太強大,而不知道從何處看起。所以,其實根本不用混淆你的代碼。
本文針對此次項目,結合以往所學所看,談談對代碼可讀性方面的認識。
程序命名
有一篇文章說史上最糟糕的兩個變量名:
- data
- data2
僅就個人而言,並不是很反感變量名的無意義。如a1,a2,b3,b4等變量命名,如str(本人就經常使用),tmp,dt等都與data與data2所說一致,其實想想有時候使用同一種相互不約而同
的命名方式有何不可,即使這是一種錯誤的命名方式。
好比看到str,我知道他是一個字符串,知道他是一個局部變量(local),而不可能是一個字段(field),對於str,我打起來很快很熟練,可能我只是在十幾行的方法中使用,這種命名有何不可。
但是還有一種人很有意思,他們不寫這種簡單的變量名,往往會這樣去聲明一個變量:
private DeserializeDockContent m_DeserializeDockContent;
或許他們實在不知道給這個字段起什么名字,但是又不能讓變量名毫無意義
,所以他們一般會將整個類名寫出來,好讓人看到變量就知道他是什么類型。
相同的,他們會覺得遵守了匈牙利命名法而自豪,如果是局部變量更簡單:
ComponentAssembly componentAssembly = new Componentassembly("XXX");
文中所談使用下划線為變量名,讓我想起了一門超牛逼的編程語言:Brainfuck,很難見的只有八種運算符的語言,有興趣的可以看看。
偽裝欺詐
看到這一節的第一個程序讓我真實感覺到了牛人的創造力
:
for(j=0; j<array_len; j+=8) { total += array[j+0]; total += array[j+1]; total += array[j+2]; /* Main body of total += array[j+3]; * loop is unrolled total += array[j+4]; * for greater speed. total += array[j+5]; */ total += array[j+6]; total += array[j+7]; }
至於偽裝欺詐,我想很多程序員也不至於去干如此有技術含量
的事,但是不排除一些看到如下代碼的程序員會做出如何瘋狂的事情:
case "btnModify": mySql.Append("update mdm_attr set mdm_code='" + txtMdmCode.Text + "',mdm_name='" + txtName.Text + "',"); mySql.Append("mdm_type='" + GetMdmType() + "',ac_num_ind='" + GetAcnumind() + "',draw_uncon_yn='" + GetDrawuncon() + "',"); mySql.Append("qry_pwd_yn='" + GetQrypwd() + "',draw_pwd_yn='" + GetDrawpwd() + "',draw_id_yn='" + GetDrawid() + "',"); mySql.Append("draw_seal_yn='" + GetDrawseal() + "',pwd_mach_yn='" + GetPwdmach() + "', note_type = '" + txtNotetype.Text + "',only_ind='" + GetOnlyind() + "',"); mySql.Append(" pg_num=" + pgnum + ", pg_line=" + pgline + ",no_ind='" + GetNoind() + "',prt_ind='" + GetPrtind() + "',"); mySql.Append(" card_type='" + GetCardType() + "',card_ind='" + GetCardInd() + "',chg_flag='" + GetChgFlag() + "',"); mySql.Append(" fee_knd='" + GetFeeKnd() + "',min_amt=" + min_amt + ",fee_code='" + txtfeecode.Text.Trim() + "',"); mySql.Append(" cif_type='" + GetCifType() + "',opn_aff_yn='" + GetOpnaFf() + "',"); mySql.Append("opn_sub_cnt=" + opn_sub_cnt + ",opr_aff_yn='" + GetOpraFf() + "',"); mySql.Append("dz_flag='" + GetDzFlag() + "',beg_date=" + beg_date + ", end_date=" + end_date + ","); mySql.Append(" opn_cnt=" + opn_cnt + ",sts='" + GetSts() + "',filler='" + txtfiller.Text.Trim() + "' "); mySql.Append(" where mdm_code ='" + txtMdmCode.Text.Trim().ToString() + "'"); break;
文檔和注釋
我一直都是一個不喜歡寫注釋的人。
在我的開發環境中將注釋的顏色盡可能的變暗,以至於我粗略一看可以忽略他。因為很多注釋真的是毫無意義。
xDoc.Save(savePath); //filestream 讀取XML文件 XmlDocument _xd = new XmlDocument(); _xd.Load(savePath); //用byte類型接收XML文件 byte[] myByte = Encoding.UTF8.GetBytes(_xd.InnerXml); //上傳到服務器,成功后提示 if (TradeHelper.TradeUtils.SaveClientConfFile("Menu.xml", myByte, false)) { this.ShowMessageBox("提交成功", "系統提示"); } //獲取Menu.xml的路徑 string menuPath = Directory.GetCurrentDirectory() + "\\Menu.xml"; //讀取Menu.xml的內容 XmlDocument xd_menu = new XmlDocument(); xd_menu.Load(menuPath); //讀取Menu_Tmp.xml 的內容 XmlDocument xd_tmp = new XmlDocument(); xd_tmp.Load(savePath); //兩個文件內容交換(讓Menu.xml 內容替換) xd_menu.InnerXml = xd_tmp.InnerXml; //保存Menu.xml xd_menu.Save(menuPath);
拿到一份100行的代碼,你會發現可能注釋會有50行,這將是怎么一種感覺?很多時候,我認為文檔比注釋更重要,如果公司的每個項目都有相應的一些必要文檔,我想開發人員也沒有那么累了。
可有人干過專門補注釋的事情?
由於某種原因,代碼可能要有某種形式的驗收,這時候就有個要求,注釋不能少於代碼量的1/3,好吧,我絞盡腦汁的去補注釋,有時候不得已就要使出小學應付作文字數的方式:
/// <summary> /// 獲取HtmlElement 可以根據ID、Name、TagName等組合 /// ID選擇器優先級最高 /// Name選擇器如果能獲得且只有一個,直接返回,不判斷其他 /// 其他選擇器取並集 使用其他選擇器最好指定Name或TagName /// </summary> HtmlElement GetElement(XmlNode item)
其實我更想寫的是思路。
程序設計
關於XML的配置,很不幸的是我手頭有個項目基本就完全符合這種情況。而我們也確實曾經使用webservice來訪問數據庫,在數據庫中存過XML字段等等,XML很強大。
我很討厭諸如此種重構方法的方式:
更恐怖的是除了RefreshToolBox還有RefreshToolBox1、RefreshToolBox2……
雖然我也喜歡在代碼中寫Hard-coded
或者說Magic Number
,但是我真的很排斥用數字作為狀態碼或着說標示符去重構方法。
如果你看到如下代碼:
total2 = total - 45; if(flg == 1) { //... } if(total2 > total3) { //... }
還值得一說的就是過度的面向對象設計。
我至今還是不能把GOF23種設計模式說全,但是不影響我干任何事情。對設計模式的批判仿佛比設計模式的重要性還要多,而面向對象是否是一個騙局,是否符合哲學,我無法去辯駁,因為我真不怎么懂面向對象。
我只是在項目中看到,由於面向對象的設計,無故的多出了很多代碼。往往是我看到這里,跳着跳着已經忘記了初衷。
某篇文章說程序員應該克制寫代碼的沖動,而多多思考,但是正因為這種思想的影響,往往讓我很難下手。
這會讓我寫代碼越來越慢。
因為我總是會考慮很多才會下手:如何寫才能有利於擴展,如何寫代碼才會更好看,如何寫才會減少不必要的bug……以前的我是不會考慮這么多的,一旦想清楚怎么樣才能實現功能之后,我就會毫不猶豫的敲出代碼,而我現在連一個變量該如何命名都會考慮很久。其實對於這種項目來說,有些考慮確實是不必要的,程序設計的再好,再有利於擴展,也很有可能無法滿足一次需求的變動。
以上是某人的感言,很符合我現在的情況。
好了,寫了許多,就不再寫下去了。不管代碼如何,總還是要有人去維護的,每一個程序員都有把代碼寫爛的天分,看一份源碼,有時候真可以了解一個人。
我的博客原文地址:其實根本不用混淆你的代碼
歡迎來我的博客:nanqi.info