為什麼有些大公司技術弱爆了?

今年年初,到一家互聯網公司實習,該公司是國內行業龍頭。

不過技術和管理方面,卻弱爆了。

那裡的程序員,每天都在看郵件,查問題工單。
這些問題,多半是他們設計不當,造成的。

代碼寫的一團糟,全是複製粘貼,連作者都沒改,大家普遍不寫注釋,也不格式化,代碼歪歪扭扭。

一個項目里,httpclient竟然出現了四種。
一種是該公司研發部寫的,
一種是老版本的開源項目,
一種是新版本的開源項目,
還有一種是開發人員造的輪子。

打介面請求響應日誌,竟然不知道用攔截器。
打錯誤日誌竟然不打上下文信息,每個人一種日誌風格,千奇百怪。
許多重要的中間流程,居然不打日誌。

idea、eclipse、myeclipse的配置文件竟然全部傳到項目里去了。

該公司混了兩年的程序員,跟快遞公司做查詢介面,竟然不知道加密運單號。

所有服務間通訊,都沒有設requestId,導致跟蹤會話很困難。

一個沒什麼qps的邊緣介面,居然做消費者生產者+阻塞隊列的非同步模式。
顯得你技術少是不是。
不知道非同步會增加維護成本,提高測試難度嗎?
而且,任務隊里沒有考慮持久化,趕上發布,丟了好多任務。

讀取一個小小的xml和exc配置文件,居然用流式解析,沒見過這麼二逼的,真是醉了。

做優化全靠拍腦門拍大腿,難道不會用excel分析日誌,用jprofile掃項目?
一個100以內的常數集合遍歷,他也要寫個優化演算法進去,演算法跟業務還攪在一起,一團亂麻。
每個人都在嚷嚷性能、演算法、分散式計算……

幾乎沒有文檔,全靠從代碼反推邏輯。

有枚舉他不用,非要在每個頁面上,把枚舉值挨個兒寫死,知道後面改代碼多麼費勁嗎?

欺騙性的變數名,裡面存儲的是AES加密的,變數名後綴卻寫成了DES;裡面存的是小寫字母,卻寫成upperStr。
一個方法十幾個參數,有三分之一是極其簡略的縮寫,注釋肯定也沒有的。
一個類寫到三四千行是常事。

開發自測,居然要把代碼全丟到公共機器上,而且都是走svn,他們把svn當ftp用。
svn裡面大量的無意義提交,一多半的提交連都編譯不過去。
我看到有個應屆生,改了兩句話,馬上提交,說是怕代碼丟失。

一個運行了兩年的項目,spring的包掃描明顯配錯了,有些bean根本掃不進來,居然沒有人發現。
一半的bean在spring管理下,另一半的bean他們自己寫單例模式來實例化。

他們用mysql來做審計系統,出報表,有個報表要跑8分鐘。
原來是有人用字元串來存多值(逗號分隔),sql里寫了like,導致沒有利用到索引。
為什麼不用pg,pg在sql編程方面,功能更豐富,更適合做統計,它本身就支持數組。

程序員們都是得過且過的態度,怎麼把代碼灌進去,跑的通測試,就算交差了。

為什麼大型互聯網公司,技術和管理這麼差勁,是怎麼形成的?
(這家公司是賣機票的,沒有明確說出公司名字,是怕給自己惹麻煩)


甲:這個A開源庫舊版本有崩潰問題啊
乙:換新版本的A
甲:換了新版本A,用舊的 GCC 編譯不過啊
乙:換新版本GCC
甲:換了新版本GCC,B開源庫不兼容啊
乙:換新版本的B
甲:換了新版本的B,導致性能下降啊
乙:開多線程
甲:開了多線程導致延遲抖動不同步了
乙:換新的延遲修正演算法
甲:換了新延遲修正演算法偶爾會崩潰啊

乙:要不。。。我們還是去看看那個A開源庫的舊版本崩潰能不能修好吧

如今上點規模的IT公司,其軟體項目的規模和複雜度都遠遠超過工程師的能力上限了,都只能小心翼翼地修補,有時局部的大改動會引發連鎖反應,大改動的風險和成本很難控制,沒有巨大的收益誰也不敢隨便改,你能看到的問題老員工看得更清楚,甚至也清楚怎麼解決,但是不動手的原因就是不知道出了事誰來背黑鍋,技術上的事情誰敢說100%不出事的。

那是不是大公司的技術項目就沒救了呢?
也不一定,有些事要等個機會的,常見的機會:
1. 技術基礎平台大革命,比如移動互聯網的興起,從PC遷移到了手機端,很多舊的技術代碼就可以拋棄了,手機上從零開始。
2. 競爭對手小宇宙爆發,對手搞出一項技術取得了競爭優勢,被迫追趕,這時候死馬當活馬治,改出任何問題也都能忍了。
3. 人事大動蕩,管理層和基層都大換血,舊代碼已經沒人有能力維護下去了,不得不重來。


樓主你好,我試著給你解釋一下,希望你能滿意。


新手經常會有這樣的想法——「這代碼怎麼這麼爛?寫的人幹什麼吃的?怎麼能這樣?為什麼不按照書上說的做?」,這很正常,大家都年輕過,經歷過這種階段,我懂你心裡的想法,所以也願意詳細地向你解釋,這一切發生的原因是什麼。

你說「

不過技術和管理方面,卻弱爆了。

那裡的程序員,每天都在看郵件,查問題工單。

這些問題,多半是他們設計不當,造成的。


你真的覺得『國內行業老大的互聯網公司』會是技術和管理弱爆了的樣子嗎?

你以為團隊應該像永動機,但現實永遠有各種摩擦、輻射、損耗。

內燃機的能量轉化率,通常只有 30% - 50%,但是它卻是驅動全世界運轉的核心引擎,順豐京東的快遞小車、聯通全國的高鐵動車綠皮、瞬時直達的飛機……


機器尚不能 100% 效率運轉,何況是人呢?

你說我們的程序員每天都在查看郵件、問題工單,你說這些問題多半是我們設計不當造成的,請問你有試過統計數據嗎?你大概只是『感覺』如此吧?

事實上,經過十幾年的發展,我們內部的『效率改進團隊』已經非常高效成熟,每月、每周、甚至每天都會有新的改進,現在的業務處理方式,不說全世界,我可以自豪地說在全國我們是領先的,甚至是遙遙領先,不然憑啥坐到了全國龍頭老大的位置呢?

所以啊,你只看到了程序員花在業務上的時間,沒看到我們內部的『效率改進團隊』為程序員們省掉的時間,我覺得我有必要站出來為默默付出的『效率改進團隊』說幾句。


當然,樓主作為實習生,不知道這些事情進而產生了這些疑問,也暴露了我們的不足。我已經在『團隊建設委員會』里提出了這個問題,大家一致通過了決議,以後我們會對新員工——包括實習生加強企業文化、歷史培訓,確保我們的新夥伴們不僅知道要去哪兒,也要清楚我們從哪裡來,長路漫漫,我們一同前行。

你覺得「

代碼寫的一團糟,全是複製粘貼,連作者都沒改,大家普遍不寫注釋,也不格式化,代碼歪歪扭扭。

當初公司起步的時候,整個項目都是幾個初創程序員加班加點熬出來的,我知道你看過《代碼大全》、《程序員修鍊之道》、《Unix 編程藝術》,你對上面的準則信手拈來,你可否翻開床頭柜上的這幾本書,看看它們的出版時間呢?


是的,公司起步的時候,這幾本書根本還沒有出版,彼時中國互聯網方興未艾,大家都是摸著石頭過河。現在你遇到問題,你可以問朋友、問導師、用谷歌、用棧溢出、用知乎,我們寫程序那個年代,看的是譚浩強、嚴蔚敏,用的是 52k 撥號上網,語言只有 C,編輯器是沒有語法高亮和實時編譯的,編譯器是沒有智能準確的報錯的,沒有現在這麼多知識、也沒有這麼多規範和好資源、好工具。不過我們還是把項目做出來了,把公司一步步推到了現在的位置。


不過這個問題是客觀存在的問題,誰也不否認,但是你知道為什麼你被分配到了一個『代碼看上去一團糟也不夠規範』的項目嗎?我們需要新鮮血液來重構一些老代碼,所以你會被分配到艱苦的崗位上。我們希望你是勇於戰鬥的戰士,我們更希望你能成長為經驗豐富的老兵,而把你放到這種崗位,是對你來說成長最快的方式。

你認為「

一個項目里,httpclient竟然出現了四種。

一種是該公司研發部寫的,

一種是老版本的開源項目,

一種是新版本的開源項目,

還有一種是開發人員造的輪子。

你不知道的是,我們最初用了開源軟體(也就是你所說的『老版本』),它構成了我們早期項目的基石,隨著業務複雜性增加,我們改進並最終切換到新版本。

這個軟體跑老業務非常成熟,但是在一些新業務上有不可調和的矛盾,所以在痛苦的適配後,研發部的同事們自告奮勇用 20% 的時間寫了新業務的組件——是的你沒看錯我們也有 20% 時間,我們鼓勵工程師的創新。


至於你說的開發人員造的輪子——這說起來可真有趣,它其實是前年來的一個清華大學實習生寫的。


當時他來了之後,針對他接手業務的需求,向我抱怨說現有的 3 種都不好,要寫一個新的來『統一天下』,這話是他的原話,我記得非常清楚,因為以我多年經驗來看這樣的做法是不可取的,但是本著鍛煉年輕人的心態(加上他的確是不可多得的天才),我同意了他的請求,於是我用自己的業餘時間接管了他的大部分工作,全力支持他寫一個新的組件,幫他擋住了所有上面的壓力,後來的故事就是你看到的這樣。

是的,他後來越深入、就越來越感到業務的複雜,不斷推翻重構、拆東牆補西牆,但始終發現和自己想的根本完全不一樣,受不了了就走了,留下來這個。


我們明年的規劃中,就包括剔除這個組件的 codebase,因為它實在是太糟糕了。

你又說「

打介面請求響應日誌,竟然不知道用攔截器。

打錯誤日誌竟然不打上下文信息,每個人一種日誌風格,千奇百怪。

許多重要的中間流程,居然不打日誌。

idea、eclipse、myeclipse的配置文件竟然全部傳到項目里去了。

該公司混了兩年的程序員,跟快遞公司做查詢介面,竟然不知道加密運單號。

所有服務間通訊,都沒有設requestId,導致跟蹤會話很困難。

攔截器並不如你所想的那班美好,也許你在自己的電腦上寫過一些玩具代碼,覺得這樣很方便、酷炫,但是真正到了戰場,你會發現沒什麼才是必須的、好的,只有適合的才是對的。


至於配置文件,這麼說吧,IDE 的配置文件傳到代碼倉庫是我定下的規矩,『怎麼會有人定這樣的規矩?』,是的你可能從軟體工程的教科書上或者某些『知名博客』上讀到了不能這樣做,但實際上這樣做在很多情況下是必須的。

原因何在?

這樣可以確保代碼克隆即可用,而不是讓每個人都去設置一大堆無聊的東西,這樣不僅節省時間,也確保了每個人的環境一致性,你想想這幾年火熱的 docker,應該明白了這樣做的正確性和必要性了吧?

你可能會說即便如此、插件也不用上傳到伺服器保存,我告訴你這樣是不行的,你要考慮到我們這個項目前後十餘年,你覺得幾個插件能堅挺十餘年?很可能我們早期用的軟體,現在你已經完全不可能找到了,所以保存一份備份是非常有必要的,決不能錯誤地認為是冗餘。


教科書只會教你基本通用的原則,樹立你基本正確的觀念,但是如果只是死守教條,如何能擁抱日益複雜的變化呢?

你看的教科書,且不說時間上已經是二十多年前的了,在適用性上,也不說就是真理,IT 行業發展日新月異,幾個月就是滄海桑田,為了適應這樣的變化,認真地思考、總結、判斷才是最重要的。

你覺得「

一個沒什麼qps的邊緣介面,居然做消費者生產者+阻塞隊列的非同步模式。

顯得你技術少是不是。

不知道非同步會增加維護成本,提高測試難度嗎?

而且,任務隊里沒有考慮持久化,趕上發布,丟了好多任務。

讀取一個小小的xml和exc配置文件,居然用流式解析,沒見過這麼二逼的,真是醉了。

你大概不知道,當初跑在你口中的「一個沒什麼qps的邊緣介面」上面的業務帶來了公司曾經 90% 的收入,所以我們用了複雜的設計以應對當時的需求,當然現在業務轉變,老系統不再需要處理那麼多業務了,但是更沒有理由為一個『works perfectly well』並且不再重要的業務重構代碼吧?

所以,不是我們秀技術,而是業務需求 + 業務變更使然,年輕人還需要多學習一個。

你抱怨「

做優化全靠拍腦門拍大腿,難道不會用excel分析日誌,用jprofile掃項目?

一個100以內的常數集合遍歷,他也要寫個優化演算法進去,演算法跟業務還攪在一起,一團亂麻。

每個人都在嚷嚷性能、演算法、分散式計算……

幾乎沒有文檔,全靠從代碼反推邏輯。

有枚舉他不用,非要在每個頁面上,把枚舉值挨個兒寫死,知道後面改代碼多麼費勁嗎?

欺騙性的變數名,裡面存儲的是AES加密的,變數名後綴卻寫成了DES;裡面存的是小寫字母,卻寫成upperStr。

一個方法十幾個參數,有三分之一是極其簡略的縮寫,注釋肯定也沒有的。

一個類寫到三四千行是常事。

我再強調一次——我們是全中國同類公司中技術能力第一的,你所說的問題,當然是不存在的。

我們有專門的 Hadoop 集群來分析日誌,當然也就用不著 Excel 了。


對於我們這種體量的公司來說,不存在什麼『常數集合』,代碼必須用合適的數據結構——這是常識吧?

特殊的演算法和業務摻雜以增加內聚性,這是我們多年的經驗,的確,它和教科書上說的不一樣,但是我前面說了,死守教條是不行的——想必你一定知道 OSI 7 層網路模型吧?

公司的技術氛圍濃厚,是和公司的基因分不開的,我們公司最重要的原則就是——『擁抱變化』,從十幾年前的機房託管單機到現在的龐大自建集群,技術躍遷了何止千萬里,所以每個人都在學習新知識、每個人都沉浸在新知識的喜悅中。


你的問題,大多都是因為沒有考慮到公司的龐大體量和十幾年的技術躍遷才有的疑問,這點不再贅述,自行體會吧。

你想的是

開發自測,居然要把代碼全丟到公共機器上,而且都是走svn,他們把svn當ftp用。

svn裡面大量的無意義提交,一多半的提交連都編譯不過去。

我看到有個應屆生,改了兩句話,馬上提交,說是怕代碼丟失。

一個運行了兩年的項目,spring的包掃描明顯配錯了,有些bean根本掃不進來,居然沒有人發現。

一半的bean在spring管理下,另一半的bean他們自己寫單例模式來實例化。

其實那不是 SVN,那是我們公司自主研發的適應我們內部需求的 源代碼管理系統 和 文件管理系統,你可以往裡面放任何東西。

你所說的「無意義提交、一多半的提交連都編譯不過去」其實只是表象,這套系統代號 TITAN,它自帶 CIDD(持續繼承、交付、部署),所以這些無法編譯的提交都是不會有機會走到下一步流程的的。


如果你工作了一年,你就會發現這個需求是很重要的,改動、尤其是大型改動,中間會有很多非可用但有需要存檔的步驟,現有的源代碼管理系統都不能很好地支持這些需求,因此你也被教育了一套適應落後工具的思想。人啊,最重要的能力是改進工具,所以用 TITAN 的時候要擁抱全新思維,不要被落後思維捆綁。


如果你工作了幾年,你可能還會問為什麼我們沒用 Jenkins、Travis 等工具,其實呀,就在 TITAN 之中呀,它凝結了公司最優秀的人才的十幾年寶貴經驗和心血。

By the way,我們最近正計劃開源它,為中國開源社區做貢獻,也希望提高業界的綜合素質。歡迎你提交 PR 哦

你最後說「

他們用mysql來做審計系統,出報表,有個報表要跑8分鐘。

原來是有人用字元串來存多值(逗號分隔),sql里寫了like,導致沒有利用到索引。

為什麼不用pg,pg在sql編程方面,功能更豐富,更適合做統計,它本身就支持數組。

程序員們都是得過且過的態度,怎麼把代碼灌進去,跑的通測試,就算交差了。

為什麼大型互聯網公司,技術和管理這麼差勁,是怎麼形成的?

為什麼不用 pg?如果你抱著這種想法,那用了 pg 也要被噴的,到時候就就會說 —— 「為什麼不用 sqlite,輕量簡單,搞這麼複雜真的有必要嗎?」,真的有必要。。。

這只是一個很簡單的系統,做的事情也很簡單,當初做這個系統的同事更熟悉 MySQL,當然 MySQL 是不二之選了,對於簡單的東西,追求的是開發速度、使用便利性。

你覺得一個月跑一次的審計代碼,8 分鐘有什麼問題嗎?就算是一周跑一次,當然也是沒問題的。

程序員的單位時間是如此寶貴,為了優化一段一個月跑一次的 8 分鐘代碼,值得花費數天的時間來做這件事嗎?

重複一遍,你的問題,大多都是因為『沒有考慮到公司的龐大體量和十幾年的技術躍遷才有的疑問』,這點不再贅述,還請自行體會。

當然,年輕人樂于思考,這是好事,是希望,新鮮血液替換老舊部件系統才能健康發展成長,人如此、公司如此、國家也是如此。

希望你勤于思考,努力學習,有問題的話,我們公司是鼓勵同事們向 CEO、CTO 寫信的,不然也不會有 CEO、CTO 信箱了你說對嗎?

當然,這樣的技術性問題、你寫給我就好,CEO 是船長,不需要關心底層鍋爐房的細節。

另外我想補充一下我的想法,希望對你有所幫助。


你看你都沒說加班問題,我們公司沒加班啊,這多好,怎麼做到激烈競爭下還能不加班的?都虧了公司老領導和元老們的一手決策

所以我想補充的不是技術問題,技術問題都不是問題,年輕人可以學習、交流,技術都會很快成長,畢竟年輕人的衝勁大、頭腦靈活。

我想說的是整體觀、大局觀、大棋戰略。


黃金的導電性最好,為什麼電腦主板還要用銅?

清華大學最好,為什麼有人要去普通學校?

飛機最快,為什麼還有人坐火車?

因為資源都是有限的,我們在現實生活中——而不是教科書上——必須兼顧成本和產出的平衡。


你問我每行代碼都多人多層人工 review 好不好?問我支不支持?我說好,review 我怎麼能不支持呢?我今天在知乎這個公眾平台我明確說了我支持。

但是你也應該多學習一個,這個現實畢竟是現實,我們要兼顧各種考量。

你今天在這裡渲染「大公司技術和管理這麼差勁」,是不對的、是失實的、是欠妥的、是缺乏認真思考的、是未加深入考量的。

將來輿論出了偏差,你雖然不用負責任,但是你認識到自己的錯誤的時候,會後悔、會內疚、會難過的吧?

何處烏托邦?或許……等下一代?

總結就是,生產效率才是最重要的,世間萬物最重要的是平衡。

怎樣取捨、如何妥協,這不僅是大自然的規律,也是我們前進、發展的準繩和仰仗的原則。

————

@bhuztez 滿意嗎


題主你看到了很多槽點,但我認為你不能只看到槽點和大概怎麼解決。有沒有想過怎麼改進,如果是你的話你怎麼做,這些項目裡面臨的主要挑戰是什麼,次要的挑戰又是什麼?

不要只告訴我技術A弱爆了,用B就可以完爆這個項目了。你知道用B的優劣,B的適用場景以及適用B的成本嗎?對於一間公司來說,成本是很重要的。我這裡說的成本不是金錢。而是,假如你看不爽一份代碼,你打算重構它,你覺得你需要投入多少時間,多少人力?重構之後,又要花費多少時間和人力去升級依賴這份代碼的其他項目?不要以為開會無用,老闆就只是在天天發郵件。如果你重構了一份代碼,不能通過溝通說服其他組去升級他們的組件,又或者你只是重構了一份雖然很醜陋,但其實並沒有多少程序依賴它的代碼,又又或者你重構了代碼只是讓代碼技術含量更高了,更好看了,卻沒給公司帶來多少收入甚至KPI,那你的工作和成果就很尷尬了。

其實上述也解釋了為什麼你身邊的同事都眼睜睜地看著這些醜陋的shit存在而無動於衷。因為他們也是需要投入成本的。先不論他們個人技術水平高低,試問誰願意挑一個又艱難,又不能產生多少效益的任務去做?當然,你會說,寫好代碼是程序員的節操。抱歉,節操多少錢一斤,北京三環商品房多少錢一平?

編程高手都有真愛,但現實就是編程高手鳳毛麟角。我們身邊的大部分同事可能只是希望養家糊口,他們頭上還掛著十幾個bug等著修。我們數落他們沒追求,但追求從來都不是嘴上說說,吐吐槽就能實現的。


人心如此,公司也如是。

矛盾分主次,公司的目標都是一樣的:用最少的成本投入到最能產生效益的項目中去,或者投入大成本去解決公司最需要解決的問題,這間公司才能繼續運作。

所以題主你想想,在你吐槽的個案中,有多少是公司真正關心的?有哪些是你的老闆認為可以創造最大效益的?有哪些才是主要矛盾或者挑戰需要最牛逼的人挺身而出第一時間解決?去辨別,解決這些關鍵的問題吧,騷年。必要時帶上(忽悠)一隊人馬(同事)跟你一起干,苟富貴,勿相忘。不要像祥林嫂一樣,天天抱怨著生活,日日思考著辭職。得罪點說一句:「淪落」到要跟這樣的人共事工作,難道自己身上就沒有原因?

這個世界有更好的公司,有更牛逼的人。如果你認為解決這間公司的這堆問題不值得,又或者同事實在太不給力,就遠走高飛吧。

我以前也跟題主一樣,看我第一份正式工作的很多技術環節都相當不爽。這份代碼寫得丑,那個設計像大學生作品,重要的項目居然連單元測試都沒有……但是我後來反觀我自己,並沒有發現比起那些醜陋代碼和糟糕實現強悍多少。我跟我的同事沒有質的區別。我笑話他們代碼混亂bug不盡,我何嘗不是少處理了一個field,倒騰錯了一個片段的數據搞到要翻工重跑?在我心底里艹了隔壁組那個「我的程序好像不能跑,你幫我debug下」的同事一千次之後,帶我做ML讓我倒騰數據並且被我的程序搞壞了幾份數據(當然後來搞好了)的T9君在會議上說:「她已經很努力了,我承認我有時候也逼得她太緊,她應該有多些時間的。」

我不是長者,不能share多少人生經驗,就留下最後一句話跟諸君共勉(好像有點怪)吧:
我觀別人大傻逼,料別人觀我亦如是!


題主有年輕氣盛的一面,但是你說的問題確實是常常存在的。

大公司常常會遭遇兩種病症,我管它叫「滑坡與蒸發」現象。

具體病症如下:

1.滑坡:招聘標準持續降低。人資的硬標準或許在提高,但是實際技術標準在降低。s 級的老一輩面試官,能容忍 a 級的應聘者,過了幾年這個 a 級的應聘者自己成了面試官,能力卻沒提高到 s 級(提高不僅靠個人努力,也要看歷史行程),於是他能容忍 b 級的應聘者……所以叫滑坡現象。

尤其是當這家公司歷史上經歷過極速壯大時期的話,滑坡現象就更加明顯。你甚至會發現一線員工技術水平遠低於早已脫離一線的經理層。

2.蒸發:如果團隊建設跟不上業務發展,大部分人都會處在疲於奔命實現需求的狀態,技術水平和交付質量長期得不到提高。個別人由於努力和運氣,技術提升較快。如果他沒有一個清晰的通道將能力體現出來,就會出現兩種可能——要麼他會拒絕繼續提升,反正現在也夠用了,同事還不如我呢,大公司一般又不裁人;要麼他覺得同事不行,跑了,蒸發了。最終留下來的人反而是相對平庸的人,那些利用公司資源達到較高水平的人反而讓其他公司得利。

最終當你來到這家公司的時候,你就會奇怪為什麼他們的技術不如你想像的好。其實不是沒有能人,只是要麼在經理室里,要麼已經蒸發了。

PS:我補充一點,已經有相關領導澄清了,題主的觀察可能有偏頗。但是我假設題主的觀察沒有偏頗,那麼是不是你理想中的項目狀態就一定好於你看到的「亂糟糟」的狀況?

答案是不一定。

不說大道理,我舉個例子,題主在互聯網圈子裡,可能沒見過一個版本控制工具,叫 ClearCase,IBM 開發的。特點是極其嚴謹,極其強大,極其複雜。如果你只看流程圖的話,那絕對是嚴謹到完美的版本控制系統。但是實際用起來的體驗如何呢?只能說,讓人撓頭啊……所以,你想像的那種「清晰而優美」的項目,維護起來,可能是極其難受的。


這個問題值得聊一聊。

許多大公司技術弱代碼爛?確實是這樣。
題主只是個年少氣盛的實習生,眼高手低,不了解就亂罵?很可能也是如此。

為什麼許多大公司技術弱代碼爛?因為它們本身是業務主導,而非技術主導。創始人也很有可能是銷售/市場出身而非技術出身。技術並非公司的核心優勢。

當領導層走的是業務思維的時候,就很少會從技術方面考慮如何解決問題。抓業務要緊,系統怎麼趕工也要先跑起來。想重構?有好處嗎?搞壞了系統怎麼辦?上馬新技術?有成功案例嗎?我們可不要做小白鼠。等等。重業務輕技術無可厚非,作為CEO只要能領導公司賺到錢讓股東滿意,就是好的CEO。說句難聽的,只要公司運營沒問題,如有必要,讓你們這群碼農天天給IE6寫Javascript都是合理的。賺錢是公司的要務,滿足碼農的好奇心求知慾不是公司的要務。委婉的說法是你未能適應企業文化。直接的說法是你進錯公司了。

再強調一句,非技術主導逼著碼農兼容IE6並不意味著這個公司差勁,或者比起那些上React的公司要怎麼低級。沒有這回事。僅僅是運營方向和策略不一樣而已。

高票答案洋洋洒洒說了一大堆,總結其實就是一句話:系統能跑,為什麼要改?
這裡那裡的問題,碼農搞起來確實很痛苦。那又怎麼樣?花錢雇你不就是要你承受這種痛苦么?只要能雇得到,系統能跑,花的錢在成本核算里過得去,就是合理的決策。

除非哪天系統實在太爛崩盤了,影響到了業務,那才是只顧業務不顧技術的領導層的失誤,那時候你可以指著CEO的鼻子說「老子當時說了要重構你不聽」。不過我想你是沒有這種機會了。因為這公司不是G-F-A-A-L,它只是個網上賣機票的。

說到Amazon,它也沒先進到在倉庫里裝自動機器人。Amazon在倉庫里雇的是工人,每人別一個低科技BP機。

想玩高科技?
想寫有活力的代碼?
想敏捷?
想快速重構?嘗鮮各種開源?甚至維護公司的開源項目來個名利雙收?
想像Facebook一樣一天發布十幾次新的feature?
想在27寸視網膜屏的iMac上面寫完代碼以後到公司廚房拿一瓶飲料然後打會乒乓球然後再讓公司雇的按摩師給你理療半小時然後回到Github上看你的項目又拿了幾個星最後開著特斯拉回家?

去那些拿足了VC的錢不知道怎麼花的科技創業公司。或者Google。它們才是視技術為生命代碼寫在DNA里的公司。

但你沒去,你去的是個賣機票的公司。在網上賣機票,也算「互聯網公司」,不過你不能指望它有多高的技術,人家發家不是靠這個。

所以,不是「為什麼大公司代碼爛」,而是「為什麼我只能進爛代碼的大公司」。

還有需要捫心自問的就是什麼叫「技術強」。許多半吊子碼農認為用上了Github上的火熱新品,能寫幾段酷炫的玩具代碼就是技術強了,看不起項目里的老代碼。殊不知,許多新項目根本活不過幾個月,能活得久的項目也是半年出一個大版本,API全換一遍,讓你欲哭無淚,你倒是升級還是不升級的好?如果讓這些半吊子決定系統架構,死都不知道怎麼死的。


掃了一下樓內的答案,其實就是兩種回答:

1. 理想主義: 現在的代碼太爛了,應該去改改改
2. 現實主義: 支撐現有業務就是最好的代碼,你說爛那是你不懂

一個團隊,在任何時候,都應該分辨得出:
分辨什麼樣的爛是真爛,什麼樣的爛是業務複雜;
分辨不出,就不要去修改。

也應該積極尋求:
如果是業務複雜,能不能更簡化更抽象一些;如果是爛,能不能在有限的成本中改好一些。

對於一個長期維護的軟體和系統而言,
爛是合理的,懶是不合理的。不合理的事情多了,只會讓未來更合理。

---------------------下面才是正文-----------------

為什麼新人總是會覺得有落差,通常並不是新人的問題,也不算是現有產品的問題。

考慮到系統是經歷了業務A - B - C這樣的轉換過程(這個 @蕭井陌 也提到了例子),然後代碼也是從無到有慢慢起來的,當時的Precondition,以及Dev Path,所以實際上現有代碼是

f(Precond, (A, B, C), DevPath)

然後新人來了後,只能看到現在的Condition,和現在的業務C,所以得到成本最低的系統是

g( Curcond, (C) )

有區別當然是正常的。
即便是持續重構所解決的,也只是降低A - B - C的業務變遷中成本,並不是現時的最佳方案 g。
而且,產品本身是要演進的,我們所要做的,是讓產品到下一個版本,也就是Cost( f_{c}, f_{d}   )的成本最小化,而不是f_{c}自己的成本最小化。而這個Cost(f_{c}, f_{d})最小化的時候,往往f_{c} 
e g_{c}

我舉個例子,系統在B的基礎上實現C,引入了State設計模式。從C到D,仍然適合State設計模式。但是如果只看C,這個State很可能就被退化掉了。
這樣,Cost(g_{c}, g_{d})反而要大於Cost(f_{c}, f_{d})


因為公司主營業務是賣機票,IT只是支撐主營業務而已。
在企業認可的預算範圍內,只要能支撐好主營業務,IT部門內部搞得好一些還是壞一些,上層不會有人在意。
尤其在我國目前的市場環境,增加營收還是比控制成本重要。


有一天你家蓋別墅的時候,經過四五個工程隊轉手,你就能體會到同樣的痛苦了。

特別是有些工程隊的優秀小工,想推翻框架用更合理的方法來蓋,卻因為許可權問題無從下手,當他成為負責人的時候,時間已經太久,經過通盤考慮,權衡利弊,只好放棄這個想法。


劉邦問韓信:你看大哥我能帶多少兵?
韓信:十萬吧。
劉邦:那你呢?
韓信:多多益善。
劉邦:為啥我帶不了這麼多兵?
葛優:人心散了,隊伍不好帶啊。

一個公司規模越小,就越靈活,也可以對自己的產品越精益求精。當人數到了一定規模,讓所有人都走在同一個頻率上就是不可能的了。

小兵甲:小兵乙你看,為什麼隔壁那個小兵丙這一招海底撈月用得和夜叉探海似的,還沒被開除?
小兵乙:黑貓白貓,能抓耗子就是好貓。
小兵甲:為什麼不讓全公司的人都練好這招海底撈月?
小兵丙:老子這就是夜叉探海。

公司每個人的技能樹都是不一樣的,既然大家都是螺絲釘,就不可能要求誰做的工作都是完美的,更沒法要求所有人寫的代碼都是一致的。之所以要把程序「模塊化」,就是要盡量讓所有人可以同時工作,只滿足介面需求,而不過多關注實現。否則吵架就吵死了。

小兵丁:咱們現在老大是誰?
小兵戊:吳惟忠。
小兵丁:那為什麼咱們還叫戚家軍?
小兵戊:因為咱們之前老大叫戚繼光。
小兵丁:可是現在咱們老大不是戚繼光了。
小兵戊:咱們之前叫戚家軍的時候老打勝仗,改了名字不一定能打贏了。
小兵丁:可是我們要與時俱進啊,既然現在老大是吳惟忠,就應該改名叫吳家軍,或者戚吳家軍。
小兵戊:改完名打輸了你負責?
小兵丁:……

凡是有一定年頭的公司,code base里一定會有一些比較古舊的,運行時間比較長的代碼。經過了長時間的測試和使用,這些代碼已經比較穩定了,雖然他們可能沒用最新的架構,最新的技術,但是他們是確定能用的。代碼重構是個費力不討好的事情,首先要考慮兼容性,其次要重新做大量測試,世界上最沮喪的事情莫過於原來好用的東西,更新版本之後不好用了,想必大家都有過這種砸電腦的衝動。

百夫長甲:大帥,我們軍營里用的黑色外套,在雪天不易隱藏,我建議把全軍的外套改成白色!
高大帥:你出錢么?
百夫長甲:政府有軍資!
高大帥:吃飯還是換衣服?

有些事情確實是不正確的,你可能觀察的很對,但是不意味著這些你觀察到的錯誤是需要被立刻修改的。對公司code base的修改會使用大量的人力,也就是財力。而這個錯誤的修復對於公司來說是非常虧本的。

百夫長甲:世界上有的事就是錯的。
高大帥:這個錯誤會引起多大的後果?
百夫長甲:導致我們在雪天更容易被發現!
高大帥:可是我們是海南駐軍。

還有些事情雖然看似可能是不對的,不過可能壓根不影響公司的運營,換句話說他現在工作的很好,效率和正確性都不需要提高,即使理論上他是不完善的。公司的核心發展方向不應該僅僅糾結於讓現有代碼盡量整潔、美觀、正確。

太監甲:皇上,李自成又打過來啦!
崇禎:關寧鐵騎呢?
太監甲:還在和女真人糾纏。
崇禎:袁崇煥呢?
太監甲:大哥,早被您殺啦!
崇禎:吳三桂呢?
太監甲:目測等李自成打進來之後就要放清軍入關了!
崇禎:快把我女兒叫來,我要砍她胳膊

有時候公司是真的不行了,這時候趕緊收拾行李跑路吧。


我覺得主要問題是,如果你想要解決這個問題,就必須得要求程序員有非常強的架構能力,然後他才能在寫之前做出規劃,留出足夠更改的空間來避免這種補丁式的修改

但有這種能力的人基本都有能力去做arch,然後那邊給錢顯然更多,工作職責也更有趣……

我們單位還好,有個principal engineer專門負責代碼質量,而且時不時給大家講SOLID和相關的設計方法等等,並且他有權讓寫的不合適的代碼打回去重寫

國內可能還沒搞出這種東西來吧……要不然就是老總沒意識到這件事帶來的效益


很正常,首先,大公司都是從小公司發展起來的。
其次,大部分情況下,代碼質量跟盈利無關。
剛開始大家只是做個東西湊合用,後來的人也不管那麼多,只是隨便加點功能上去。越加越多。到最後要麼是整個系統慢慢越來越龐大。誰也搞不定。終於出了問題,推倒重來。
有的也是中間出了某個有魄力的老大,進行了梳理。
題主遇到的就是這個公司歷任老大都比較重視業務。不重視穩健性罷了。


張口閉口說的是重構的心,
開機關機乾的是作踐代碼的事。

有幾人真正做到了代碼質量和功能並存?


題主你好,我是一名菜鳥。我也經常和題主一樣抱怨公司代碼爛,經常和朋友吐槽項目架構垃圾。題主的境況我感同身受。
首先,我認為作為一名新手,或者說團隊的新成員,對代碼抱怨是可以理解。代碼不是我寫的,而且我的水平又不高,讓我這個水平不高的人去理解那一堆天書,簡直是要了命了。所以,吐槽兩句怎麼了!別人拉了一泡屎,我罵兩句街怎麼了!
其次,想依仗一己之力改變現狀太難了。打開項目工程,隨便翻了一下,發現到處都是不舒服的代碼。但是這個時候如果領導真的讓你動刀,去解決你認為不爽的地方,你肯定就傻眼了。這種任務,根本就不是一個人能搞的定的,需要全員配合,需要領導支持。這是一個漫長的過程,這麼大工程,出了問題,誰來負責?
我感覺我能做的就是,把我認為不好的地方找出來,然後看看有沒有好的替代方案。最後拿給同事和領導,說我們可以如此這般……,大家都覺的沒問題了,你就成功了一小步。如果大家對你的方案提出質疑,請耐心聽取他們的意見。如果他們只是一味的怕麻煩,認為不出問題能運行就行了。那麼題主你可以考慮換個環境。工作嗎,混口飯吃而已,不爽了就換一個唄。
最後我想說的是:我捍衛題主表達自己不滿的方式,認同題主在技術方面的追求。垃圾的架構就是垃圾,不好的代碼就是不好,沒什麼好解釋的,雖然它還能運行。看到別人拉了一泡屎,罵個街當然可以,不然滿大街都是拉屎的怎麼辦,這可是我受不了的。如果能一邊罵街一邊把屎打掃了,那就更好了。清理不完也不要緊,能清理一點是一點。千萬別看到別人拉了屎,罵完街自己又拉了一泡。
最好的方式,還是別罵街。畢竟罵街不文明……


為什麼有一種我們公司的既視感,但後來想像應該不是,我們這邊不用mysql,也不用svn。

來到這個公司兩年了,爛代碼見的越來越多,新的功能完全就是網上堆代碼了。為什麼不敢換新技術呢?因為底層數據結構都用了10年了,誰也不敢換架構,而且現在連重構一次的時間都沒有。嗯,大公司有的時候也有大公司的無奈,但是題主還是走吧,我也要走了


樓主看到的現象是:「大家普遍不寫注釋,幾乎沒有文檔,全靠從代碼反推邏輯。」,事實真相可能是「代碼就是最好的注釋」。

樓主看到的現象是:「代碼也不格式化」,事實真相可能是「一旦格式化就破壞了追蹤代碼修改歷史的鏈條」。

樓主看到的現象是:「程序員每天都在看郵件,查問題工單」,事實真相可能是「通過郵件和問題工單驅動的協同開發模式可能是現階段公司最有效率的工作模式」。

樓主看到的現象是:「問題多半是設計不當照成的」,事實真相可能是「問題多半是設計不當的項目組實際上遠好於設計良好被編碼成渣渣的項目組」。

樓主看到的現象是:「idea和配置文件竟然全部傳到項目里去了」,事實真相可能是「其實項目組的人都希望看到這些 idea 和統一的配置文件,Github 上一個優秀的 VIM 配置文件,下面就有幾千顆小星星」。

樓主看到的現象是:「一個沒什麼qps的邊緣介面,居然做消費者生產者+阻塞隊列的非同步模式」,事實真相可能是「當今業界很多經典的框架,都是使用消費者生產者+非阻塞隊列的非同步模式」,當然樓主只是少寫了一個「非」字。

存在的東西一定有它的合理性,否則它就沒有存在的必要了。樓主看到的種種現象,現象背後的原因,樓主可能並不了解,而如果樓主能夠了解現象背後的背景和由來,可能對現象本身會有完全不同的看法。樓主實習的互聯網公司,作為國內的行業龍頭,技術上一定有許多獨到和先進之處,如果像樓主說得「技術暴弱」了,那應該早死在沙灘上才對呀。所以樓主認為的「技術暴弱」,並不是事實上的「技術暴弱」,只是樓主的偏見罷了。

當然每個大公司或多或少都有自己的積弊,這是每個在歲月的磨礪中從小公司成長起來的大公司都需要面對的。處理的好,基業長青,再創輝煌;處理的不好,慢慢被創新的小公司趕上和超越。所以大公司需要不斷的流程優化和技術創新,才有可能延緩創新者窘境的到來。同樣,個人也需要不斷的自省和提升,才能在垂暮之年前創造屬於自己獨特的價值,而不是簡單給公司扣上一個「差勁」的帽子後,安然地在現狀上繼續徘徊,共勉!


我們Office組也有一部分這樣的問題。但是想想我們有一萬人,開發了30年,問題居然還比題主的輕好多,就覺得我們實在太厲害了。

這種問題是沒法解決的,因為不賺錢,不賺錢你去做了,而且還做出了翔,把程序搞掛了,在你上面三層的老大就不知道要怎麼跟CEO解釋。

但是通常來說,因為微軟還是很鼓勵代碼要跟上時代的發展的。如果這件事情你去做了,雖然不賺錢,但是沒有做出翔,而且跑起來還更快了,你的前途就一片光明了。


題主是一位善於觀察的有心人,贊!

發現樓里很少有人是從軟體工程的角度來分析的,有的明顯扯得太遠、太長、偏題了,真是遺憾。

題主提到這些問題和現象其實沒什麼可奇怪的,無非是糟糕的軟體工程管理所導致的一些 Bad Smells(涉及團隊的開發流程、開發規範,系統架構設計,個人的開發技能等方面),以及中式軟體工程江湖上幾十年來的「糙快猛」開發文化在互聯網大公司的延續而已,多數過來人 70 後、85 前碼農對這些傳統陋習早已是習以為常、司空見慣的吧。

理論分析

為什麼大型互聯網公司,技術和管理這麼差勁,是怎麼形成的?

一個不可否認的事實是,並非所有一流大公司的所有軟體研發部門都這麼差。

大公司的一些項目團隊技術差、管理差的現象在江湖上並不少見,尤其在軟體工程基礎和意識多年來都很薄弱的中式江湖就更不奇怪了。即便是一流企業,通常也會有一些表現差的二(三)流團隊和部門。按照通常的邏輯,我不相信這些現象會出現在一流龍頭企業的核心產品研發部門,所以最大可能這些是題主在一個二三流、非核心、管理較差的研發部門實習過程中看到的情況。

造成一個團隊或部門技術差的原因其實也很明確:

主要是因為管理水平(如工程管理、技術管理、研發管理、項目管理、質量管理等等)差造成的。所以,板子應該打在相應的領導、管理者(如架構師、項目經理、研發經理、技術主管等)身上,而基層的碼農可以說基本無責。碼農的表現差,那也是因為領導把他們招進來,培養、培訓、管理、帶出來的。所以,團隊技術差的主因通常是因為技術領導、技術帶頭人(架構師)的水平差

還有一些其他相對次要的原因,例如,公司發展太快,招人太多(大部分是低技能的編程新手),一時技術管理更不上,領導顧不過來,等等。

那麼,為什麼「糙快猛」開發模式無論對於中式江湖、美式江湖都是有效的?

西方的軟體工程專家們對此有個很好的比喻和解釋:Design Debts(設計債)。題主所列舉的這些問題和想像無非是軟體工程中一些常見的設計債、技術債或管理債(Management Debts)。用負債來打比方是很貼切的。

首先,不要忘了,我們開發軟體的目的是為了什麼?純粹為了技術而搞技術?這種想法太嫩,太天真。IT/軟體/互聯網企業的第一要務無疑是贏利、賺錢,有了充足的現金流企業才能生存、持續發展,所以經濟面的考慮、搞經濟必然是第一位的(Money First),搞政治(讓公司權力掌握在誰手裡)排第二(或第一位)。

可是公司賺錢一定要有很好的技術,很好的管理嗎?不一定啊,你看江湖上不是還有很多二三流企業活得很好很滋潤么。把東西、服務賣出去,首先靠的是銷售(Sales)、營銷(Marketing)、關係(Guan Xi)等等那些最重要的手段。必要的時候還可以來點忽悠,不要小看了忽悠,幾千年來人類社會的實踐充分證明忽悠也是生產力,高水平的忽悠更是一門藝術。而技術差點、代碼亂點,只要不捅大簍子,問題其實不大的,只要產品能買得出去,系統還能運行,公司還有源源不斷的現金流,還能掌控足夠的市場份額,有什麼必要勞師動眾、勞民傷財來改進管理、改進技術,讓現任領導們難堪么?產品和代碼質量差不多、馬馬虎虎就可以了嘛,怎麼算這都是一筆划算的經濟帳、政治帳。所以,像改善軟體工程管理、提高代碼質量、提升員工技能水平等等這些科技、技術方面的考慮因素頂多排在許多領導優先考慮的第三位。

當然,技術差、代碼質量差、架構設計差、項目管理差等等這些日常開發中的諸多缺點、問題和不合理現象是以一種負債的形式欠下了,而且債務還再不斷地累積,這有影響嗎?不要忘了,欠債總是要還的。為什麼這些差勁的現象不嚴重,還可以持續,領導們也不重視?因為:從量變到質變,還沒有到發生質變的臨界點(還債)的時刻。問題來了,什麼時候還債呢?

以上,我從軟體工程學、公司政治經濟學、管理學的角度對為什麼中國軟體業的一些一流大公司也會存在一些軟體工程技術差、管理差的團隊和部門作出了解釋。不服可以來辯。


以下對題主所列舉的一些 Bad Smells 進行簡短分析。

架構師水平差

一個項目里,httpclient竟然出現了四種。
一種是該公司研發部寫的,
一種是老版本的開源項目,
一種是新版本的開源項目,
還有一種是開發人員造的輪子。

一個項目里採用的同一個功能構件竟然同時出現 4 個來源不同的版本應該說是反常的,也許在一個大公司的幾個不同部門、產品線之間出現這種現象還能容忍。這個項目組的架構師去哪裡了?難道就不能做點深入的技術調研,盡量作出一個統一的選擇?當然,也許這個項目組正在同時對這 4 個 httpclient 進行比較實驗。排除這種情況,感覺這個項目的技術管理是失控的,或者是因為這個項目的架構師歲水平不行,無法服眾。

打介面請求響應日誌,竟然不知道用攔截器。
打錯誤日誌竟然不打上下文信息,每個人一種日誌風格,千奇百怪。
許多重要的中間流程,居然不打日誌。

同上,我還是覺得這個項目的架構師水平不行,沒人懂 Logger 的價值,自然不會有人來作出規範。

所有服務間通訊,都沒有設requestId,導致跟蹤會話很困難。

同樣是架構設計的問題,requestId 這應該很容易想到吧。

幾乎沒有文檔,全靠從代碼反推邏輯。

這個項目組的架構師會寫文檔,有時間寫文檔嗎?

程序員們都是得過且過的態度,怎麼把代碼灌進去,跑的通測試,就算交差了。

一個項目組、團隊沒有一個靠譜的技術帶頭人,結局必然是這樣的。

碼農技能差

為啥一個項目組的碼農技能差,代碼慘不忍睹?因為大公司圖便宜和高性價比,招了大量的嫩手,卻又不給有效的在崗培訓。

開發自測,居然要把代碼全丟到公共機器上,而且都是走svn,他們把svn當ftp用。
svn裡面大量的無意義提交,一多半的提交連都編譯不過去。
我看到有個應屆生,改了兩句話,馬上提交,說是怕代碼丟失。

難道是半拉子的 CI?

可怕的是這個團隊沒有一個嚴格的開發流程規範,怎麼提交代碼,怎麼集成,怎麼測試。。。基本採取放羊式管理,責任還在架構師。也有可能是新員工培訓的問題。

有枚舉他不用,非要在每個頁面上,把枚舉值挨個兒寫死,知道後面改代碼多麼費勁嗎?

江湖俗稱 Hard Coded。可見大公司招了許多嫩手。

代碼寫的一團糟,全是複製粘貼,連作者都沒改,大家普遍不寫注釋,也不格式化,代碼歪歪扭扭。

欺騙性的變數名,裡面存儲的是AES加密的,變數名後綴卻寫成了DES;裡面存的是小寫字母,卻寫成upperStr。
一個方法十幾個參數,有三分之一是極其簡略的縮寫,注釋肯定也沒有的。
一個類寫到三四千行是常事。

估計這個項目組是不可能有代碼規範的,也沒有 Code Review(包括工具),當然也可能規範神馬的都有,就是無法有效執行。


多值不用PG(或者其他文檔型資料庫)也不單獨創建一個表來存,用逗號分隔,如果總是獲取整個列表倒也罷了,遇到有單項查詢的時候就死定了。。。
這一條太有體會,必須來吐一下。這也算是資料庫應用中的一個pain point吧,也是很多應用選擇關係型和mongoDB這類文檔型資料庫的考慮點之一。不過postgreSQL似乎解決的不錯。

另外check in 項目配置文件這個真不能忍。。。


關鍵是大字,我按照老闆的意思做過不只一份全面改進換代計劃,直到老闆跳槽都沒辦法跟所有人達成一致,搞技術容易,搞人難


現在在做某通信運營商的收發工單告警代維派單系統。每周迭代一次,公司框架用的代碼跟樓主的說的一樣,贊同萌萌姐的回答。恩,就是求個分@陳萌萌我問總監咱們都明碼傳輸么?總監說,你去和客戶談報價。
以上。


推薦閱讀:

TAG:互聯網 | 程序員 | 軟體架構 | 軟體工程 |