你在公司項目裡面看到過哪些操蛋的代碼?
11-25
String resu<
......
return result.toString();
算嗎?
盡情吐槽吧!
相關問題: 你所見過最噁心的代碼片段是怎樣的? - 互聯網
if (m_doc-&>isModified() == true)
{
for (int i = 0; i &< 100; i++)
{
save(); //Save the document for 100 times to ensure it has been saved successfully.
}
}
不知道誰寫的,總之我都看哭了
(a != b) ? b : a
以前在人人上貼了這段代碼來吐槽前公司的代碼質量,被轉發後火了,因為神最右的註解:
和老婆意見不一致的時候聽她的;意見一致的時候聽我的
======================== 關於評論中提到的運算符重載等問題,這裡統一回答一下: 我摘的這段代碼被我省略了上下文。實際情況是,變數是基本類型,也沒有重載運算符等其他讓這段代碼有意義的原因。我剛看到它的時候也絞盡腦汁去想有沒有別的可能,試圖理解這麼寫的用意,最後發現只是代碼寫得爛而已。
enum FiveLine
{
Gold,
Wood,
Water,
Fire,
Earth,
};
看枚舉名字不知道五行(hang)是什麼鬼,看了枚舉內容恍然大霧,原來是五行(xing)……
哎。。。跟你們說個奇葩的事情吧。。。 背景:做手持設備的公司,你們可以理解成手機一樣的東西。
第一家公司有個大神。寫驅動的。 不知道怎麼寫並發的代碼。。。
如果出現問題,就直接sleep。並且創造了自己的一套調試理論。
於是在代碼裡面就會看到各種莫名其妙的sleep(xxx)。 而且很多都還是神奇數字。不按那個休眠,並發就會出問題...
由於大神傑出的工作,讓代碼出問題的概率降到了8小時一次。
又特么由於豬隊友的硬體設計,我們那裡的機器電池在連續使用6小時之後就沒電了,於是客戶相當於每6小時就要重啟一次機器...
嗯...於是,相安無事。
============================== 沒想到幾句吐槽這麼多贊。
看到評論區裡面真的有人這麼寫代碼,又想寫兩句。 借用 @vczh 說的一句話(原話記不太清)
現在硬體性能逐步提升,寫出能跑的程序太簡單,而寫出真正好的程序太難。
希望大家在寫程序上多追求極致和規範。 如果碰到看起來很傻的問題,先多看看別人怎麼解決的。 別什麼事情都想當然。
上面的話說給大家,也更多的說給我自己。
我軟有不少代碼看上去挺好的但是會被標識成操蛋,這都歸功於各種靜態檢查工具。
在我軟代碼裡面起個變數名叫WhiteList都會被自動發bug,因為用White來表示允許就屬於種族歧視,一定要改成AllowList。我會告訴你我們因此還真的改了服務介面而且還要做向下兼容嗎?
還有變數名叫country也會被查,因為正確的說法是country and region。
我不是說public的類成員哦,private的都不行。
另外kill,dead之類的字眼都是有問題的。
當然你真的一定要用這些詞你就得說明理由,然後加supression。
要像 @vczh 那樣變數起名bitch什麼的那是要死一百遍啊。
所以你現在知道寫點代碼有多難了吧。
從長度上來說,完爆樓上各位的。感受下:
if(m_Str2.Find(""")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find(":")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("/")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("!")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("@")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("#")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("$")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("%")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("^")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("*")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("(")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find(")")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("/")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("|")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find(":")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("[")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("]")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("{")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
if(m_Str2.Find("}")&>=0)
{
AfxMessageBox("您輸入的包含非法字元");
m_Str2="";
UpdateData(FALSE);
return;
}
哪怕不知道 RE,也該知道 FindOneOf 啊?!!!! 就是再不濟,也寫個循環吧。 謹遵 DRY 原則的程序員看到這段代碼受到了 1024 Kg 的傷害。
當然,還有什麼: 一個線程回調函數函數寫了 700 多行的事情咱就不說了。 一個小小的項目專門定義了名叫 Global.h/cpp 的文件來放置全局變數咱也不說了。一個小小的項目中一二百個全局變數咱也不說了,這些全局變數中大部分還是指針變數咱也甭說了!!! 我去哭一會去。
---
看見這段代碼的時候,我拍了很久的掌
以前所在公司做激光雕刻軟體,客戶對雕刻速度有要求,於是乎大神把顯示在客戶端的所需時間乘上4/5。後來軟體交給我維護,重寫了界面,新版本到了客戶手裡雕刻速度變慢了,無論怎麼優化雕刻演算法,都不能達到原來的雕刻速度。
後來忘記是怎麼看到那個* 4/5了,真是買了表的
&
&
&
&
&&
&
&
…………
&
&
&
&
…………
&
&&
&
…………
&
&
public enum ColorType { Green, // 綠色 Hong, // 紅色 }
//...... this.curColortype= ColorType.Hong; ...... 毫無違和感! 英語和漢語的激烈碰撞,一時愣是沒讀懂代碼,「Hong」為何物,你看注釋才恍然大悟!犀利 可能是綠的拼音(lv) 有點像等級,所以為了防止歧義,用了Green!贊一個!
!!!!!!!!!!!!! 程序員很可愛,我愛程序猿大家庭! 這些蘊含智慧的代是禮物也是驚喜! 可以幫你拉這麼多贊!感謝! !!!!!!!!!!!!! 真愛身邊的程序員! 愛他們
舉三個我前東家的故事:
1. 寫 Facebook Android的代碼時候看到public void testSetCurrentMessageCount() {
setupGlobalTestEnvironment();
currentThread.setValue(10);
assertEquals(10, currentThread.getValue());
}
public void testGetCurrentMessageCount() {
testSetCurrentMessageCount(); // Couldn"t figure out a better way...
}
對,好像是沒有更好的辦法來測試getter。。。
2. Facebook的Android和iOS的代碼里都大量使用 Dependency Injection,主要好處是 便於測試 和 每個類實例的生命周期便於維護。只是開始的時候為了圖方便,用的是類的靜態方法來拿到 全局的 providerMap。後來Tech Lead規範編程風格之後,禁止大家直接調用靜態的globalProvider方法,從ctor里注入。但是FB里的人圖方便,還是在繼續使用。最後沒辦法,函數名被Tech Lead改成這樣:(由於保密協議,我刪除了實現邏輯的代碼)
+ (FBProviderMap *)globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED {
// ....
FBAssertNotNil(globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED, @"Call +[FBGlobalProviderMap setGlobalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED:] before invoking this method.");
return globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED;
}
}
+ (FBProviderMapData *)globalProviderMapDataDO_NOT_USE_OR_YOU_WILL_BE_FIRED {
return [[self globalProvidersDO_NOT_USE_OR_YOU_WILL_BE_FIRED] providerData];
}
2. 來自FB神童 Evan Priestley 的 Hackathon 代碼 (這哥么高中畢業後開始以寫程序為生,主導FB很多的大項目。離開FB之後創立:Phabricator )。代碼本身並不是有缺陷,只是它產生了一個有趣的段子:
Tech Crunch 一直以來以爆FB的八卦為榮,但是很多時候八卦內容完全不準確,甚至是非顛倒,讓高層很不爽。Evan Priestely 在一次Hackathon的時候在Facebook Photo里加了一個小按鈕 「Fax Photo」,支持把當前照片傳真出去,並且收費1美元(背後直接調用第三方傳真公司的API)。功能本身在2009年的美國當然沒鳥用,當時email,facebook和iPhone都已經高度普及,直接發照片的鏈接或者郵件即可,沒人還想去傳真一下。不過 Facebook 已具備極其強大的灰度發布功能,Evan把這個按鈕發布出來,只允許 TechCrunch 公司的IP可見(除了TechCrunch,其他用戶都看不到),並且在twitter上「透露」了一下Facebook Photo有新功能。
第二天,TechCrunch開始騷動了,一編輯火速發文(伴以截圖)來說明Facebook Photo中「fax this」按鈕的功能:TechCrunch 原文: Facebook Now Lets You Fax Your Photos. I Have No Idea Why Anyone Would Want To Do This 。在產品流程上,還專門花了一刀成功把圖片傳真到了公司的傳真機上。接下來,開始詳細「剖析」此功能開發的初衷和適用場景,最後開始吐槽在這個互聯網高度發達的時代開發這麼一個古代功能並沒有什麼卵用。。。
過了兩天,TechCrunch終於在眾多網友的熱心評價下,意識到自己被耍了。於是又發文補充:Yeah Ok, So Facebook Punk"d Us
Evan Priestely 一直是Facebook很多員工心目中的天才,對,極其有爭議的天才。
// 以下所有left代表右 // 以下所有right代表左
變數命名
class UplaodDuiLie // 上傳隊列
// Uplaod 非手誤,完全原文。
// 為什麼你們只吐槽 typo 而不吐槽中英文混合呢。。
有次看一項目源碼,注釋里有個warning。
// warning: Do not make any changes here. // I got confused why it can run successfully. PLEASE Do not make any changes before you figure it out.
曾經在一個家公司,有一次有人發現對每個請求,有個地方都會空等了一秒。 後來問老大,說,如果客戶有新要求,隨時可以把性能提高一倍以上。。。
很久以前我遇到一個做ANDROID的同事,寫前端界面的時候肯定會有不少按鈕之類的要聲明,有些界面上的控制項比較多,可是他不喜歡聲明變數,對 不只是懶得起變數名,連聲明都懶得寫。所以他直接用數組。。。。 所以他的代碼里會出現很多類似這種: btns[0] list[1] 控制項對象的引用方式,多麼考驗記憶力的編程方式啊,全宇宙只有他自己能維護這份代碼了!!! 這種寫法完全解決了他懶得聲明的問題啊,Button[] btns=new Button[10]; 只需一行代碼,就有十個按鈕可以用了!!!多麼方便啊!!!只要自己一輩子都記住 0是確定按鈕 1 是取消 2 是xxxx
說到這個。 2005 年的剛加入 Opera 的時候, 給一個奇葩的設備做瀏覽器。
代碼裡面出了一個堆錯誤 (heap corruption). 然後會崩掉 ...
有一個新人, 焦頭爛額的做了2個星期,寫出了這樣一段驚天地泣鬼神的代碼(C++)
void reflow(int layoutid, ...)
{
if (this == NULL)
{
return;
}
.....
}
我當場就嚇得魂飛魄散,對這位同學對 C++ 的理解( 一看就不是菜鳥), 遇到問題不擇手段堅定不移的執行力的敬佩之心如滔滔江水連綿不絕,黃河泛濫一發不可收拾。。
尼瑪果然是流氓會武術,誰也擋不住。
這位同學後來當了項目經理, 再最後創業去了,據說還挺成功的。。
PS: 如果你能夠理解這段代碼為何可以工作, 好處壞處能說上來,而且願意來北京工作,聯繫我,我給的薪水肯定比平均水平高多了。。 ======================================================================= 這個其實本意只是一個吐槽而已,說到底這個問題的標題是 「你在公司項目裡面看到過哪些操蛋的代碼?」, 所以,這裡面寫法都是反諷的寫法,沒有看懂的抱歉了。
這是一段非常惡劣的代碼, 其他回答裡面很多代碼其實也就是命名不規範, 做事粗糙,說到底,是開發人員的知識結構,或者是基礎不好。而寫這個代碼的人其實沒有這些問題。
評論裡面很多提到是因為:
p = NULL;
p -&> layout( ..);
引起的。問題的本質確實是這樣子的。
但是這麼簡單的問題,那位哥怎麼可能想不到, 放一個斷點,看看為啥 p 為 NULL。
如果發現 p 是允許為NULL的(比如內存耗盡, 這個在低端設備上面很正常, 畢竟當年設備都沒有分頁系統, 你沒有辦法控制用戶去看什麼網頁,有一些網頁過於複雜,一定會耗盡內存)。簡單的檢查下指針就好了。
if (p)
{
p-&>layout(...);
}
問題,p = NULL 這個事實,是堆錯誤引起的。 也就是說 p = NULL 這個結果,是由於其他 BUG, 在使用堆對象的時候越界,導致 p 的內容被覆蓋了。 由於很多類的(對象)都有 layout 這個類的對象的引用。 而這些對象由於堆錯誤會被概率很低的隨機的覆蓋掉。 這位哥在無法修復堆錯誤的情況下,用了這麼一個極端的方法。
這個是一個非常錯誤的方法, 任何情況下這種代碼都不應該出現你的管理的代碼中(這段代碼是事實也沒有通過代碼審查,我在提交紀錄裡面看這個,大吃了一驚)。
從本質上面, 這段代碼挺體現一個人的性格的,能寫出這種代碼,大多數都是心裏面藐視規則, 為達到目的不擇手段的。
奧運會要來了,街邊建築很舊了,有阻觀瞻,重修來不及了,怎麼辦, 那就刷刷臨街的一面咯,背街不用管了
忘了收拾房間了,宿管馬上來檢查,怎麼辦,全部塞在抽屜里咯。
看沒看出來這些其實都是一回事情。
這種性格做開發人員是非常不適合的,因為這種哲學非常注視短期利益,而軟體開發除非是打一棍子就跑,長期利益其實非常重要,因為短期利益積累起來的問題在長期會指數性的放大。
但是這種性格不見得就不適合項目經理和創業哦?^^, 這裡面得道理就不多講了,做過的可能都會有感受。
關於為何我說 「如果你能夠理解這段代碼為何可以工作, 好處壞處能說上來,而且願意來北京工作,聯繫我,我給的薪水肯定比平均水平高多了。。」 這句話是放在 PS 裡面的。因為如果你能看懂這段代碼, 基本上說明你是了解 C++ 的對象模型大多數情況下是如何實現的。
void class_name::reflow(int x), 在C++中,其實被展開為類似 class_name_reflow(class_name * this, int x).
具體技術叫 name mangling (Name mangling) 所以這樣的代碼
p-&>reflow(10);
如果layout 是一個非虛函數,其實等價於
class_name_reflow(p, 10);
所以 this 只是作為一個普通的參數傳入一個函數而已,於是
((class name *)NULL) -&> reflow(10),並不會立即崩潰。於是給了
void reflow(int layoutid, ...)
{
if (this == NULL)
{
return;
}
.....
}
這種代碼存在的機會。
這裡有一個細節, if (this == NULL) 需要出現在 reflow 函數中引用任何一個成員變數之前。 如果 reflow 是虛函數,這個程序活不了那麼久的,((class name)* NULL) -&> reflow (10)就掛了
因為對於虛函數,這個翻譯為
p-&>vtable-&>class_name_reflow(p, 10);
找 vtable 的時候就掛了。
另外,這個代碼不會引起內存泄漏,說內存泄漏的童鞋你們想多了。
你可能要說,知道這些,又有個卵用呢,反正我也不能寫這種這種代碼。
事實上,從我的經驗來, 如果只是說一個 C++ 開發人員的調試能力(眾多能力的一種),了解 C++ 的對象模型是非常重要的。 C++ 允許很低級的操作(比如直接操作指針), 於是很大部分極其難調的 BUG 都是和內存相關的,如果你不知道 C++ 的對象模型,很多問題完全無從下手。
比如, 如果你知道 C++ 中 this 只是作為一個普通參數,你就會知道,一旦崩潰,棧頂的函數可能並非是崩潰的源頭。
this == NULL 的時候是因為 ((class_name*)p)-&>func(), 那 this == 0x04 (32位機)呢?其實也可能是,只是情況變為 ((second_parent*) p)-&>func()
而實際上 C++ 的對象模型比大多數想的要複雜很多很多。 如果你覺得還不夠好玩的話,我再給你一個例子
#include &
class P1
{
public:
virtual ~P1() {}
};
class P2
{
public:
virtual ~P2() {}
};
class Derived: public P1, public P2
{
};
int main()
{
Derived *b = new Derived();
printf("allocated at address %p
", b);
P2 *s = b;
printf("delete at address %p
", s);
delete s;
return 0;
}
這個可以編譯哦 ^^
這個是運行結果:
allocated at address 0x7fa08bc04be0
delete at address 0x7fa08bc04be8
分配的地址和刪除的地址竟然都不一樣了!! 但是這個程序是沒有內存錯誤的哦?怎麼做到的? 找找原因,說不定你對 C++ 的實現會有很不一樣的理解哦。。
當然如果你連分配地址和刪除地址不一樣這種事情都不敏感,間接證明你對堆分配原理其實也不了解, 那我也不好說什麼了 ^^
對了,這個是符合 C++ 標準的
5.3.5 Delete
3 In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand』s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.
一個交易種類有兩種類型,然後他用true和false各代表一種類型。從頭到尾都用bool類型判斷。然後現在需要添加第三種類型。 呵呵呵呵呵呵呵呵。。。。。。。。。。。
本來還懷疑自己的智商能不能碼農的道路上越走越遠,看了這個問題的回答,又煥發起無窮的信心。
C++:
三萬多行的頭文件;
兩萬多行的函數;
在堆棧上創建一個鎖說是要鎖本函數;
由於智能指針的循環引用導致某個對象泄露,於是裸指針拿出來 delete 之;
析構順序導致推出崩潰,於是強制 sleep 之;
Qt 項目中使用 signal 向 slot 傳遞指針,然後在 slot 中 delete(整個項目都是這樣做的!),導致每個 signal 都是專款專用的;
底層庫用 message box 報告錯誤卡死程序邏輯,導致售後去機房重啟;
底層庫內部監聽固定埠導致系統中只能有一個進程引用他們家的庫;
某對象有個 protected 成員,外部函數想訪問,於是臨時寫一個子類 public 之,然後強制把基類指針轉換為子類指針(說實話我覺得這個智商挺高,腦洞派);
一段程序在本機上調試正常拿到遠程用 Team Viewer 運行就不正常,查了半天原來用了人家 Team Viewer 佔用的埠;
舉個例子:Worker::setDataSource(DateSource* pSrc) 用來設置數據源,結果 HttpDataSource、RtpDataSource 等子類裡面只有數據源的配置信息,所有收取數據的邏輯都是在 Worker 里用超巨 switch 實現的;
函數返回臨時變數的非常量引用,視 warning 而不見,說是性能好;
javascript:
視原生 Object 而不見,自己用數組封裝一個 Map(和 ES6 的Map無關)還巨複雜;
for 循環中使用閉包引用迭代子 i,踩中了閉包傳引用的坑,於是用 jQuery 判斷當前執行了多少次,還特意注釋之;
為了解決動態內容多次綁定事件的問題,每個回調函數都判斷一下自己有沒有被執行過;
類似這樣的「函數式編程」:obj.listen("some-event", bind(curry(asynchronous(chain(……), deley, bind(someObj, curry(callback, anotherObj))), foo), bar));
類似這樣的「神秘主義編程」:var ___ = ..., __$_ = ...,_$____$_$$_HaHaHaDoYouKnowWhoIAm = ...;
注釋: 定製項目里的改動,不刪除老代碼只注釋掉,然後改動旁邊注釋修改人的姓名或工號,這本來倒是沒什麼,但是後來改動多了,還有「定製版的定製」時,代碼就熱鬧了。就像這樣:
//int a = 1;
//int a = 2; // modified by 234561 康莊子項目甲方要求要兩個,支持多個的代碼見下方
//int a = 3; // modeified by 234562 現在要三個了
//int a = -1; // modeified by 234563 馬甲河子項目要求不限制個數,-1表示無窮
//int a = 0; // modeified by 234562 234563改的不對,-1會導致崩潰,應該用0表示無窮
int a = -1; // modeified by 234563 崩潰是其他模塊的問題,這裡就應該用-1,因為0在用戶配置里表示沒有許可權
推薦閱讀:
※你見過最美的漢服照是什麼樣的? ※你見過哪些中國人在和發達國家相比時表現出自卑感的言行? ※情商低有多討人厭? ※吃火鍋時最討厭什麼? ※你自己養的狗和別人家的孩子遇到危險,只能救一個,你會救哪一個,為什麼?
TAG:程序員 | 調查類問題 | 編程 | 代碼 |