慎入:史上最爛的代碼集合
實(shí)本沒有什么代碼是“史上最爛”的,要有也只有“史上更爛”的,我想隨便說說這個(gè)話題,也是源自豆瓣的一個(gè)討論。事實(shí)上,系統(tǒng)復(fù)雜了被罵代碼爛是一件司空見慣的事情。當(dāng)然,也有一些短小的代碼片段,就足以看出代碼作者是個(gè)不怎么樣的人。
布爾類型的使用是很容易變成最爛代碼的:
- if (isTrue())
- if (isTrue())
- doSomething();
- if(boolVal == true) {
- .....
- }
有一些毫無意義的注釋:
- return 1; // 返回 1
- //如果標(biāo)志為真,就返回true
- if(flag)
- return true;
更無意義的是這樣的變量命名:
- public static final int ONE = 1;
- public static final int TWO = 2;
也有人說,最爛的代碼片段應(yīng)該是這樣的才對(duì):
- }
- }
- }
- }
- }
- }
- }
- }
- }
還有曾經(jīng)被罵到遍體流膿的12306.cn,代碼節(jié)選:
- var sig = 0;
- if(searchwordl.indexOf("'") > -1 || searchwordl.indexOf("\"") > -1 || searchwordl.indexOf("%") > -1 || searchwordl.indexOf("#") > -1 || searchwordl.indexOf("&") > -1 || searchwordl.indexOf("*") > -1 || searchwordl.indexOf("(") > -1 || searchwordl.indexOf(")") > -1 || searchwordl.indexOf("@") > -1 || searchwordl.indexOf("`") > -1 || searchwordl.indexOf("/") > -1 || searchwordl.indexOf("\\") > -1 || searchwordl.indexOf(",") > -1 || searchwordl.indexOf(".") > -1 || searchwordl.indexOf("=") > -1 || searchwordl.indexOf("<") > -1 || searchwordl.indexOf(">") > -1)
- sig = 1;
- searchwordl=searchwordl.replace("'","");
- //searchwordl=searchwordl.replace(" ","");
- searchwordl=searchwordl.replace("%","");
- searchwordl=searchwordl.replace("#","");
- searchwordl=searchwordl.replace("&","");
- searchwordl=searchwordl.replace("*","");
- searchwordl=searchwordl.replace("(","");
- searchwordl=searchwordl.replace(")","");
- searchwordl=searchwordl.replace("@","");
- searchwordl=searchwordl.replace("`","");
- searchwordl=searchwordl.replace("/","");
- searchwordl=searchwordl.replace("\\","");
- searchwordl=searchwordl.replace(",","");
- searchwordl=searchwordl.replace(".","");
- searchwordl=searchwordl.replace("=","");
- searchwordl=searchwordl.replace("<","");
- searchwordl=searchwordl.replace(">","");
- if(searchwordl == '請(qǐng)輸入搜索條件'){
- alert("請(qǐng)輸入搜索條件");
- return false;
- }
- if(searchwordl == ''){
- alert("請(qǐng)正確輸入搜索條件");
- return false;
- }
- if(sig == 1){
- alert("請(qǐng)正確輸入搜索條件");
- return false;
- }
- document.getElementById('searchword').value=searchwordl;
還有JavaScript的爛代碼,這實(shí)在太多了,就不貼了。越靈活的語言,越難駕馭,超級(jí)爛的代碼就越容易見到。
Tiago Fernandez做過一個(gè)投票,選舉最爛的Java API:
- 公式是:score = (I can live with) + (Painful * 2) + (Crappy * 3) + (Hellish * 4)
- 結(jié)果,你猜到了嗎?
Java的框架多、語法嚴(yán)格,對(duì)于限制那些要來搞破壞的程序員確實(shí)有幫助。但是真要搞破壞,要限制還是限制不住。以前我接觸過一個(gè)Portlet擴(kuò)展類,一共好幾千行,當(dāng)時(shí)覺得這代碼已經(jīng)夠爛了??墒呛髞砦铱吹搅?000多行的存儲(chǔ)過程,還有7000多行的jsp頁面——我以前以為Java程序員的破壞力要遠(yuǎn)遠(yuǎn)小于C/C++程序員。看來,也不盡然。
我的經(jīng)歷中接觸到的爛代碼,最常見的大概包括下面幾種:
一些命名的惡習(xí),比如“cptct”這種縮略語縮略到幾乎是密碼電報(bào)的方法名,大概是受到Basic毒害,即便是早期的 Visual Basic 版本也在代碼中強(qiáng)制實(shí)施了一些約束(如變量名的長(zhǎng)度、模塊中允許的變量數(shù)和模塊的大小)。
早些年的web項(xiàng)目(甚至包括現(xiàn)在的一些小公司做的web項(xiàng)目),不懂解耦、不會(huì)分層,邏輯全部揉在一起,一坨屎一樣。頁面模板直接訪問數(shù)據(jù)庫、樣式代碼散落在世界各地,HTML寫死在各種邏輯里。
在某些程序員眼里,“復(fù)用”==“繼承”,只要有可復(fù)用的屬性、公共的方法,就設(shè)法用無敵霹靂繼承大法來解決,也不管適不適合,一級(jí)又一級(jí),***一定是一棵偉岸無邊的繼承樹。
無窮無盡的工具類。這類代碼比繼承大法的代碼好不到哪去,XXHelper、XXTools這樣的靜態(tài)類滿山遍地都是,但是復(fù)用的眼光倒是比只會(huì)繼承多了一條路……
不會(huì)用標(biāo)準(zhǔn)庫函數(shù)、封裝好的類庫。我見過好幾個(gè)這樣的程序員,對(duì)于Integer、Long、Double這些數(shù)值對(duì)象類型的定義、方法幾乎完全不了解,倒是對(duì)String很熟悉,所有的轉(zhuǎn)換、校驗(yàn),全部都轉(zhuǎn)換成String以后完成,完成后再轉(zhuǎn)回來。
上帝類。本質(zhì)是對(duì)類的職責(zé)單一不理解。用Java、C++的程序員寫出上帝類也就罷了,今年我居然聽朋友說到一個(gè)寫Ruby的有相當(dāng)工作經(jīng)驗(yàn)程序員寫出一個(gè)巨大的上帝類來……
滿大街亂跑的設(shè)計(jì)模式。本質(zhì)是過度設(shè)計(jì)。好好一個(gè)“new Template()”非要引入工廠,再搞一個(gè)策略模式、模板模式,不過癮,***加上注解來實(shí)現(xiàn)……
大部分的JavaScript、CSS。不解釋。
今天有同事說,代碼之所以成為爛代碼,很大可能是寫代碼的人會(huì)遇到比后來讀代碼的人多得多的問題,雖然寫代碼的人解決了大部分的問題,但是剩下的問題還是足以讓代碼遺臭萬年。不過我不這么看,我看到過年份比較早的VB代碼、還有Delphi代碼,雖然都是界面開發(fā)用的,雖然很多理念遠(yuǎn)遠(yuǎn)不及今天,代碼依然清晰易懂。
有的程序員說,工期緊、項(xiàng)目重,領(lǐng)導(dǎo)催得我天天吐血,迫不得已我寫出了爛代碼??陀^原因千千萬萬,我確實(shí)無話可說,畢竟在物質(zhì)文明還非常虛弱的時(shí)候,還是不要扯精神文明的蛋。但是,優(yōu)秀的程序員是有追求的,而人是會(huì)麻木的,總是把項(xiàng)目壓力掛在嘴邊的,給一個(gè)寬松的限期也不見得能如何。
還有的程序員說,唯物辯證法告訴我們,任何事物都有兩面性,所以我們要學(xué)習(xí)爛代碼中好的設(shè)計(jì),并且把糟糕的設(shè)計(jì)引以為戒……我說,得了吧。爛就是爛,把屎放在冰激凌蛋筒里也還是屎,那么矯情干什么?
有很多程序員總有一種推倒重來的沖動(dòng),特別是看到爛代碼的時(shí)候。我也曾經(jīng)如此。其實(shí)這是危險(xiǎn)的。況且在很多情況下你的重寫未必有他原來的爛代碼好。也許你能解決其中的30個(gè)問題,卻引入了50個(gè)新問題。重構(gòu)還是要在業(yè)務(wù)模型和流程清晰的情況下盡量小改動(dòng)、劃模塊入手,大開大合總是危險(xiǎn)的。
總說十五年前吃過多少多少苦的程序員我一點(diǎn)都不佩服,我佩服的是在十五年前那種條件和觀念下,依然能夠?qū)懗霈F(xiàn)在看來都讓人無比舒坦代碼的優(yōu)秀程序員。不寫爛代碼就是愛惜生命、節(jié)約資源、保護(hù)地球,寫好的代碼就是一個(gè)程序員的素質(zhì),沒有那么多理由可以講。