蜜桃二区,毒医王妃不好惹免费阅读全文,奶水奶头咂着奶小说,被快递员上门做到高潮,日本巨乳人妻无删减,情爱小说连载,暴躁妹妹csgo,床戏描写多的小说片段,给弟弟的家规

專業(yè)網(wǎng)站建設(shè)B/S軟件開發(fā)專業(yè)微信營銷專業(yè)技術(shù)建設(shè)團(tuán)隊(duì)做客戶滿意度最高的軟件公司
鄭州網(wǎng)站建設(shè)、鄭州網(wǎng)站開發(fā)
 

三十年軟件開發(fā)之路:老碼農(nóng)的自我修養(yǎng)!

作者:網(wǎng)站建設(shè)出處:學(xué)眾科技發(fā)布時(shí)間:2020年05月18日點(diǎn)擊數(shù):2502

“千帆過盡仍少年”,對(duì)于程序員來說,保留技術(shù)初心、不斷提升實(shí)力是夯實(shí)自己的不二法則。而本文的作者,作為一名有著三十多年開發(fā)經(jīng)驗(yàn)的“老”程序員,就在本文中詳細(xì)總結(jié)了自己這些年踩過的坑和實(shí)踐得出的真理,談到了包括軟件開發(fā)、團(tuán)隊(duì)工作、個(gè)人成長等方方面面。相信閱讀本文后,會(huì)幫助你成為更優(yōu)秀的程序員。

聲明:本文已獲作者 Julio Biason 翻譯授權(quán)。

譯者 | 王艷妮,責(zé)編 | 郭芮

以下為譯文:

這是我 30 年來從事軟件開發(fā)過程中所學(xué)到的一些實(shí)際經(jīng)驗(yàn),可能有些聽起來憤世嫉俗,但都是我的切身經(jīng)驗(yàn)之談。

再次強(qiáng)調(diào),有些內(nèi)容真的是憤世嫉俗,有些則是對(duì)不同工作崗位的長期觀察。

軟件開發(fā)

先明確問題,再開始寫代碼

如果你不知道你想要解決的問題是什么,那你肯定就不知道要寫些什么代碼。在編寫任何代碼之前,先明確地把應(yīng)用程序是如何工作的寫下來。

“如果沒有需求或設(shè)計(jì),編程就是向空文本文件不斷增加bug的藝術(shù)?!薄狶ouis Srygley

有時(shí),即使只是“電梯演講”(指短時(shí)間內(nèi)表述結(jié)果內(nèi)容)那么長——用僅僅兩個(gè)自然段來描述這個(gè)應(yīng)用程序的功能——也足夠了。

有時(shí)候我看著自己的代碼發(fā)呆,不知道下一步該怎么做,其實(shí)往往是因?yàn)橄乱徊奖緛砭瓦€沒有被定義出來。一般出現(xiàn)這種情況,就意味著是時(shí)候停下來,與同事們討論一下了——或者重新考慮解決方案。

將步驟寫為注釋

如果你不知道如何開始,請(qǐng)先用自然語言、英語或你的母語描述應(yīng)用程序的流程,然后用代碼填充注釋之間的空白。比這更好的做法是:將每個(gè)注釋視為一個(gè)函數(shù),然后編寫出能完全實(shí)現(xiàn)其功能的代碼。

Gherkin是幫助你了解期望(expectation)的好幫手

Gherkin是一種測(cè)試描述格式,它指出“鑒于系統(tǒng)處于特定狀態(tài),當(dāng)發(fā)生某些事情時(shí),這是預(yù)期的后果”。即使你不使用任何能讀取Gherkin的測(cè)試工具,它也會(huì)讓你很好地理解應(yīng)用程序的預(yù)期效果。

單元測(cè)試很好,集成測(cè)試更好

在我目前的工作中,我們只測(cè)試模塊和類(例如,我們只為視圖層編寫測(cè)試,然后僅測(cè)試操縱 器層,依此類推)。它能讓我們了解到某一部分有沒有出錯(cuò),但缺乏對(duì)整體的觀察——而集成測(cè)試測(cè)試了整個(gè)系統(tǒng)的行為,在這方面會(huì)表現(xiàn)得更好。

測(cè)試可以讓API更好

我們?cè)诓煌瑢哟沃芯幋a:有一個(gè)存儲(chǔ)層,應(yīng)該使我們的數(shù)據(jù)永久存儲(chǔ);有一個(gè)處理層,應(yīng)該對(duì)存儲(chǔ)的數(shù)據(jù)進(jìn)行一些轉(zhuǎn)換;有一個(gè)視圖層,它有關(guān)于數(shù)據(jù)必須如何被展示出來的信息......等等。

正如我所提到的,集成測(cè)試感覺更好,但是單獨(dú)測(cè)試不同層可以讓你更好地了解其API。然后你可以更好地了解如何調(diào)用東西:API是否太復(fù)雜了?是否需要保留大量數(shù)據(jù)才能進(jìn)行一次調(diào)用?

做你知道如何在命令行上運(yùn)行的測(cè)試

也不是說命令行對(duì)于任何項(xiàng)目都很重要,但是當(dāng)你知道運(yùn)行測(cè)試的命令時(shí),你就知道如何讓測(cè)試的執(zhí)行自動(dòng)化起來,然后你可以在一個(gè)連續(xù)的集成工具中使用這些測(cè)試。

時(shí)刻準(zhǔn)備好扔掉你的代碼

很多人在剛開始使用TDD(測(cè)試驅(qū)動(dòng)開發(fā),Test-Driven Development)時(shí),一旦被告知他們可能不得不重寫很多東西,就會(huì)變得很生氣。

TDD“旨在”扔掉代碼:越了解你的問題,那么你就會(huì)越明白,無論你寫了什么,從長遠(yuǎn)來看都無法解決問題。

所以你不應(yīng)該擔(dān)心這個(gè)。你的代碼不是一面墻:如果你必須永遠(yuǎn)拋棄它,那也不是白白浪費(fèi)了材料。當(dāng)然這意味著你編寫代碼的時(shí)間一去不復(fù)返了,但是你現(xiàn)在對(duì)這個(gè)問題有了更好的理解。

好的語言生來帶有綜合測(cè)試

可以肯定的是,如果一種語言在其標(biāo)準(zhǔn)庫中自帶一個(gè)測(cè)試框架——即使小得不能再小——那么與沒有測(cè)試框架的語言相比,它周圍的生態(tài)系統(tǒng)仍將擁有更好的測(cè)試,無論該語言的外部測(cè)試框架有多好。

未來思路是垃圾思路

當(dāng)開發(fā)人員試圖解決問題時(shí),他們有時(shí)會(huì)試圖找到一種方法來一下解決所有問題,包括未來可能出現(xiàn)的問題。

但現(xiàn)實(shí)就是這樣:未來的問題永遠(yuǎn)不會(huì)到來,你最終要么必須維護(hù)一堆永遠(yuǎn)不會(huì)被完全使用的龐大代碼,要么得整個(gè)重新寫,因?yàn)橛幸淮蠖哑ㄓ脹]有的東西......

解決你現(xiàn)在遇到的問題,然后解決下一個(gè),然后再下一個(gè)。直到有一天,你會(huì)發(fā)現(xiàn)這些解決方案中顯現(xiàn)出了一種固定的模式,然后你才能真正地“一次性解決所有問題”。

文檔是寫給未來自己的情書

我們都知道,為函數(shù)、類(class)和模塊編寫該死的文檔是一個(gè)痛苦的過程。但是以后當(dāng)你看到文檔就能回想起來當(dāng)時(shí)你編寫函數(shù)時(shí)的思路,你就會(huì)明白將來文檔能在關(guān)鍵時(shí)刻救你一命。

功能文檔是份合同

當(dāng)你以編寫文檔作為自己編程工作的起始點(diǎn)時(shí),你實(shí)際上是在簽訂合同(可能是跟未來的自己):我說了這個(gè)函數(shù)要做這件事情,那么它就必須做這件事情。如果稍后你發(fā)現(xiàn)代碼與文檔不匹配,那你就是代碼出了問題,而不是文檔出了問題。

如果一個(gè)函數(shù)的描述包含“和”,這就是不對(duì)的

一個(gè)函數(shù)應(yīng)該且僅應(yīng)該做一件事,真的。當(dāng)你編寫函數(shù)文檔并發(fā)現(xiàn)你寫了“和”這個(gè)字的時(shí)候,這意味著該函數(shù)不僅僅是做一件事。那么就需要將該函數(shù)分解為兩個(gè)獨(dú)立函數(shù)并刪除“和”。

不要使用布爾型變量作為參數(shù)

當(dāng)你設(shè)計(jì)一個(gè)函數(shù)時(shí),你可能會(huì)想要添加一個(gè)flag——不要這樣做。

現(xiàn)在,讓我給你舉個(gè)栗子:假設(shè)你有一個(gè)消息傳遞系統(tǒng),并且有一個(gè)函數(shù)可以將所有消息返回給用戶,稱為getUserMessages。但有一種情況是需要返回每條消息的摘要(例如,第一段)或完整消息,因此,你添加一個(gè)名為retrieveFullMessage的flag/布爾參數(shù)。

再說一次,不要這樣做。

因?yàn)槿魏巫x你代碼的人都會(huì)看到getUserMessage(userId,true)并想知道這里的true到底是個(gè)什么意思。

你可以將函數(shù)重命名為getUserMessageSummaries并使用另一個(gè)getUserMessagesFull或類似的東西,但每個(gè)函數(shù)只調(diào)用原始的getUserMessage為true或false——但是類/模塊外部的接口仍然是清楚 的。

但是一定“不要”在函數(shù)中添加flags / Boolean作為參數(shù)。

注意界面的變化

在上面幾點(diǎn)中,我提到了重新命名函數(shù)的問題,如果你能操縱 使用該函數(shù)的整個(gè)源頭,那就不算是問題,只需要搜索和替換即可。

但是,如果該函數(shù)實(shí)際上是由庫公開的,那么你不能隨便地更改函數(shù)名稱。這將打破你無法操縱 的許多其他應(yīng)用程序,并惹惱其他人。

你可以通過文檔或某些代碼功能創(chuàng)建新函數(shù)并將當(dāng)前函數(shù)標(biāo)記為已棄用,然后,經(jīng)過幾次釋放后,你終于可以Kill掉原來的函數(shù)了。

(你可以做的一個(gè)有些混蛋的舉動(dòng)是創(chuàng)建新函數(shù),將當(dāng)前函數(shù)標(biāo)記為已棄用,并在函數(shù)開頭添加一個(gè)休眠,這樣一來使用舊函數(shù)的人會(huì)被迫更新。)

好的語言自帶集成的文檔

如果語言有自己的方式來記錄函數(shù)、類、模塊或其他,而且?guī)в幸粋€(gè)哪怕最簡單的文檔生成器,你就可以確切知道所有的函數(shù)、類、模塊、庫、框架都具有良好的文檔了(不是說一定特別好,但至少是比較好的)。

大多數(shù)情況下,沒有集成文檔的語言,文檔方面做得都不怎么樣。

一門語言絕不僅僅是一門語言而已

編程語言就是你寫的、而且能做事情的東西,但在特別 關(guān)鍵詞以外它還有很多別的東西:它有一個(gè)構(gòu)建系統(tǒng),它有一個(gè)依賴操縱 系統(tǒng),它有一種使工具/庫/框架互動(dòng)的方式,它有一個(gè)社區(qū),它有一種與人打交道的方式。

不要僅僅因?yàn)橐环N語言容易使用就選擇它。永遠(yuǎn)記住,你可能因?yàn)橐环N語言的語法很簡明而支持這種語言,但是與此同時(shí)你也是在支持維護(hù)人員對(duì)待這個(gè)社區(qū)的方式。

有時(shí)候,寧愿讓應(yīng)用程序崩潰也不要什么都不做

雖然這聽起來很奇怪,但即使在處理過程中添加了某些錯(cuò)誤,也不要默默地捕捉到錯(cuò)誤但什么都不做。

Java中一個(gè)可悲的常見模式是:

這看起來跟處理異常沒有什么關(guān)系——除了重復(fù)了一遍,僅此而已。

如果你不知道如何處理它,那就隨它去吧,你早晚會(huì)知道它會(huì)發(fā)生什么。

如果你知道如何處理該問題,那么就處理它

與前一點(diǎn)相反:如果你知道什么東西在何時(shí)會(huì)導(dǎo)致異常/錯(cuò)誤/某種結(jié)果,并且知道如何處理它,那么就請(qǐng)?zhí)幚硭?。顯示錯(cuò)誤信息,嘗試將數(shù)據(jù)保存在其他位置,將日志文件中用戶的輸入捕獲到以便以后處理,但要記得處理它。

類型決定你的數(shù)據(jù)是個(gè)什么東西

內(nèi)存中只是一串字節(jié)序列;字節(jié)只是 0 到 255 之間的數(shù)字組合;這些數(shù)字的真正含義取決于語言的類型系統(tǒng)。

例如,在C中,值為 65 的char型變量可能是字母“A”,值為 65 的int型變量是數(shù)字65——處理數(shù)據(jù)時(shí)請(qǐng)不要忘記這一點(diǎn)。這也是為什么大多數(shù)人在用布爾型變量做加法以查看True的數(shù)量時(shí)經(jīng)常出錯(cuò)。

現(xiàn)在,讓我展示一下我最近看到的一個(gè)JavaScript里的例子:

如果你的數(shù)據(jù)具有模式(schema),請(qǐng)使用結(jié)構(gòu)(structure)來保留它

你可能會(huì)想要使用列表(或元組,如果你用的語言同意的話)來保存數(shù)據(jù),如果它很簡單——比如說,只有 2 個(gè)字段。

但是如果你的數(shù)據(jù)有一個(gè)模式(schema),有一個(gè)固定的格式——你應(yīng)該每次都使用一些結(jié)構(gòu)來保存它,不管是用struct還是class。

理解并保持cargo cult的方式

“Cargo cult”是一種理念,如果其他人那樣做了,那么我們也可以。大多數(shù)情況下,cargo cult只是對(duì)一個(gè)問題的偷懶的解決方法:

“如果X這樣做了,我們?yōu)槭裁匆紤]如何正確存儲(chǔ)我們的用戶數(shù)據(jù)?”

“如果有某巨頭公司是這樣存儲(chǔ)數(shù)據(jù)的,那么我們也可以”。

“如果有某巨頭公司支持這種做法,那就說明這種方法很好。”

......

不要管所謂的“合適的生產(chǎn)力工具”,你只需要盡力去push進(jìn)程

“合適的生產(chǎn)力工具”其實(shí)意味著:對(duì)于某件事情,有一個(gè)正確的工具和一個(gè)錯(cuò)誤的工具——例如,應(yīng)該使用另外的某種語言/框架而不是當(dāng)前的語言/框架。但每當(dāng)我聽到有人提到這個(gè)詞時(shí),他們都是在試圖推銷他們喜歡的語言/框架,而不是合適的語言/框架。

“正確的工具”比你想象的更明顯

也許你當(dāng)前的項(xiàng)目需要處理一些文本,也許你很想說“讓我們用Perl吧!”,因?yàn)槟阒繮erl在處理文本時(shí)非常強(qiáng)大。

但你漏掉了哪一點(diǎn)呢?你在一個(gè)C的團(tuán)隊(duì)工作,每個(gè)人會(huì)C,而不是Perl。

當(dāng)然,如果它是一個(gè)小的、“放在角落”的不起眼的項(xiàng)目,那么用Perl就可以了——但如果它對(duì)公司很重要,那么最好還是用C。

PS:你的英雄項(xiàng)目(本文稍后將詳細(xì)介紹)可能因此而失敗。

不要跟你項(xiàng)目之外的事情糾纏

有時(shí)人們會(huì)試圖改變外部庫/框架,而不是使用適當(dāng)?shù)臄U(kuò)展工具——例如,直接對(duì)WordPress或Django進(jìn)行更改。

這樣很容易讓你的項(xiàng)目秒癱瘓,變得無法維護(hù)。一旦公布了新版本,你就必須與主項(xiàng)目保持同步,并且很快就會(huì)發(fā)現(xiàn)改動(dòng)不再適用,你將把外部項(xiàng)目留在一個(gè)舊版本中,且充滿了安全漏洞。

數(shù)據(jù)流動(dòng)比模式更重要

(再次說明,這僅僅是個(gè)人意見)當(dāng)你了解數(shù)據(jù)如何在代碼中流動(dòng)時(shí),你的代碼質(zhì)量就會(huì)更上一層樓,這比無腦應(yīng)用一堆設(shè)計(jì)設(shè)計(jì)模式(design pattern)好多了。

設(shè)計(jì)模式是用來描述解決方案的,但它不能找到解決方案

(同樣,個(gè)人觀點(diǎn))大多數(shù)時(shí)候我看到設(shè)計(jì)模式被應(yīng)用的時(shí)候,它們被用作尋找解決方案的一種方式,所以你最終會(huì)扭曲一個(gè)解決方案——有時(shí)候,甚至是扭曲問題本身——來適應(yīng)某個(gè)設(shè)計(jì)模式。

首先,解決你的問題,找到一個(gè)好的解決方案,然后你可以檢查模式,以提供如何命名該解決方案的思路。

我經(jīng)??吹竭@種情況發(fā)生:我們有這個(gè)問題;一個(gè)設(shè)計(jì)模式接近正確的解決方案;讓我們使用這個(gè)設(shè)計(jì)模式吧;現(xiàn)在我們需要在適當(dāng)?shù)慕鉀Q方案基礎(chǔ)上添加很多東西以適應(yīng)這個(gè)設(shè)計(jì)模式......

學(xué)習(xí)函數(shù)式編程的基礎(chǔ)知識(shí)

你不需要徹底搞懂“什么是一個(gè)單子(monad)?”和“這是一個(gè)函子(functor)?”等問題,但要知道不能一直改變數(shù)據(jù)——使用新值創(chuàng)建一個(gè)新元素(將數(shù)據(jù)視為不可變),并盡可能使函數(shù)/類不保留某些內(nèi)部狀態(tài)(純函數(shù)/類)。

認(rèn)知成本是可讀性的殺手

“認(rèn)知失調(diào)”是一種高大上的說法,但其實(shí)意思就是“我需要同時(shí)記住兩個(gè)(或更多)不同的東西才能理解這一點(diǎn)?!卑堰@些不同的東西保留在你的頭腦中會(huì)產(chǎn)生成本,并且事物之間關(guān)聯(lián)性越小,這種成本就越會(huì)不斷積存 (因?yàn)槟惚仨毎阉羞@些都記在腦子里)。

例如,將布爾值相加以計(jì)算True的數(shù)量就是一種輕微的認(rèn)知不協(xié)調(diào);如果你正在閱讀一段代碼并看到一個(gè)sum()函數(shù),你知道它是列表中所有數(shù)字的總和,你就預(yù)料到列表由數(shù)字組成,但我看到過人們使用sum函數(shù)計(jì)算布爾值列表中的True的數(shù)量,這也太特么容易讓人糊涂了吧。

Magical Number 7 ,正負(fù)二(7+- 2 的范圍內(nèi))

“magical number”是一篇心理學(xué)文章中提到的概念,意思指人們可以在同一時(shí)間記住的事物的數(shù)量。如果你有一個(gè)函數(shù),它調(diào)用一個(gè)調(diào)用函數(shù)的函數(shù),該函數(shù)又調(diào)用一個(gè)調(diào)用函數(shù)的函數(shù)……再往下說下去你可能要瘋。

想一想:我會(huì)得到這個(gè)函數(shù)的結(jié)果,然后將它傳遞給第二個(gè)函數(shù),得到它的結(jié)果,然后傳遞給第三個(gè)函數(shù)。但是:

  • 當(dāng)今,心理學(xué)家更多地談?wù)揗agical Number 4,而不是7。

  • 把函數(shù)當(dāng)成寫作文(如“我將調(diào)用該函數(shù),然后該函數(shù),然后該函數(shù)......”),而不是函數(shù)作為主體(如“該函數(shù)將調(diào)用該函數(shù),將調(diào)用該函數(shù)......”) 。

走捷徑挺nice的,但只是在短期內(nèi)如此

許多語言、庫、框架都有縮短工作時(shí)間的方法,減少了需要你打字輸入的內(nèi)容。但是,稍后,這些東西會(huì)讓你栽跟頭,你將不得不棄用這些捷徑并懂得人間正道是滄桑的道理。

因此,在使用之前,先了解那些捷徑是如何做事情的。

你不需要先用難的方式寫東西然后再用捷徑的方式清理:你只需要走捷徑在后臺(tái)做事情,所以你至少知道使用它可能出錯(cuò)的地方在哪里,以及如何用非捷徑方式替換它。

抵制“輕松”的誘惑

當(dāng)然IDE會(huì)幫助你完成大量的自動(dòng)填充并讓你輕松構(gòu)建你的項(xiàng)目,但是你明白發(fā)生了什么嗎?你了解你的構(gòu)建系統(tǒng)是如何工作的嗎?如果你必須在沒有IDE的情況下運(yùn)行你的程序,你知道該怎么做嗎?如果沒有自動(dòng)填充你能記住你的函數(shù)名嗎?是不是有辦法打破/重命名一些東西讓它們更容易被理解?......

要對(duì)窗簾后面的東西保持好奇。

總是在你的日期中使用時(shí)區(qū)

處理日期時(shí)請(qǐng)始終添加時(shí)區(qū)。你的計(jì)算機(jī)時(shí)區(qū)和生產(chǎn)服務(wù)器時(shí)區(qū)(或其中一個(gè)實(shí)例時(shí)區(qū))將始終存在問題,你將花大量時(shí)間來調(diào)試為什么界面總是顯示錯(cuò)誤的時(shí)間。

總是使用UTF-8

在日期上出現(xiàn)的問題,也將出現(xiàn)在對(duì)字符的編碼上。所以時(shí)刻記得將你的字符串轉(zhuǎn)換為UTF8,將它們作為UTF8 保存在數(shù)據(jù)庫中,在你的API上返回UTF8。

你可以轉(zhuǎn)換為任何其他編碼方式,但UTF8 贏得了編碼戰(zhàn)爭(zhēng),因此更容易保持這種方式。

從笨辦法開始

遠(yuǎn)離IDE的一種方法是“從笨辦法開始”:只需獵取 編譯器并獲得一個(gè)帶有代碼突出顯示的編輯器(任何編輯器),做你該做的事情:寫代碼,構(gòu)建它,運(yùn)行它。

不,這并不容易。但是當(dāng)你跳進(jìn)某個(gè)IDE時(shí),你看到某個(gè)按鈕只會(huì)簡單地想,“是的,它會(huì)運(yùn)行它”(順便說一下,這正是IDE所做的)。

日志用于事件,而不是用戶界面

很長一段時(shí)間,我使用日志向用戶顯示正在發(fā)生的事情——因?yàn)?,你知道的,使用單個(gè)東西會(huì)更容易一些。

使用標(biāo)準(zhǔn)輸出通知用戶發(fā)生了什么事件,使用標(biāo)準(zhǔn)錯(cuò)誤通知用戶有關(guān)錯(cuò)誤的信息,但使用日志來捕捉可以在日后輕松處理的東西。

將日志想成是你必須解析以便在那時(shí)從中提取一些信息的東西,而不是用戶界面,它不一定要是讓人看得懂的明文。

Debugger們被高估了

我常常聽到很多人抱怨,不能Debug的編輯器有多糟糕。

但是當(dāng)你的代碼投入生產(chǎn)時(shí),你無法運(yùn)行你喜歡的Debugger;哎呀,你甚至不能運(yùn)行自己喜歡的IDE;但是logging......logging隨處都可以運(yùn)行......你可能在崩潰時(shí)沒有所需的信息(例如,不同的日志記錄級(jí)別),但你可以啟用日志記錄以便稍后找出某些內(nèi)容。

不是說Debugger們很糟糕,只是它們沒有大多數(shù)人想象的那么有用。

始終使用版本操縱 系統(tǒng)

“這只是個(gè)隨便寫的破程序,我只想學(xué)點(diǎn)東西”——這不是一個(gè)不使用版本操縱 系統(tǒng)的好借口。如果你從一開始就使用版本操縱 系統(tǒng),那么當(dāng)你做了一些傻事時(shí),撤銷會(huì)更容易。

每次提交一個(gè)更改

我見過人們編寫提交消息,如“修復(fù)了問題#1,# 2 和#3”。除非所有這些問題都是重復(fù)的——那么其中兩個(gè)應(yīng)該已經(jīng)不存在——它們應(yīng)該分三次提交,而不是一次。

嘗試在每次提交中只進(jìn)行一項(xiàng)更改(并且這里的更改并不是“一個(gè)文件更改”; 如果一個(gè)更改需要更改三個(gè)文件,你應(yīng)該將這三個(gè)文件一起提交。想想“如果我還原這一步,那是什么消逝了?“)

當(dāng)你過度交換時(shí),“git add -p”是你的朋友

(僅限Git的主題)Git同意使用“-p”部分合并文件,這同意你僅選擇相關(guān)更改并不管其他更改——可能是為了新的一項(xiàng)提交。

按數(shù)據(jù)/類型組織項(xiàng)目,而不是功能

大多數(shù)項(xiàng)目的組織如下:

換句話說,它們使數(shù)據(jù)按功能分類組織(所有傳入的模型都在同一目錄/包中,所有過濾器都在同一個(gè)目錄/包中,依此類推)。

這很好,很有效。但是當(dāng)你按照數(shù)據(jù)進(jìn)行組織時(shí),將項(xiàng)目拆分到較小的項(xiàng)目中會(huì)更容易——因?yàn)樵谀承r(shí)候,可能你想要做的與你現(xiàn)在正在做的幾乎一樣,只是有些許小的差異。

現(xiàn)在,你可以創(chuàng)建一個(gè)僅處理Data1 的模塊,另一個(gè)僅適用于Data2 的模塊,依此類推,然后你就可以將它們分解為獨(dú)立的模塊了。然后當(dāng)你有另一個(gè)項(xiàng)目也有Data1 但也處理Data3 時(shí),你可以重新用上Data1 模塊中的大部分內(nèi)容。

創(chuàng)建庫

我已經(jīng)見過很多項(xiàng)目要么創(chuàng)建一個(gè)包含不同項(xiàng)目的大型存儲(chǔ)庫,要么保留不同的分支,這些分支不被用作以后加入主要開發(fā)區(qū)域的臨時(shí)環(huán)境,而作為一個(gè)小而不同的東西連續(xù) 下去了(從上文講到的模塊化角度來說,請(qǐng)想象一下,我沒有構(gòu)建一個(gè)重用Data1 類型的新項(xiàng)目,而是擁有一個(gè)具有完全不同的主函數(shù)和Data3 類型的分支)。

為什么不將公共部分拆分出來加到庫里并在不同的項(xiàng)目中應(yīng)用它呢?

原因在于,大多數(shù)情況下,“因?yàn)槿藗円词遣恢廊绾蝿?chuàng)建庫,要么是他們擔(dān)心如何將這些庫‘公布’到依賴源中而不致泄露(因此也許你也應(yīng)該了解你的項(xiàng)目治理 工具如何檢索依賴項(xiàng),以便你可以創(chuàng)建自己的依賴項(xiàng)存儲(chǔ)庫)?!?

學(xué)會(huì)監(jiān)控

從前,為了理解系統(tǒng)的行為方式,我添加了大量的指標(biāo):輸入速度、輸出速度、中間滯留數(shù)量、已處理的數(shù)量......這樣可以很好地了解系統(tǒng)的行為方式:速度在下降嗎?如果是的,那我可以檢查正在輸入系統(tǒng)的內(nèi)容以了解原因。在某些時(shí)候下降是否正常?......

事實(shí)上,在此之后,試圖查明一個(gè)沒有任何監(jiān)控的系統(tǒng)有多健康就變得很奇怪,僅使用“是否應(yīng)答請(qǐng)求”來檢查系統(tǒng)運(yùn)行狀況不再適用。

盡早添加監(jiān)控將有助于你了解系統(tǒng)的行為方式。

config文件是個(gè)好東西

想象一下,你編寫了一個(gè)函數(shù),你必須為它傳入一個(gè)初始值才能開始運(yùn)行(例如,一個(gè)推特用戶帳戶ID)。但是后來你又必須用兩個(gè)值來做,所以你就直接用另一個(gè)值再次調(diào)用了該函數(shù)。

使用配置文件更有道理,只需使用兩個(gè)不同的config文件運(yùn)行應(yīng)用程序兩次。

命令行選項(xiàng)很奇怪,但很有幫助

如果你將某樣?xùn)|西移動(dòng)到config文件,你還可以通過添加選項(xiàng)來選擇配置文件并公開它來幫助用戶。

現(xiàn)在對(duì)每種語言的命令行選項(xiàng)都有一些庫可以處理,這將有助于你構(gòu)建一個(gè)良好的命令行,并為你的用戶提供一個(gè)標(biāo)準(zhǔn)的接口。

不僅僅是功能組成,還有應(yīng)用程序組成

Unix自帶“應(yīng)用程序只做一件事,并且把它做好”的理念。

如今,我說你可以使用一個(gè)帶有兩個(gè)配置文件的應(yīng)用程序,但是如果你需要兩個(gè)應(yīng)用程序的結(jié)果呢?那時(shí)你可以編寫一個(gè)應(yīng)用程序,用兩個(gè)配置文件讀取第一個(gè)的結(jié)果并轉(zhuǎn)換為單個(gè)結(jié)果。

即使是做APP,也要從原始的東西開始

APP的開發(fā)可能會(huì)涉及微服務(wù)——這很好——但微服務(wù)需要一些關(guān)于應(yīng)用程序如何通過線路(協(xié)議等)在彼此之間“對(duì)話”的想法。你不需要從那開始,應(yīng)用程序都可以從文件中寫入和讀取,這樣容易多了。

當(dāng)你了解了網(wǎng)絡(luò)是如何工作后,再通過電話進(jìn)行交談時(shí)可能會(huì)擔(dān)心的吧。

優(yōu)化是面向編譯器的

假設(shè)你需要更高的性能,你可能很想看看你的代碼和“可以在這里擠出更多性能的東西”或“如何在這里刪除幾個(gè)循環(huán)來獲得更多速度”。

好吧,猜猜怎么著?編譯器知道如何做到這一點(diǎn)。智能化的編譯器甚至可以刪除你的部分代碼,因?yàn)樗冀K會(huì)生成相同的結(jié)果。你需要做的是為代碼考慮更好的設(shè)計(jì),而不是如何改進(jìn)當(dāng)前代碼。

代碼是為了讓人類閱讀的、優(yōu)化面向編譯器的,因此,找到一種智能的方法來解釋你在嘗試做的是什么(在代碼中)而不是使用更少的話語來表述。

通過懶惰(評(píng)估)

Lisp很久以前就這么做了,而現(xiàn)在大多數(shù)語言都是這樣做的。

例如,Python有yield語句,它將停止當(dāng)前函數(shù)的執(zhí)行并馬上 返回值,只有在再次調(diào)用該函數(shù)時(shí)才會(huì)產(chǎn)生新值。如果你將使用yield的函數(shù)鏈接起來,則不需要像保留返回列表的函數(shù)那樣多的內(nèi)存。

在團(tuán)隊(duì)/工作上

code review并不是為了彰顯風(fēng)格

花點(diǎn)時(shí)間進(jìn)行code review,指出架構(gòu)或設(shè)計(jì)問題,而不是代碼樣式(風(fēng)格)問題。沒有人真正喜歡那些在code review中寫“你在這一行中留下空白了”或“括號(hào)前缺少空格”的人。

現(xiàn)在,如果你確實(shí)發(fā)現(xiàn)了架構(gòu)或設(shè)計(jì)問題,那么你可以順便說一下代碼風(fēng)格問題。

代碼格式化工具還可以,但它們也不是無往不勝的

團(tuán)隊(duì)可能想要幸免在code review中討論樣式,因而可能會(huì)考慮使用代碼格式化工具在提交之前自動(dòng)格式化代碼。

是的,這部分解決了這個(gè)問題,但是還有一個(gè)小問題:我們?nèi)祟惒幌裼?jì)算機(jī)那樣能靈活地閱讀代碼,計(jì)算機(jī)可讀的內(nèi)容可能無法被人閱讀。當(dāng)然,有人試圖在有利于人類閱讀的方面制造一些啟發(fā)式方法,但這并不意味著這些方法正確。

如果你使用代碼格式化工具,請(qǐng)使用它來找出最能更改代碼的位置。你可能需要簡化這一部分的代碼,以幸免它出現(xiàn)混亂。

代碼風(fēng)格:遵循它就是了

如果你的項(xiàng)目具有已被定義的代碼樣式,則必須遵循它。有時(shí)可能不清楚(“這個(gè)結(jié)構(gòu)/類應(yīng)該是單數(shù)還是復(fù)數(shù)”?),但請(qǐng)盡力遵循它。

...除非代碼樣式是Google Code樣式

(完全個(gè)人觀點(diǎn),你不同意也沒關(guān)系)每次谷歌公布自己的編碼風(fēng)格,都是一場(chǎng)垃圾焚燒。社區(qū)之前采納了更好的風(fēng)格方式,谷歌帶來一個(gè)與此很不相同的的風(fēng)格,只是為了能使其在自己名下。

C / C ++只有一種編碼風(fēng)格:K&R

(再次,完全個(gè)人意見)其他所有編碼風(fēng)格都是錯(cuò)誤的。(笑)

Python只有一種編碼風(fēng)格:PEP8

社區(qū)(大部分)使用PEP8 風(fēng)格,遵循它,那么你的代碼可以順利地與生態(tài)系統(tǒng)中的其他部分集成。

顯式優(yōu)于隱式

你知道什么是有史以來最糟糕的函數(shù)名稱之一嗎?sleep()。

睡了多久?是幾秒還是幾毫秒?

對(duì)你使用的東西要表達(dá)地明確一些,sleepForSecs和sleepForMs并不完美,但比一個(gè)單純的sleep更好。

(當(dāng)你編寫應(yīng)用程序命令行界面或其配置文件時(shí),請(qǐng)考慮這一點(diǎn)。)

(我可以在這里拋出整個(gè)“Python之禪”,但我正在努力專注于講個(gè)人的,直接的體驗(yàn)。)

公司想要專才,但全才在公司待的時(shí)間更長

如果你對(duì)單一語言了解很多,那么它可能會(huì)讓你更容易找到一份工作,但從長遠(yuǎn)來看,一門語言的使用可能會(huì)消逝,你就需要再學(xué)一門別的語言了。適當(dāng)了解許多門其他語言有助于長遠(yuǎn)進(jìn)展,更不用說這可能有助于你想出更好的解決方案了。

“一種不能影響你對(duì)編程的思考方式的語言,不值得了解?!薄狝lan Perlis

很長一段時(shí)間,我遵循著一個(gè)簡單的編程規(guī)則:我在家里用來玩的語言不應(yīng)該是我在工作中使用的語言。這使我能夠接觸到后來我在工作代碼庫中應(yīng)用的新內(nèi)容。

我通過編寫Rust代碼了解了泛型如何在Java中工作;我理解了Spring如何完成依賴注入因?yàn)槲抑坝袑W(xué)過如何在C++中實(shí)現(xiàn)。

心中有用戶

想一想你將如何使用你從用戶那里收集的數(shù)據(jù)——這在當(dāng)今“隱私”變?yōu)橐环N奢侈的時(shí)代更為普遍。

如果你捕獲任何使用數(shù)據(jù),請(qǐng)記住保護(hù)它免遭未經(jīng)授權(quán)的使用。

處理用戶數(shù)據(jù)的最佳安全方法是壓根不捕獲它

你可以確定,在某些時(shí)候,數(shù)據(jù)會(huì)因某些安全漏洞或人為干擾而泄漏。如果你沒有捕獲任何用戶數(shù)據(jù)——或以匿名方式存儲(chǔ)——你將不會(huì)遇到任何問題。

記下來那些“讓我花了一個(gè)多小時(shí)才解決的愚蠢失誤”

我嘗試過,但從未真正建成過一個(gè)列表來記錄那些需要花一個(gè)多小時(shí)才能修正的失誤,這種失誤僅僅是“忘了添加依賴”或“添加注釋”一類,可我不止一次與這些愚蠢的失誤作斗爭(zhēng)了。

但你應(yīng)該嘗試保留一個(gè)列表來記錄那些讓你花了一個(gè)多小時(shí)才解決的愚蠢失誤,因?yàn)橛辛怂院竽憬鉀Q起這類失誤來要更快一些。

如果它無法在你的計(jì)算機(jī)上運(yùn)行,那么你就有麻煩了

我看過很多系統(tǒng)永遠(yuǎn)無法在孤立的計(jì)算機(jī)上運(yùn)行,比如開發(fā)人員工具,因?yàn)橄到y(tǒng)需要在專門的環(huán)境中運(yùn)行。

這真的會(huì)扼殺生產(chǎn)力。

如果你的系統(tǒng)將在一個(gè)專門的環(huán)境中運(yùn)行——包括“云”——那就去找可以抽象你所用之物的東西。例如,如果你使用的是AWS SQS(隊(duì)列),請(qǐng)找到一個(gè)可以抽象隊(duì)列工作方式的庫,這樣你也可以使用RabbitMQ了,就可以在你自己的計(jì)算機(jī)上輕松運(yùn)行了。

如果你使用的是非常專門化的東西,你可能必須自己編寫抽象邏輯了,將其與主系統(tǒng)隔離,這樣你就可以安心開發(fā)主要產(chǎn)品。



個(gè)人生活

該停下來的時(shí)候,就停下來吧

要知道自己什么時(shí)候?qū)懖粍?dòng)代碼了,要知道自己什么時(shí)候?qū)W不動(dòng)了......不要強(qiáng)迫自己,不然將來只會(huì)使事情變得更糟。

有一次偏頭痛時(shí)(不嚴(yán)峻 ,但也不算輕),我試著堅(jiān)持繼續(xù)寫代碼。結(jié)果第二天,當(dāng)我好點(diǎn)了的時(shí)候,我不得不將大部分重寫,因?yàn)榍耙惶鞂懙膶?shí)在太爛了。

CoC保護(hù)的是你,而不是別人

當(dāng)你開始使用任何語言/庫/框架時(shí),請(qǐng)檢查他們的CoC。這會(huì)保護(hù)你,不會(huì)讓你因?yàn)闆]能立馬就上手而被別人懟,而不是阻止你告訴別人你的想法。

我提這個(gè)因?yàn)楹芏嗳吮г笴oC,但是他們忘記了正是CoC使他們能加入任何項(xiàng)目而不被白眼,被說是“新手菜雞”或“先去看完文檔,否則別來煩我們”。

此外,請(qǐng)記住,大多數(shù)反對(duì)CoC的都是那些希望能直接責(zé)罵任何人的人。

學(xué)會(huì)說不

有時(shí),你不得不說:不,我不能這樣做;不,在這個(gè)時(shí)間之前完不成;不,我覺得不能做到這一點(diǎn);不,我寫這個(gè)感覺不舒服。

有一次我不得不對(duì)我們的CTO說:“好的,我會(huì)做的,但我想說明,我不認(rèn)同我們正在做的事情?!弊詈?,APP剛好就因?yàn)槲覀冏龅氖虑槎唤沽恕?

你負(fù)責(zé)你代碼的使用

這很難,非常非常難,這就是“自由”和“責(zé)任”之間的區(qū)別。

寫代碼沒有錯(cuò),例如,用于捕捉人臉并檢測(cè)其種族的軟件,但你必須考慮它將被用在何處。

當(dāng)還沒完成時(shí),不要說“已經(jīng)完成了”

你厭倦了一遍又一遍地運(yùn)行同樣的事情。有時(shí)候即使你記得會(huì)發(fā)生一些小故障,但是因?yàn)槟憷哿?,你就告訴大家“已經(jīng)完成了”。

——不要那樣做。有人會(huì)在第一次運(yùn)行時(shí)就遇到故障并馬上 告訴你它不work。

你將從痛苦中了解你自身

我們對(duì)無法編譯的代碼會(huì)感到很挫敗,也會(huì)對(duì)客戶來回詢問一些事情而感到憤慨 。當(dāng)發(fā)生這種情況時(shí),我們會(huì)遷怒于他人。

生活就是如此,這些都是難免的。

人們之所以會(huì)對(duì)代碼/架構(gòu)感到生氣/煩惱,是出于關(guān)懷

你會(huì)發(fā)現(xiàn)自己處于硬幣的另一面:你將描述一些解決方案,人們會(huì)對(duì)某些解決方案感到惱火/生氣。當(dāng)人們關(guān)懷 產(chǎn)品/代碼時(shí),他們往往會(huì)有這種反應(yīng)。

“是的,你不喜歡那種安靜的解決方案,因?yàn)槟闾谝饬恕?,這是別人對(duì)我的最暖心的贊美之一。

從你的煩惱中學(xué)習(xí)

你會(huì)煩惱、生氣、沮喪和憤慨 ,你會(huì)看到人們因?yàn)檫@些情緒而陷入困境。所以你必須了解它,不要忽視它。

我從教訓(xùn)中學(xué)到的一件事是,當(dāng)我感到沮喪時(shí),我會(huì)變得非常有侵略性。現(xiàn)在,當(dāng)我注意到我開始感到沮喪時(shí),我會(huì)向其他人尋求幫助。看到其他人也在努力解決你的問題,這真的很治愈的感覺。

注意人們對(duì)你的反應(yīng)

我有一個(gè)“憤慨 男人的休息臉”那樣一種臉。

有時(shí)候我一問問題,人們就會(huì)略微 后退——就好像我在說他們的解決方案是錯(cuò)的一樣。那時(shí)我必須補(bǔ)充道,“我不是說這是錯(cuò)的,我只是有點(diǎn)困惑”。

這可能會(huì)幫助你幸免陷入困境。

學(xué)會(huì)識(shí)別那些人格有毒的人,并遠(yuǎn)離他們

你會(huì)發(fā)現(xiàn)那些人,即使他們不對(duì)你的事情竊竊私語,他們也會(huì)對(duì)所有事情都說壞話——甚至是說其他人的壞話——而且是公開地說。

遠(yuǎn)離那些人。

你不知道這種態(tài)度會(huì)讓你情緒多么失落。

防備 微觀侵略

“微觀侵略”(Micro-aggressions)是每次小劑量的侵略性評(píng)論。就像有人一直稱你為“那個(gè)人”或看似人畜無害地評(píng)論你在某些政策中的立場(chǎng)。

這種行為很難反擊,因?yàn)镻R不會(huì)聽從你說的話認(rèn)為他們這是在攻擊你。而且,這種行為很難被發(fā)現(xiàn),因?yàn)樗鼈兛雌饋碜銐蛐?,但是它們?huì)堆積起來,到最后你會(huì)一次爆發(fā)你所有的憤慨 。

最好遠(yuǎn)離,盡可能幸免接觸。

不,我不認(rèn)為這樣的人是“會(huì)改正的”

(個(gè)人意見)有人可能會(huì)說“嘿,也許如果你跟那個(gè)人說一下,他們就不會(huì)那么做了”。

就個(gè)人而言,我認(rèn)為他們不會(huì)。這種東西對(duì)他們來說已經(jīng)太久了,他們覺得很自然,而且大多數(shù)情況下,你才是做錯(cuò)的那個(gè)人(因?yàn)闆]有g(shù)et到他們是在開玩笑,例如,真正的“薛定諤的混蛋”風(fēng)格。)

只有當(dāng)你意識(shí)到自己是那類有毒的人/微侵略者時(shí),才有可能自己改正

除非你意識(shí)到你表現(xiàn)得像一個(gè)有毒的人或是在微觀攻擊某人,并且意識(shí)到你實(shí)際上是在搞破壞,不然沒有辦法改變這些性格特征(再次強(qiáng)調(diào),個(gè)人觀點(diǎn))。

......大多數(shù)情況下,聽到別人批判 的聲音可能會(huì)讓你覺得,“他們跟我過不去!”

英雄項(xiàng)目:總有一天你必須做的事情

“英雄項(xiàng)目”是你個(gè)人認(rèn)為可以解決項(xiàng)目中一系列問題的項(xiàng)目/規(guī)范變更/框架。它可能是不同的架構(gòu)、新的框架甚至是新的語言。

這意味著你將花費(fèi)你的空閑時(shí)間來寫一些已經(jīng)被應(yīng)用的/已經(jīng)存在的東西,只是為了證明自己的一個(gè)觀點(diǎn)。

有時(shí)它會(huì)告訴你錯(cuò)在哪里。

(但不管如何,你都從中得到一些東西。)

不要混淆“英雄項(xiàng)目”與“英雄綜合癥”

我至少見過兩類這種情況:有人聲稱項(xiàng)目離了他們就玩不轉(zhuǎn),或者聲稱他們不需要任何人的幫助。

這是“英雄綜合癥”,認(rèn)為有人可以自己獨(dú)當(dāng)一面。

不要做那種人。

知道何時(shí)果斷辭職

你告訴你的老板你沒有按時(shí)完成某項(xiàng)工作,因?yàn)橐恍┮饬现獾脑?,他卻朝你發(fā)飆。

你的一個(gè)同事不斷微觀攻擊你。

另一個(gè)是那個(gè)一直在做愚蠢惡作劇的家伙,不停說廢話以及在背后議論其他的小組。

第三個(gè)人總是抱怨說,當(dāng)他不在時(shí),大家的工作就都搞不定了。

現(xiàn)在是時(shí)候開始投簡歷了,無論你目前的薪水有多高或項(xiàng)目有多棒。

......除非你想在四十多歲時(shí)還經(jīng)常被別人惹惱。

IT世界是一個(gè)非常小的“蛋”

我們這里有這么一種說法:“某事物的世界是一個(gè)小蛋”,這意味著你生活在一個(gè)小世界里,世界整體很小。

IT世界真的很小。

記住今天與你一起工作的人,你可能會(huì)在 15 年后與他重逢,這期間你們可能已經(jīng)各自換過三四份工作了。

你會(huì)在中途遇到很多其他的I.T.人。

他們會(huì)談?wù)撟约骸?

無論你說什么/做什么,都會(huì)被大家談?wù)摰?,一個(gè)人會(huì)聽到并傳遞給另一個(gè)公司,這個(gè)公司將傳遞給其他人,再把故事傳遞給另一家公司,然后突然,你意識(shí)到了,當(dāng)?shù)貨]有人會(huì)雇用你了,因?yàn)槊總€(gè)人都知道你搞砸了一個(gè)項(xiàng)目或捶了一個(gè)同事的臉。

紙質(zhì)筆記實(shí)際上很有幫助

我曾經(jīng)多次嘗試“無紙化”。在某些時(shí)候,我確實(shí)不需要用紙了,但是到最后,在你旁邊如果有一個(gè)小筆記本和一支筆來讓你寫下你需要發(fā)送數(shù)據(jù)的那個(gè)該死的URL的話,真的挺得勁的。

Trello非??幔玃ost-it更好

沒有什么比在桌子上放一堆Post-it更能顯出你是這樣一個(gè)人了:“我真的很忙,但我忙中又井井有條”。

在博客中記錄你笨手笨腳的解決方案仍然比什么都不寫要好

你可能會(huì)覺得“我沒有準(zhǔn)備好談?wù)撨@個(gè)”或“這太愚蠢了我不應(yīng)該談?wù)撨@個(gè)”。

創(chuàng)建一個(gè)博客,公布你那些看起來笨手笨腳的解決方案。不管怎么說,它們肯定還是比某些人的解決方案更聰慧。

此外,稍后再回來寫下更好的解決方案,挑戰(zhàn)你自己之前的方案。

以顯示你的成長。

除此之外,博客還可以幫助你保存筆記或待辦事項(xiàng)。

...但請(qǐng)關(guān)閉評(píng)論

公布你笨手笨腳的解決方案的一個(gè)問題是,這會(huì)吸引一些只想惹毛你的人?!斑@太愚蠢了”,他們會(huì)說??赡軙?huì)有人說,“你好傻”,而他們不知道誰才真的傻。

把評(píng)論關(guān)了。不要讓那些人阻止你。

把你的笨手笨腳的解決方案公布到網(wǎng)上

不要只把那些“很酷,近乎完美”的項(xiàng)目放到Github上,你完全可以表現(xiàn)出來,在某些時(shí)候,你只是初學(xué)者。

畢竟你總是可以隨時(shí)返回并修改代碼。

(或者說不要:我仍然擁有我的第一個(gè)Python項(xiàng)目的公共repo,看起來我剛剛將Java翻譯成Python,而不包含有Python特性的部分。)

列出“我不知道的事情”

著名物理學(xué)家理查德費(fèi)曼保留了一本標(biāo)題為“我不知道的東西”的筆記本。

當(dāng)你發(fā)現(xiàn)一些看起來很酷的東西并且你想知道更多時(shí),創(chuàng)建一個(gè)標(biāo)題為“我不知道的東西”的文件/注釋/任何內(nèi)容都行,然后記下你發(fā)現(xiàn)了的/弄清楚了的東西。

沙澧街