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

2021-05-17    分類: 軟件開發(fā)

【CSDN編者按】“千帆過盡仍少年”,對(duì)于程序員來說,保留技術(shù)初心、不斷提升實(shí)力是夯實(shí)自己的不二法則。而本文的作者,作為一名有著三十多年開發(fā)經(jīng)驗(yàn)的“老”程序員,就在本文中詳細(xì)總結(jié)了自己這些年踩過的坑和實(shí)踐得出的真理,談到了包括軟件開發(fā)、團(tuán)隊(duì)工作、個(gè)人成長(zhǎng)等方方面面。相信閱讀本文后,會(huì)幫助你成為更優(yōu)秀的程序員。
聲明:本文已獲作者 Julio Biason 翻譯授權(quán)。
作者 | Julio Biason
譯者 | 王艷妮,責(zé)編 | 郭芮
以下為譯文:
這是我30年來從事軟件開發(fā)過程中所學(xué)到的一些實(shí)際經(jīng)驗(yàn),可能有些聽起來憤世嫉俗,但都是我的切身經(jīng)驗(yàn)之談。
再次強(qiáng)調(diào),有些內(nèi)容真的是憤世嫉俗,有些則是對(duì)不同工作崗位的長(zhǎng)期觀察。
軟件開發(fā)
先明確問題,再開始寫代碼
如果你不知道你想要解決的問題是什么,那你肯定就不知道要寫些什么代碼。在編寫任何代碼之前,先明確地把應(yīng)用程序是如何工作的寫下來。
“如果沒有需求或設(shè)計(jì),編程就是向空文本文件不斷增加bug的藝術(shù)?!薄狶ouis Srygley
有時(shí),即使只是“電梯演講”(指短時(shí)間內(nèi)表述結(jié)果內(nèi)容)那么長(zhǎng)——用僅僅兩個(gè)自然段來描述這個(gè)應(yīng)用程序的功能——也足夠了。
有時(shí)候我看著自己的代碼發(fā)呆,不知道下一步該怎么做,其實(shí)往往是因?yàn)橄乱徊奖緛砭瓦€沒有被定義出來。一般出現(xiàn)這種情況,就意味著是時(shí)候停下來,與同事們討論一下了——或者重新考慮解決方案。
將步驟寫為注釋
如果你不知道如何開始,請(qǐng)先用自然語(yǔ)言、英語(yǔ)或你的母語(yǔ)描述應(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ì)越明白,無論你寫了什么,從長(zhǎng)遠(yuǎn)來看都無法解決問題。
所以你不應(yīng)該擔(dān)心這個(gè)。你的代碼不是一面墻:如果你必須永遠(yuǎn)拋棄它,那也不是白白浪費(fèi)了材料。當(dāng)然這意味著你編寫代碼的時(shí)間一去不復(fù)返了,但是你現(xiàn)在對(duì)這個(gè)問題有了更好的理解。
好的語(yǔ)言生來帶有綜合測(cè)試
可以肯定的是,如果一種語(yǔ)言在其標(biāo)準(zhǔn)庫(kù)中自帶一個(gè)測(cè)試框架——即使小得不能再小——那么與沒有測(cè)試框架的語(yǔ)言相比,它周圍的生態(tài)系統(tǒng)仍將擁有更好的測(cè)試,無論該語(yǔ)言的外部測(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í)際上是由庫(kù)公開的,那么你不能隨便地更改函數(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ì)被迫更新。)
好的語(yǔ)言自帶集成的文檔
如果語(yǔ)言有自己的方式來記錄函數(shù)、類、模塊或其他,而且?guī)в幸粋€(gè)哪怕最簡(jiǎn)單的文檔生成器,你就可以確切知道所有的函數(shù)、類、模塊、庫(kù)、框架都具有良好的文檔了(不是說一定特別好,但至少是比較好的)。
大多數(shù)情況下,沒有集成文檔的語(yǔ)言,文檔方面做得都不怎么樣。
一門語(yǔ)言絕不僅僅是一門語(yǔ)言而已
編程語(yǔ)言就是你寫的、而且能做事情的東西,但在特殊關(guān)鍵詞以外它還有很多別的東西:它有一個(gè)構(gòu)建系統(tǒng),它有一個(gè)依賴控制系統(tǒng),它有一種使工具/庫(kù)/框架互動(dòng)的方式,它有一個(gè)社區(qū),它有一種與人打交道的方式。
不要僅僅因?yàn)橐环N語(yǔ)言容易使用就選擇它。永遠(yuǎn)記住,你可能因?yàn)橐环N語(yǔ)言的語(yǔ)法很簡(jiǎn)明而支持這種語(yǔ)言,但是與此同時(shí)你也是在支持維護(hù)人員對(duì)待這個(gè)社區(qū)的方式。
有時(shí)候,寧愿讓應(yīng)用程序崩潰也不要什么都不做
雖然這聽起來很奇怪,但即使在處理過程中添加了某些錯(cuò)誤,也不要默默地捕捉到錯(cuò)誤但什么都不做。
Java中一個(gè)可悲的常見模式是:
try { something_that_can_raise_exception()} catch (Exception ex) { System.out.println(ex);}
這看起來跟處理異常沒有什么關(guān)系——除了重復(fù)了一遍,僅此而已。
如果你不知道如何處理它,那就隨它去吧,你早晚會(huì)知道它會(huì)發(fā)生什么。
如果你知道如何處理該問題,那么就處理它
與前一點(diǎn)相反:如果你知道什么東西在何時(shí)會(huì)導(dǎo)致異常/錯(cuò)誤/某種結(jié)果,并且知道如何處理它,那么就請(qǐng)?zhí)幚硭伞o@示錯(cuò)誤信息,嘗試將數(shù)據(jù)保存在其他位置,將日志文件中用戶的輸入捕獲到以便以后處理,但要記得處理它。
類型決定你的數(shù)據(jù)是個(gè)什么東西
內(nèi)存中只是一串字節(jié)序列;字節(jié)只是0到255之間的數(shù)字組合;這些數(shù)字的真正含義取決于語(yǔ)言的類型系統(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里的例子:
console.log(true+true === 2);> trueconsole.log(true === 1);> false
如果你的數(shù)據(jù)具有模式(schema),請(qǐng)使用結(jié)構(gòu)(structure)來保留它
你可能會(huì)想要使用列表(或元組,如果你用的語(yǔ)言允許的話)來保存數(shù)據(jù),如果它很簡(jiǎn)單——比如說,只有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)該使用另外的某種語(yǔ)言/框架而不是當(dāng)前的語(yǔ)言/框架。但每當(dāng)我聽到有人提到這個(gè)詞時(shí),他們都是在試圖推銷他們喜歡的語(yǔ)言/框架,而不是合適的語(yǔ)言/框架。
“正確的工具”比你想象的更明顯
也許你當(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ì)試圖改變外部庫(kù)/框架,而不是使用適當(dāng)?shù)臄U(kuò)展工具——例如,直接對(duì)WordPress或Django進(jìn)行更改。
這樣很容易讓你的項(xiàng)目秒癱瘓,變得無法維護(hù)。一旦發(fā)布了新版本,你就必須與主項(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)如此
許多語(yǔ)言、庫(kù)、框架都有縮短工作時(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ù)庫(kù)中,在你的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ì)簡(jiǎn)單地想,“是的,它會(huì)運(yùn)行它”(順便說一下,這正是IDE所做的)。
日志用于事件,而不是用戶界面
很長(zhǎng)一段時(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)目的組織如下:
.+-- IncomingModels| +-- DataTypeInterface| +-- DataType1| +-- DataType2| +-- DataType3+-- Filters| +-- FilterInterface| +-- FilterValidDataType2+-- Processors| +-- ProcessorInterface| +-- ConvertDataType1ToDto1| +-- ConvertDataType2ToDto2+-- OutgoingModels +-- DtoInterface +-- Dto1 +-- Dto2
換句話說,它們使數(shù)據(jù)按功能分類組織(所有傳入的模型都在同一目錄/包中,所有過濾器都在同一個(gè)目錄/包中,依此類推)。
這很好,很有效。但是當(dāng)你按照數(shù)據(jù)進(jìn)行組織時(shí),將項(xiàng)目拆分到較小的項(xiàng)目中會(huì)更容易——因?yàn)樵谀承r(shí)候,可能你想要做的與你現(xiàn)在正在做的幾乎一樣,只是有些許小的差異。
.+-- Base| +-- IncomingModels| | +-- DataTypeInterface| +-- Filters| | +-- FilterInterface| +-- Processors| | +-- ProcessorInterface| +-- OutgoingModels| +-- DtoInterface+-- Data1| +-- IncomingModels| | +-- DataType1| +-- Processors| | +-- ConvertDataType1ToDto1| +-- OutgoingModels| +-- Dto1...
現(xiàn)在,你可以創(chuàng)建一個(gè)僅處理Data1的模塊,另一個(gè)僅適用于Data2的模塊,依此類推,然后你就可以將它們分解為獨(dú)立的模塊了。然后當(dāng)你有另一個(gè)項(xiàng)目也有Data1但也處理Data3時(shí),你可以重新用上Data1模塊中的大部分內(nèi)容。
創(chuàng)建庫(kù)
我已經(jīng)見過很多項(xiàng)目要么創(chuàng)建一個(gè)包含不同項(xiàng)目的大型存儲(chǔ)庫(kù),要么保留不同的分支,這些分支不被用作以后加入主要開發(fā)區(qū)域的臨時(shí)環(huán)境,而作為一個(gè)小而不同的東西延續(xù)下去了(從上文講到的模塊化角度來說,請(qǐng)想象一下,我沒有構(gòu)建一個(gè)重用Data1類型的新項(xiàng)目,而是擁有一個(gè)具有完全不同的主函數(shù)和Data3類型的分支)。
為什么不將公共部分拆分出來加到庫(kù)里并在不同的項(xiàng)目中應(yīng)用它呢?
原因在于,大多數(shù)情況下,“因?yàn)槿藗円词遣恢廊绾蝿?chuàng)建庫(kù),要么是他們擔(dān)心如何將這些庫(kù)‘發(fā)布’到依賴源中而不致泄露(因此也許你也應(yīng)該了解你的項(xiàng)目管理工具如何檢索依賴項(xiàng),以便你可以創(chuàng)建自己的依賴項(xiàng)存儲(chǔ)庫(kù))?!?br/>學(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ì)每種語(yǔ)言的命令行選項(xiàng)都有一些庫(kù)可以處理,這將有助于你構(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)化面向編譯器的,因此,找到一種智能的方法來解釋你在嘗試做的是什么(在代碼中)而不是使用更少的話語(yǔ)來表述。
通過懶惰(評(píng)估)
Lisp很久以前就這么做了,而現(xiàn)在大多數(shù)語(yǔ)言都是這樣做的。
例如,Python有yield語(yǔ)句,它將停止當(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)然,有人試圖在有利于人類閱讀的方面創(chuàng)造一些啟發(fā)式方法,但這并不意味著這些方法正確。
如果你使用代碼格式化工具,請(qǐng)使用它來找出最能更改代碼的位置。你可能需要簡(jiǎn)化這一部分的代碼,以避免它出現(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ā)布自己的編碼風(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í)間更長(zhǎng)
如果你對(duì)單一語(yǔ)言了解很多,那么它可能會(huì)讓你更容易找到一份工作,但從長(zhǎng)遠(yuǎn)來看,一門語(yǔ)言的使用可能會(huì)消失,你就需要再學(xué)一門別的語(yǔ)言了。適當(dāng)了解許多門其他語(yǔ)言有助于長(zhǎng)遠(yuǎn)發(fā)展,更不用說這可能有助于你想出更好的解決方案了。
“一種不能影響你對(duì)編程的思考方式的語(yǔ)言,不值得了解?!薄狝lan Perlis
很長(zhǎng)一段時(shí)間,我遵循著一個(gè)簡(jiǎn)單的編程規(guī)則:我在家里用來玩的語(yǔ)言不應(yīng)該是我在工作中使用的語(yǔ)言。這使我能夠接觸到后來我在工作代碼庫(kù)中應(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ì)列工作方式的庫(kù),這樣你也可以使用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)你開始使用任何語(yǔ)言/庫(kù)/框架時(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)同我們正在做的事情?!弊詈螅珹PP剛好就因?yàn)槲覀冏龅氖虑槎唤沽恕?br/>你負(fù)責(zé)你代碼的使用
這很難,非常非常難,這就是“自由”和“責(zé)任”之間的區(qū)別。
寫代碼沒有錯(cuò),例如,用于捕捉人臉并檢測(cè)其種族的軟件,但你必須考慮它將被用在何處。
當(dāng)還沒完成時(shí),不要說“已經(jīng)完成了”
你厭倦了一遍又一遍地運(yùn)行同樣的事情。有時(shí)候即使你記得會(huì)發(fā)生一些小故障,但是因?yàn)槟憷哿耍憔透嬖V大家“已經(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ì)變得非常有侵略性?,F(xiàn)在,當(dāng)我注意到我開始感到沮喪時(shí),我會(huì)向其他人尋求幫助??吹狡渌艘苍谂鉀Q你的問題,這真的很治愈的感覺。
注意人們對(duì)你的反應(yīng)
我有一個(gè)“憤怒男人的休息臉”那樣一種臉。
有時(shí)候我一問問題,人們就會(huì)稍微后退——就好像我在說他們的解決方案是錯(cuò)的一樣。那時(shí)我必須補(bǔ)充道,“我不是說這是錯(cuò)的,我只是有點(diǎn)困惑”。
這可能會(huì)幫助你避免陷入困境。
學(xué)會(huì)識(shí)別那些人格有毒的人,并遠(yuǎn)離他們
你會(huì)發(fā)現(xiàn)那些人,即使他們不對(duì)你的事情竊竊私語(yǔ),他們也會(huì)對(duì)所有事情都說壞話——甚至是說其他人的壞話——而且是公開地說。
遠(yuǎn)離那些人。
你不知道這種態(tài)度會(huì)讓你情緒多么失落。
謹(jǐn)防微觀侵略
“微觀侵略”(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ù)情況下,聽到別人批評(píng)的聲音可能會(huì)讓你覺得,“他們跟我過不去!”
英雄項(xiàng)目:總有一天你必須做的事情
“英雄項(xiàng)目”是你個(gè)人認(rèn)為可以解決項(xiàng)目中一系列問題的項(xiàng)目/規(guī)范變更/框架。它可能是不同的架構(gòu)、新的框架甚至是新的語(yǔ)言。
這意味著你將花費(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í)候開始投簡(jiǎn)歷了,無論你目前的薪水有多高或項(xiàng)目有多棒。
......除非你想在四十多歲時(shí)還經(jīng)常被別人惹惱。
IT世界是一個(gè)非常小的“蛋”
我們這里有這么一種說法:“某事物的世界是一個(gè)小蛋”,這意味著你生活在一個(gè)小世界里,世界整體很小。
IT世界真的很小。
記住今天與你一起工作的人,你可能會(huì)在15年后與他重逢,這期間你們可能已經(jīng)各自換過三四份工作了。
你會(huì)在中途遇到很多其他的I.T.人。
他們會(huì)談?wù)撟约骸?br/>無論你說什么/做什么,都會(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非常酷,但Post-it更好
沒有什么比在桌子上放一堆Post-it更能顯出你是這樣一個(gè)人了:“我真的很忙,但我忙中又井井有條”。
在博客中記錄你笨手笨腳的解決方案仍然比什么都不寫要好
你可能會(huì)覺得“我沒有準(zhǔn)備好談?wù)撨@個(gè)”或“這太愚蠢了我不應(yīng)該談?wù)撨@個(gè)”。
創(chuàng)建一個(gè)博客,發(fā)布你那些看起來笨手笨腳的解決方案。不管怎么說,它們肯定還是比某些人的解決方案更聰明。
此外,稍后再回來寫下更好的解決方案,挑戰(zhàn)你自己之前的方案。
以顯示你的成長(zhǎng)。
除此之外,博客還可以幫助你保存筆記或待辦事項(xiàng)。
...但請(qǐng)關(guān)閉評(píng)論
發(fā)布你笨手笨腳的解決方案的一個(gè)問題是,這會(huì)吸引一些只想惹毛你的人?!斑@太愚蠢了”,他們會(huì)說。可能會(huì)有人說,“你好傻”,而他們不知道誰(shuí)才真的傻。
把評(píng)論關(guān)了。不要讓那些人阻止你。
把你的笨手笨腳的解決方案發(fā)布到網(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)了的/弄清楚了的東西。
原文:https://blog.juliobiason.net/thoughts/things-i-learnt-the-hard-way/

文章名稱:三十年軟件開發(fā)之路:老碼農(nóng)的自我修養(yǎng)!
文章來源:http://www.muchs.cn/news44/113994.html

網(wǎng)站建設(shè)、網(wǎng)絡(luò)推廣公司-創(chuàng)新互聯(lián),是專注品牌與效果的網(wǎng)站制作,網(wǎng)絡(luò)營(yíng)銷seo公司;服務(wù)項(xiàng)目有軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設(shè)