
編程是枯燥的,除非……
作為一個(gè)開(kāi)發(fā)者,我干同一份工作的時(shí)間不會(huì)超過(guò)兩年。
每一份新工作都是一次職業(yè)的飛躍,而且在我們這個(gè)行業(yè)中,高頻跳槽本來(lái)就很常見(jiàn)。但是我前任,前前任,前前前任,前前前…任雇主對(duì)于我的辭職并不開(kāi)心。有些甚至試圖挽留我,但是我已經(jīng)厭倦了,我真心無(wú)法繼續(xù)留下來(lái)了。
(免責(zé)聲明:我很幸運(yùn)地生活在程序員供不應(yīng)求的地方,不過(guò)后來(lái)我發(fā)現(xiàn)換工作并不總是一個(gè)很好的選擇!)。
我現(xiàn)在是Enki的聯(lián)合創(chuàng)始人和CTO。我負(fù)責(zé)工程文化。我的部分工作是要確保我們的開(kāi)發(fā)人員永遠(yuǎn)不會(huì)像我過(guò)去那樣覺(jué)得工作無(wú)聊枯燥。
在我的團(tuán)隊(duì)的共同努力下,我們制定了防止程序員感到無(wú)聊枯燥的策略,并應(yīng)用到公司里。由于這一策略到目前為止一直運(yùn)作良好,所以在這里我想和大家一起分享。
在Enki公司,我們可以放肆地沖鋒具有挑戰(zhàn)性的問(wèn)題。為很多有趣的事情寫(xiě)代碼,解決大量有趣的謎題。因此,“無(wú)聊”并不是一個(gè)迫切的問(wèn)題。甚至剛開(kāi)始的時(shí)候,你完全找不到它的蹤跡。但是,隨著時(shí)間的流逝,無(wú)聊會(huì)像藤蔓一樣漸漸爬滿大樹(shù),然后在最糟糕的時(shí)刻擊垮你。
這就是為什么我們要建立一種拯救無(wú)聊的文化來(lái)盡早解決這個(gè)問(wèn)題的原因。
時(shí)間太長(zhǎng);學(xué)不到東西
開(kāi)發(fā)人員感到無(wú)聊枯燥最常見(jiàn)和最明顯的原因是,項(xiàng)目的持續(xù)時(shí)間過(guò)長(zhǎng)。
我在我第一份工作中就親身經(jīng)歷了這種體驗(yàn)。我們團(tuán)隊(duì)的任務(wù)是通過(guò)一個(gè)便捷API來(lái)準(zhǔn)備和提供財(cái)務(wù)數(shù)據(jù)。一開(kāi)始因?yàn)閿?shù)據(jù)的復(fù)雜性和規(guī)模,令我非常興奮。同時(shí)我從中也學(xué)會(huì)了如何高性能地分析數(shù)據(jù)和API設(shè)計(jì)。但是一年以后,我們依然工作于完全相同的數(shù)據(jù)集,用著完全相同的技術(shù)。我只是成為了某個(gè)特定方面的“專(zhuān)才”,也沒(méi)有什么可以學(xué)習(xí)的新內(nèi)容。
我無(wú)法改變團(tuán)隊(duì)或項(xiàng)目,因?yàn)閷?duì)于公司而言,這種重復(fù)性的枯燥的任務(wù)是有意義的。并且由于我熟知數(shù)據(jù)和技術(shù)而無(wú)法換到其他崗位。我沒(méi)有理由只是為了學(xué)習(xí)新的東西而去更換現(xiàn)有的技術(shù)。在我表明了我的枯燥和沮喪之后,因?yàn)閱?wèn)題依然沒(méi)有解決,所以我選擇了跳槽。
在我們的團(tuán)隊(duì)中,我們嘗試著不讓任何人從事相同的代碼、產(chǎn)品和數(shù)據(jù)集超過(guò)三個(gè)月。三個(gè)月的時(shí)間是我們?nèi)我舛ǖ?,或許對(duì)于規(guī)模較大的公司而言,顯得太短了點(diǎn)。但是我們主張快速轉(zhuǎn)換。
為了做到這一點(diǎn),我們提出了一個(gè)全棧文化。我們每一個(gè)開(kāi)發(fā)人員都能夠工作于(或者可以很快學(xué)會(huì))代碼庫(kù)的任何部分。
另一個(gè)預(yù)防枯燥的方法是經(jīng)常性地討論。我們每個(gè)星期都有直接、開(kāi)放、一對(duì)一的討論。如果開(kāi)發(fā)人員開(kāi)始覺(jué)得過(guò)于舒服或已經(jīng)熟能生巧了,那么就到了轉(zhuǎn)換工作的時(shí)候。
維護(hù)遺留代碼很無(wú)聊
當(dāng)項(xiàng)目處于維護(hù)模式,即開(kāi)發(fā)人員90%的時(shí)間都花在了修復(fù)bug,而不是開(kāi)發(fā)新功能的時(shí)候,你可以報(bào)告給我們——正式或非正式的方式都可。
有人會(huì)說(shuō),維護(hù)是不可避免的。舊代碼需要支持。建造軟件就像蓋房子。你需要維護(hù)的老房子,并時(shí)常翻新。是這樣的嗎?
是的,但又不是。問(wèn)題的關(guān)鍵是態(tài)度。
我曾經(jīng)有一個(gè)導(dǎo)師,他對(duì)此抱著一種玩世不恭的心態(tài)。他將無(wú)為當(dāng)作理所當(dāng)然。他總是說(shuō),軟件開(kāi)發(fā)工作就是這樣的;假如生活強(qiáng)奸了你,那就躺著享受吧。
維護(hù)模式有時(shí)是糟糕的技術(shù)決策加之缺乏勇氣才導(dǎo)致的結(jié)果。
大型,整體式的,依賴(lài)關(guān)系復(fù)雜的代碼庫(kù)往往需要額外的維護(hù)工作。與此相反的是,架構(gòu)良好的微服務(wù)基礎(chǔ)結(jié)構(gòu)就顯得較為靈活。當(dāng)微服務(wù)出現(xiàn)故障的時(shí)候,你可以更換它。你可以使用不同的語(yǔ)言或技術(shù)從頭開(kāi)始重寫(xiě)。這樣你就可以學(xué)到新的東西,而不是簡(jiǎn)單地修補(bǔ)舊的代碼。如果你的架構(gòu)還不允許這么做,那么你需要采取步驟來(lái)改進(jìn)它,并在此過(guò)程中學(xué)習(xí)一些開(kāi)發(fā)技能。
微服務(wù)策略只是解決“枯燥”維護(hù)問(wèn)題的方法中的一個(gè)。還有一個(gè)措施是構(gòu)建智能工具,使維護(hù)變得更加高效和樂(lè)趣。這方面的一個(gè)極端例子就是,F(xiàn)acebook對(duì)他們那個(gè)龐大的PHP代碼庫(kù)做的事情。他們?cè)谑炀氄莆誔HP的基礎(chǔ)上構(gòu)建了自己的編譯器和自己的類(lèi)型語(yǔ)言(Hack),既方便維護(hù),又提高了開(kāi)發(fā)體驗(yàn)。雖然我懷疑Facebook依然沒(méi)有完全“解決”遺留問(wèn)題,但聽(tīng)上去它讓工作變得更有趣了。
復(fù)制/粘貼很無(wú)聊
還有就是編碼,編碼,還是編碼。
在我以前的一些工作中,我寫(xiě)了很多收效甚微的代碼。例如,我曾為了數(shù)據(jù)整合寫(xiě)過(guò)Groovy和Python腳本。數(shù)據(jù)很復(fù)雜,有許多不一致的模式,這使得大多數(shù)地方無(wú)法做到自動(dòng)化。因此,我不得不寫(xiě)大量的代碼,而我的同事因此認(rèn)為我學(xué)到了很多東西。
但其實(shí)我并沒(méi)有學(xué)到很多。為什么?
因?yàn)?0%(沒(méi)有計(jì)算過(guò),純粹是夸張手法!)的代碼是從Stack Overflow直接復(fù)制/粘貼來(lái)的。還有40%則復(fù)制/粘貼自其他腳本。無(wú)論是我同事的腳本,還是我的,都是如此。很多很多代碼都是重復(fù)性的。很少涉及創(chuàng)造和學(xué)習(xí)。
那么對(duì)此我們又是怎么做的呢?
作為一個(gè)團(tuán)隊(duì),我們要關(guān)注其他人寫(xiě)的代碼類(lèi)型。我們會(huì)審查,同步和回顧代碼。如果發(fā)現(xiàn)有人一個(gè)星期都沒(méi)有生產(chǎn)創(chuàng)造性的代碼,那我們就會(huì)去查看原因。
有時(shí),問(wèn)題的根源在于技術(shù)。我們可能比我們應(yīng)該的做了更多的腳本和配置工作。在這種情況下,我們會(huì)增加自動(dòng)化。不過(guò),很多時(shí)候,是因?yàn)槲覀兓谀撤N原因做了太多的復(fù)制/粘貼工作。在這種情況下,我們會(huì)共同承擔(dān)這個(gè)枯燥的工作以便于盡快完成。
內(nèi)部工具通常很沒(méi)意思
作為開(kāi)發(fā)人員,我們希望創(chuàng)建定制的內(nèi)部工具來(lái)解決具體問(wèn)題,因?yàn)閯?chuàng)造新事物總是令人興奮不已。此外,打造定制的解決方案常常比重復(fù)利用現(xiàn)有的解決方案更清潔。但學(xué)習(xí)專(zhuān)有工具要比學(xué)習(xí)流行的開(kāi)源技術(shù)無(wú)趣多了。
為什么?
因?yàn)槟悴荒芨愕呐笥呀涣鲗?zhuān)有工具;它成不了你吹噓的資本;你不能在Hacker News上看到它的身影;你不能在編程馬拉松中使用它;它在你秘密的業(yè)余項(xiàng)目中也毫無(wú)用武之地。
但是,很多企業(yè)陷入創(chuàng)造的陷阱——他們所創(chuàng)造的東西反而會(huì)帶來(lái)更多的煩惱。換句話說(shuō):他們解決了一個(gè)短期的挫折,從長(zhǎng)期來(lái)看卻會(huì)導(dǎo)致更多的挫折。
我對(duì)此深有體會(huì)。在我曾經(jīng)的一份工作中,對(duì)于大規(guī)模數(shù)據(jù)集成,我被約束必須使用公司制造的DSL。在我看來(lái),它就是另一種類(lèi)似于SQL的術(shù)語(yǔ)(夸張手法)。我更喜歡使用和學(xué)習(xí)低級(jí)的開(kāi)放式技術(shù),例如Spark。如果沒(méi)有這種限制的話,我的效率能高5倍都不止(請(qǐng)不要糾結(jié)這個(gè)數(shù)字,領(lǐng)會(huì)精神?。?。
什么樣的文化可以預(yù)防這種情況呢?
我們應(yīng)該盡量偏向于開(kāi)源技術(shù)。勇于面對(duì)最前沿的技術(shù)。毫不留情地拋棄自定義代碼,只要有開(kāi)源技術(shù)成熟到足以取代這些自定義代碼。而當(dāng)我們自己編寫(xiě)的代碼變得夠格通用的時(shí)候,開(kāi)放源碼。
偶爾我們也會(huì)犯錯(cuò)。例如,曾經(jīng)有一段時(shí)間我們使用agenda.js庫(kù)來(lái)安排我們的后端工作,因?yàn)樗瓷先ゼ痊F(xiàn)代化又鼓舞人心。但是最后,它反而讓事情變復(fù)雜了,所以我們只能回頭用一個(gè)舊的更可靠的技術(shù)(略顯古老的cron?。1M管如此,我們也沒(méi)有后悔用它試驗(yàn),因?yàn)檫@是一個(gè)寶貴的學(xué)習(xí)經(jīng)驗(yàn)。
做一只程序猿很無(wú)聊
令開(kāi)發(fā)者無(wú)聊的另一個(gè)常見(jiàn)原因是糟糕的人力管理。更具體地講是從上而下,獨(dú)裁地管理開(kāi)發(fā)人員。
自認(rèn)為目標(biāo)遠(yuǎn)大的主管有時(shí)候會(huì)使用這種管理風(fēng)格而不自知。特別是當(dāng)一個(gè)項(xiàng)目不會(huì)進(jìn)展良好,或截止期限將至的時(shí)候。在壓力的作用下,獨(dú)裁統(tǒng)治會(huì)成為一種自然反射——討論時(shí)“一言堂”,不接受集思廣益,沒(méi)有經(jīng)過(guò)辯證和解釋就直接告訴大家去做什么。目的就是為了節(jié)省時(shí)間,盡快完成工作。
不過(guò)很多被管理的員工也不一定會(huì)生氣:事實(shí)上,有些人還很享受直接被告知要做什么。當(dāng)然,告知的方式得合適。
不過(guò),這里還有一個(gè)隱藏成本。
你在開(kāi)發(fā)人員寫(xiě)代碼之前就準(zhǔn)確告知了他們?cè)撊绾尉幋a,將這個(gè)智力和創(chuàng)造性的過(guò)程變成了一個(gè)機(jī)械的過(guò)程:換句話說(shuō),就是將開(kāi)發(fā)人員訓(xùn)練成了程序猿。
除非是黑客在攻克邊界情況,或是,程序需要做一個(gè)臨時(shí)補(bǔ)丁,否則參與的開(kāi)發(fā)人員總是希望能了解“為什么”他們要采取這種做事方式而不是另一種。當(dāng)一個(gè)開(kāi)發(fā)人員不再關(guān)心重大決策以及決策背后的原因的時(shí)候,也是他準(zhǔn)備換工作的時(shí)候。
如何避免這種情況?
鼓勵(lì)公開(kāi)討論的文化。一個(gè)用于討論,制定戰(zhàn)略和計(jì)劃的定期論壇是一個(gè)團(tuán)隊(duì)所必須的。為了保持這樣的文化,每個(gè)團(tuán)隊(duì)成員都應(yīng)該保持警惕。
特別是當(dāng)舉步維艱的時(shí)期(或最后期限正在逼近的時(shí)候),學(xué)生需要說(shuō)出他們的心聲,而導(dǎo)師需要仔細(xì)聆聽(tīng)。
做一天和尚撞一天鐘很無(wú)聊
最后但并非最不重要的一個(gè)原因:一個(gè)封閉的環(huán)境中會(huì)成為樂(lè)趣的絕對(duì)殺手。
這在開(kāi)發(fā)領(lǐng)域或高科技產(chǎn)業(yè)并不罕見(jiàn)。也適用于幾乎任何辦公室工作。每天都在同一間辦公室,面對(duì)同樣的人,沐浴同樣的文化,做同樣的工作……即使是在一個(gè)高速發(fā)展的環(huán)境下,即使所有情況客觀都是“好”的,大家也會(huì)對(duì)這些好的地方習(xí)以為常,然后開(kāi)始對(duì)那些不那么好的部分悶悶不樂(lè)耿耿于懷。
那么我們?cè)撛趺磻?zhàn)勝它呢?
關(guān)鍵因素是多樣性:雇用不同背景和不同來(lái)源的人(例如目前我們團(tuán)隊(duì)的6個(gè)人就來(lái)自于英國(guó),法國(guó),俄羅斯和希臘4個(gè)不同國(guó)家)。如果團(tuán)隊(duì)中的每一個(gè)人都能會(huì)我們的文化帶來(lái)新鮮要素,那么即使每天面對(duì)同樣的人也會(huì)變得有趣,也會(huì)變得不那么難以忍受。
同時(shí),我們努力創(chuàng)造走出去的機(jī)會(huì)。
比如,我們會(huì)去公共場(chǎng)合聚會(huì),會(huì)一起去參加編程馬拉松。我們都有自己業(yè)余項(xiàng)目,并致力于最喜歡的開(kāi)源工具。我們甚至?xí)r不時(shí)地會(huì)幫助其他團(tuán)隊(duì)承擔(dān)技術(shù)含量不那么高的工作(如招聘,營(yíng)銷(xiāo),分銷(xiāo)…)。不是因?yàn)槲覀兩瞄L(zhǎng)這些,而是為了能有一個(gè)變化。
我們還組織團(tuán)隊(duì)搞活動(dòng)(例如Secret Cinema),每周舉辦一次不預(yù)定日程的“enkithon”活動(dòng)。有時(shí)候,我們會(huì)一起過(guò)把黑客的癮。有時(shí)候,我們會(huì)頭腦風(fēng)暴一個(gè)新點(diǎn)子。有時(shí)候,我們會(huì)沉溺于玩英雄聯(lián)盟。甚至我們還一起去泡吧。不到最后一秒我們自己也不知道要去做什么,直到我們共同決定。
我們對(duì)抗無(wú)聊和枯燥的方法或許還不成熟,還有點(diǎn)混亂。但就像食譜一樣,每一份食譜都不能自稱(chēng)是絕對(duì)完美的。調(diào)整用量,更換配料,反復(fù)練習(xí)才能精益求精。
數(shù)據(jù)分析咨詢(xún)請(qǐng)掃描二維碼
若不方便掃碼,搜微信號(hào):CDAshujufenxi
SQL Server 中 CONVERT 函數(shù)的日期轉(zhuǎn)換:從基礎(chǔ)用法到實(shí)戰(zhàn)優(yōu)化 在 SQL Server 的數(shù)據(jù)處理中,日期格式轉(zhuǎn)換是高頻需求 —— 無(wú)論 ...
2025-09-18MySQL 大表拆分與關(guān)聯(lián)查詢(xún)效率:打破 “拆分必慢” 的認(rèn)知誤區(qū) 在 MySQL 數(shù)據(jù)庫(kù)管理中,“大表” 始終是性能優(yōu)化繞不開(kāi)的話題。 ...
2025-09-18CDA 數(shù)據(jù)分析師:表結(jié)構(gòu)數(shù)據(jù) “獲取 - 加工 - 使用” 全流程的賦能者 表結(jié)構(gòu)數(shù)據(jù)(如數(shù)據(jù)庫(kù)表、Excel 表、CSV 文件)是企業(yè)數(shù)字 ...
2025-09-18DSGE 模型中的 Et:理性預(yù)期算子的內(nèi)涵、作用與應(yīng)用解析 動(dòng)態(tài)隨機(jī)一般均衡(Dynamic Stochastic General Equilibrium, DSGE)模 ...
2025-09-17Python 提取 TIF 中地名的完整指南 一、先明確:TIF 中的地名有哪兩種存在形式? 在開(kāi)始提取前,需先判斷 TIF 文件的類(lèi)型 —— ...
2025-09-17CDA 數(shù)據(jù)分析師:解鎖表結(jié)構(gòu)數(shù)據(jù)特征價(jià)值的專(zhuān)業(yè)核心 表結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 規(guī)范存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如數(shù)據(jù)庫(kù)表、Excel 表、 ...
2025-09-17Excel 導(dǎo)入數(shù)據(jù)含缺失值?詳解 dropna 函數(shù)的功能與實(shí)戰(zhàn)應(yīng)用 在用 Python(如 pandas 庫(kù))處理 Excel 數(shù)據(jù)時(shí),“缺失值” 是高頻 ...
2025-09-16深入解析卡方檢驗(yàn)與 t 檢驗(yàn):差異、適用場(chǎng)景與實(shí)踐應(yīng)用 在數(shù)據(jù)分析與統(tǒng)計(jì)學(xué)領(lǐng)域,假設(shè)檢驗(yàn)是驗(yàn)證研究假設(shè)、判斷數(shù)據(jù)差異是否 “ ...
2025-09-16CDA 數(shù)據(jù)分析師:掌控表格結(jié)構(gòu)數(shù)據(jù)全功能周期的專(zhuān)業(yè)操盤(pán)手 表格結(jié)構(gòu)數(shù)據(jù)(以 “行 - 列” 存儲(chǔ)的結(jié)構(gòu)化數(shù)據(jù),如 Excel 表、數(shù)據(jù) ...
2025-09-16MySQL 執(zhí)行計(jì)劃中 rows 數(shù)量的準(zhǔn)確性解析:原理、影響因素與優(yōu)化 在 MySQL SQL 調(diào)優(yōu)中,EXPLAIN執(zhí)行計(jì)劃是核心工具,而其中的row ...
2025-09-15解析 Python 中 Response 對(duì)象的 text 與 content:區(qū)別、場(chǎng)景與實(shí)踐指南 在 Python 進(jìn)行 HTTP 網(wǎng)絡(luò)請(qǐng)求開(kāi)發(fā)時(shí)(如使用requests ...
2025-09-15CDA 數(shù)據(jù)分析師:激活表格結(jié)構(gòu)數(shù)據(jù)價(jià)值的核心操盤(pán)手 表格結(jié)構(gòu)數(shù)據(jù)(如 Excel 表格、數(shù)據(jù)庫(kù)表)是企業(yè)最基礎(chǔ)、最核心的數(shù)據(jù)形態(tài) ...
2025-09-15Python HTTP 請(qǐng)求工具對(duì)比:urllib.request 與 requests 的核心差異與選擇指南 在 Python 處理 HTTP 請(qǐng)求(如接口調(diào)用、數(shù)據(jù)爬取 ...
2025-09-12解決 pd.read_csv 讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)的科學(xué)計(jì)數(shù)法問(wèn)題 為幫助 Python 數(shù)據(jù)從業(yè)者解決pd.read_csv讀取長(zhǎng)浮點(diǎn)數(shù)據(jù)時(shí)的科學(xué)計(jì)數(shù)法問(wèn)題 ...
2025-09-12CDA 數(shù)據(jù)分析師:業(yè)務(wù)數(shù)據(jù)分析步驟的落地者與價(jià)值優(yōu)化者 業(yè)務(wù)數(shù)據(jù)分析是企業(yè)解決日常運(yùn)營(yíng)問(wèn)題、提升執(zhí)行效率的核心手段,其價(jià)值 ...
2025-09-12用 SQL 驗(yàn)證業(yè)務(wù)邏輯:從規(guī)則拆解到數(shù)據(jù)把關(guān)的實(shí)戰(zhàn)指南 在業(yè)務(wù)系統(tǒng)落地過(guò)程中,“業(yè)務(wù)邏輯” 是連接 “需求設(shè)計(jì)” 與 “用戶體驗(yàn) ...
2025-09-11塔吉特百貨孕婦營(yíng)銷(xiāo)案例:數(shù)據(jù)驅(qū)動(dòng)下的精準(zhǔn)零售革命與啟示 在零售行業(yè) “流量紅利見(jiàn)頂” 的當(dāng)下,精準(zhǔn)營(yíng)銷(xiāo)成為企業(yè)突圍的核心方 ...
2025-09-11CDA 數(shù)據(jù)分析師與戰(zhàn)略 / 業(yè)務(wù)數(shù)據(jù)分析:概念辨析與協(xié)同價(jià)值 在數(shù)據(jù)驅(qū)動(dòng)決策的體系中,“戰(zhàn)略數(shù)據(jù)分析”“業(yè)務(wù)數(shù)據(jù)分析” 是企業(yè) ...
2025-09-11Excel 數(shù)據(jù)聚類(lèi)分析:從操作實(shí)踐到業(yè)務(wù)價(jià)值挖掘 在數(shù)據(jù)分析場(chǎng)景中,聚類(lèi)分析作為 “無(wú)監(jiān)督分組” 的核心工具,能從雜亂數(shù)據(jù)中挖 ...
2025-09-10統(tǒng)計(jì)模型的核心目的:從數(shù)據(jù)解讀到?jīng)Q策支撐的價(jià)值導(dǎo)向 統(tǒng)計(jì)模型作為數(shù)據(jù)分析的核心工具,并非簡(jiǎn)單的 “公式堆砌”,而是圍繞特定 ...
2025-09-10