學(xué)編程一年復(fù)盤:從抄代碼到自動(dòng)化辦公工具的實(shí)戰(zhàn)路徑)
一年前我做了一個(gè)決定用下班后的兩小時(shí)從零開始學(xué)編程。當(dāng)時(shí)多半是帶著一肚子怨氣——每天手工整理表格、復(fù)制粘貼數(shù)據(jù)、反復(fù)核對(duì)格式實(shí)在讓人忍無可忍。但說實(shí)話心里完全沒底非科班出身、離開校園好幾年、數(shù)學(xué)和英語都不算好身邊也沒有人可以問網(wǎng)上鋪天蓋地的“三個(gè)月精通”看著更像廣告而不是經(jīng)驗(yàn)。現(xiàn)在一年過去了我不僅寫完了三個(gè)完整的小項(xiàng)目還把一個(gè)內(nèi)部數(shù)據(jù)處理的工具穩(wěn)定跑在了同事的電腦上。這篇是“學(xué)習(xí)經(jīng)歷”系列的第一篇我打算把這一整年的完整路徑、典型踩坑和真正沉淀下來的學(xué)習(xí)方法從頭到尾復(fù)盤一遍。如果你也正在猶豫要不要學(xué)、或者學(xué)了一陣子了但總覺得沒有實(shí)質(zhì)進(jìn)展這篇應(yīng)該能給你一些參考至少能讓你少走我走過的那些彎路。1. 為什么我決定從“抄代碼”開始而不是先啃語法書1.1 第一次失敗的教訓(xùn)捧著教材啃了一周大多數(shù)人學(xué)編程的第一個(gè)動(dòng)作包括我自己都是去搞一本經(jīng)典的入門書打算“系統(tǒng)”地學(xué)一遍。我最初選的是一本講Python基礎(chǔ)的教材厚厚一本從計(jì)算機(jī)組成、變量類型、數(shù)據(jù)結(jié)構(gòu)這些概念開始講。結(jié)果呢我認(rèn)認(rèn)真真看了差不多一周連一行能跑的代碼都沒寫出來。第1章講計(jì)算機(jī)原理第2章講環(huán)境安裝到第3章終于寫了第一段代碼卻完全不明白為什么這么寫也不知道這些東西將來能干嘛。一周之后我果斷放棄了那種挫敗感至今記得一度懷疑自己是不是真的“不是學(xué)編程的料”。問題出在哪現(xiàn)在回頭看出在信息輸入和反饋的順序上。大腦獲取新知識(shí)的時(shí)候如果沒有一個(gè)即時(shí)反饋的閉環(huán)很難把抽象的概念錨定下來??磿系拇a示例雖然每一個(gè)字都能看懂但那個(gè)“懂了”非常脆弱就像你看懂了一個(gè)菜譜真正上手才發(fā)現(xiàn)連火候都控制不住。我一直沒有親手敲出一段東西、沒有看到自己寫的代碼真的“跑起來”的那一刻所以那些概念很快就模糊成了一團(tuán)。第一次學(xué)習(xí)失敗不是因?yàn)槲冶慷且驗(yàn)榉椒ㄟ`背了大腦的學(xué)習(xí)規(guī)律。1.2 換個(gè)路子手動(dòng)“抄”一個(gè)能跑的項(xiàng)目痛定思痛之后我換了一個(gè)思路。不看書了先找一個(gè)小項(xiàng)目。當(dāng)時(shí)找的是一個(gè)天氣預(yù)報(bào)查詢腳本邏輯非常簡單輸入城市名調(diào)用一個(gè)公開的天氣接口返回溫度和天氣描述。代碼總共不超過一百行有完整的開源版本。我做的事情特別笨把代碼一個(gè)一個(gè)字符地手動(dòng)敲進(jìn)編輯器然后運(yùn)行看結(jié)果。這里有必要解釋一下為什么“手動(dòng)敲”這么重要。復(fù)制粘貼表面上是省了時(shí)間但同時(shí)也省掉了大腦對(duì)語法結(jié)構(gòu)的關(guān)注過程。你手動(dòng)敲一遍會(huì)發(fā)現(xiàn)原來每個(gè)變量都是有名字的原來函數(shù)調(diào)用的括號(hào)里是需要傳參數(shù)的原來縮進(jìn)在Python里不只是風(fēng)格問題而會(huì)影響代碼運(yùn)行。我在敲的過程中頻繁遇到報(bào)錯(cuò)比如漏了一個(gè)冒號(hào)、括號(hào)沒有閉合、變量名拼錯(cuò)。每修一個(gè)報(bào)錯(cuò)我就對(duì)這門語言的結(jié)構(gòu)規(guī)則多建立一層肌肉記憶。這種“敲錯(cuò)、報(bào)錯(cuò)、修好、跑通”的循環(huán)才是真正的學(xué)習(xí)閉環(huán)。1.3 “抄代碼”的具體操作細(xì)節(jié)我要特別強(qiáng)調(diào)一下我說的“抄”不等于機(jī)械打字。在把別人的代碼完整敲一遍之后我會(huì)做以下幾件事第一逐行加上注釋。用自己的話解釋每一行代碼在干什么寫不出來就說明那一行沒看懂再回去看文檔。第二故意改動(dòng)參數(shù)看結(jié)果的變化。比如把城市名改成成都看看返回的數(shù)據(jù)有什么不同把單位改成攝氏度看看顯示邏輯怎么變。第三刪除一部分代碼讓程序跑掛觀察報(bào)錯(cuò)信息長什么樣。如果你對(duì)某個(gè)報(bào)錯(cuò)有印象下次再遇到的時(shí)候就不會(huì)慌你甚至能猜到是哪一類問題。這三步做完一個(gè)一百行的腳本才算真正被“吸收”了一半。剩下的另一半靠后續(xù)的練習(xí)鞏固。按照這個(gè)節(jié)奏我花了一周不到就把那本厚書扔了。不是因?yàn)樗鼪]用而是我找到了更適合入門的方式先用一個(gè)具體項(xiàng)目建立全貌讓大腦知道“這么做是可以跑起來、可以解決問題的”之后再回頭看概念就快很多了。1.4 速成課的隱性代價(jià)我也買過市面上那種連續(xù)打卡的學(xué)習(xí)課程每天跟著視頻敲一小段代碼還有助教答疑體驗(yàn)確實(shí)順滑。但順滑恰恰是問題所在。那種課程里所有的坑都被填平了所有代碼都是對(duì)的所有步驟都是驗(yàn)證過的你很難體驗(yàn)到真實(shí)的報(bào)錯(cuò)現(xiàn)場。等你離開課程面對(duì)一個(gè)完全沒有配好的環(huán)境、一個(gè)全新的需求你沒有經(jīng)歷過從零到一的那段掙扎根本不知道從哪里下手。當(dāng)然速成課可以用于建立初期的信心讓人感覺自己“能學(xué)會(huì)”這是它存在的價(jià)值。但如果你把它當(dāng)成能力建設(shè)的主要路徑那大概率會(huì)在遇到第一個(gè)真實(shí)場景時(shí)徹底卡住。學(xué)習(xí)的真相是必須有某個(gè)階段是難以下手的、經(jīng)常報(bào)錯(cuò)的、需要反復(fù)查資料的這個(gè)階段不能跳跳過了就補(bǔ)不回來。真正有效的學(xué)習(xí)一定發(fā)生在親手解決現(xiàn)場問題的過程中。2. 設(shè)計(jì)一條“夠得著”的學(xué)習(xí)路徑而不是收藏一堆教程2.1 用目標(biāo)倒推學(xué)習(xí)內(nèi)容學(xué)了一個(gè)多月后我遇到的一個(gè)新問題知識(shí)點(diǎn)太多了這個(gè)也想看那個(gè)也想學(xué)。一會(huì)兒覺得數(shù)據(jù)分析很酷一會(huì)兒又覺得爬蟲很神奇再過兩天又聽說后端開發(fā)的錢多。這種狀態(tài)下最容易被各種“路線圖”帶著走。后來我做了個(gè)特別簡單的調(diào)整先寫清楚自己半年后想解決什么問題。我在一張紙上列了三件事自動(dòng)化處理Excel報(bào)表從公開網(wǎng)頁上抓取需要的數(shù)據(jù)能讀懂別人寫的Python代碼。目標(biāo)一旦寫下來學(xué)習(xí)的邊界就清晰了。我的所有學(xué)習(xí)就圍繞這三件事展開別的一概不碰。比如前端開發(fā)、游戲開發(fā)的內(nèi)容再有趣也跟我沒有關(guān)系等我先把這三個(gè)目標(biāo)達(dá)成再說。這里有個(gè)容易被忽略的點(diǎn)不同目標(biāo)對(duì)應(yīng)的學(xué)習(xí)路徑差異非常大。想做數(shù)據(jù)分析的人重點(diǎn)應(yīng)該放在pandas、數(shù)據(jù)處理、可視化這些模塊上想寫Web后端的人重點(diǎn)就是HTTP協(xié)議、框架路由、數(shù)據(jù)庫操作而我想做的事偏自動(dòng)化處理那核心就是文件讀寫、字符串處理、正則表達(dá)式和爬蟲基礎(chǔ)。目標(biāo)不清晰的時(shí)候人的第一反應(yīng)是“什么都想要”最后什么都沒學(xué)好。2.2 我的資源篩選原則與淘汰方法這半年里我收藏過的教程、文章、課程合計(jì)超過四十個(gè)最后真正看完的可能只有十分之一。我總結(jié)出了一套資源篩選原則可以用來判斷什么東西值得投入時(shí)間資源類型我的處理方式原因帶完整代碼倉庫的視頻教程值得看可以邊看邊敲有反饋閉環(huán)沒有代碼倉庫的視頻教程先收藏不看很容易變成“看熱鬧”操作跟不上前兩章沒有代碼示例的書籍跳過抽象概念堆砌沒有反饋閉環(huán)問題導(dǎo)向的博客/帖子遇到問題才查帶著問題去看記得最牢大而全的路線圖/課程大綱只用來查缺補(bǔ)漏不適合當(dāng)主線學(xué)習(xí)容易只見樹木不見森林核心原則是資源是地圖不是路線。真正的主線應(yīng)該是你手里那個(gè)具體的目標(biāo)和項(xiàng)目所有學(xué)習(xí)資源都圍繞它來取用。遇到一個(gè)報(bào)錯(cuò)去搜索解決方案得到的文章哪怕不完整因?yàn)樗鼛湍憬鉀Q了當(dāng)下的問題它的價(jià)值反而遠(yuǎn)高于那些“系統(tǒng)全面”的教程。2.3 把學(xué)習(xí)時(shí)間切成“塊”而不是“條”我前期還有一個(gè)明顯的失敗試圖用每天十五分鐘的碎片時(shí)間去學(xué)編程。碎片時(shí)間聽知識(shí)類播客、看教學(xué)短視頻看起來每天都在“接觸”編程但實(shí)際效果約等于零。學(xué)編程和學(xué)歷史不一樣它需要連續(xù)的注意力來進(jìn)入狀態(tài)、處理報(bào)錯(cuò)、完成一個(gè)完整的邏輯閉環(huán)。十五分鐘剛進(jìn)入狀態(tài)就斷了下次接著來又要重新過一遍上下文。這種損耗日積月累下來非常驚人。后來我把時(shí)間重新設(shè)計(jì)了一下效果立刻好轉(zhuǎn)。工作日選兩個(gè)晚上每次至少一個(gè)半小時(shí)周末抽一個(gè)完整的上午大概三小時(shí)用于寫項(xiàng)目。時(shí)間總量并沒有增加多少但學(xué)習(xí)方式發(fā)生了本質(zhì)變化。晚上一段完整時(shí)間可以專注學(xué)一個(gè)新語法、做一個(gè)完整的小練習(xí)周末的上午可以連續(xù)調(diào)試一兩個(gè)小時(shí)的代碼處理項(xiàng)目里真正棘手的問題。固定時(shí)間段帶來的另一個(gè)好處是“心理啟動(dòng)成本”大大降低。因?yàn)槊刻旃潭ǖ臅r(shí)間點(diǎn)開始學(xué)大腦會(huì)形成一種類似條件反射的專注狀態(tài)打開編輯器的那一下不會(huì)覺得痛苦不像以前那樣每次都要磨蹭半天。2.4 三個(gè)月的可測量里程碑沒有里程碑的學(xué)習(xí)會(huì)陷入“好像一直在學(xué)但不知道自己到底學(xué)會(huì)了沒有”的泥潭。我給自己設(shè)了三道檢驗(yàn)關(guān)第一個(gè)月結(jié)束不看任何參考獨(dú)立寫出一個(gè)腳本讀取一個(gè)文本文件提取里面所有的郵箱地址去重后輸出到新文件。第二個(gè)月結(jié)束實(shí)現(xiàn)一個(gè)簡單的定時(shí)爬蟲每天定時(shí)從公開網(wǎng)頁抓取指定數(shù)據(jù)寫入Excel并自動(dòng)發(fā)送一封包含摘要的郵件。第三個(gè)月結(jié)束不依賴參考代碼獨(dú)立設(shè)計(jì)一個(gè)小工具的完整邏輯并實(shí)現(xiàn)出來供真實(shí)工作場景使用。這個(gè)做法最大的價(jià)值是它把模糊的“學(xué)會(huì)”變成了可驗(yàn)證的“能寫出什么”。每過關(guān)一次對(duì)自己的信心就增加一分。過不了關(guān)就重新回去補(bǔ)基礎(chǔ)。這個(gè)方法我一直用到現(xiàn)在每次學(xué)新東西都會(huì)先想清楚什么產(chǎn)物能證明我學(xué)會(huì)了而不是說“我看了多少小時(shí)的課所以我覺得我在進(jìn)步”。3. 前兩個(gè)月的“低效期”我踩過的三個(gè)典型坑3.1 收藏夾越來越滿能力卻沒有提升這是我最后悔的一個(gè)階段。每天花大量時(shí)間刷技術(shù)網(wǎng)站看到一個(gè)“Selenium爬蟲實(shí)戰(zhàn)”覺得好收藏看到一篇“Pandas性能優(yōu)化指南”覺得有用收藏看到“100個(gè)Python面試題”覺得早晚用得上收藏。一個(gè)多月過去收藏夾里積累了四十多篇教程但我親手寫完的練習(xí)屈指可數(shù)。而且我發(fā)現(xiàn)自己有一個(gè)荒謬的心理機(jī)制收藏的動(dòng)作會(huì)產(chǎn)生一種“我已經(jīng)掌握了”的錯(cuò)覺。收藏得越多心里越覺得自己在學(xué)習(xí)但實(shí)際上只是把知識(shí)從一個(gè)位置搬到了另一個(gè)位置收進(jìn)收藏夾里的內(nèi)容我后來甚至一次都沒打開過。意識(shí)到這個(gè)問題之后我給自己立了一條特別簡單的鐵律收藏一篇新教程之前必須先把上一篇收藏里的練習(xí)做完。做不完就不能收藏新的。這條規(guī)則執(zhí)行起來效果明顯直接斷掉了“囤積式學(xué)習(xí)”的毛病。后來我還順手清理了收藏夾把百分之八十的內(nèi)容刪掉了。留下來的只有那些我真實(shí)用到過、解決問題時(shí)幫上忙的文章。學(xué)編程真的不需要那么多“資料”需要的是把一個(gè)東西吃透。3.2 筆記做得像藝術(shù)品知識(shí)還是別人的第二個(gè)坑比收藏還隱蔽做筆記上癮。我一度把筆記軟件當(dāng)成了創(chuàng)作現(xiàn)場。每天學(xué)完后開始整理筆記給關(guān)鍵概念涂上顏色加上漂亮的標(biāo)題貼幾張截圖還要把代碼段折疊起來。整理完心里特別滿足覺得自己把知識(shí)“沉底”了。但實(shí)際上那次整理筆記的整個(gè)過程我一直處于一種“搬運(yùn)”的狀態(tài)。我搬的是別人書里的結(jié)構(gòu)抄的是別人博客上的結(jié)論并沒有形成一個(gè)屬于自己的認(rèn)知框架。結(jié)果是筆記打開過好幾遍每次看都覺得好看但脫離筆記之后照樣寫不出代碼來。后來我把自己解放了出來。筆記用途收縮成三類第一類報(bào)錯(cuò)信息及其解決方案方便以后再遇到同樣問題時(shí)的快速檢索第二類反復(fù)要查的語法結(jié)構(gòu)比如某個(gè)庫的常用函數(shù)簽名不占用我腦子了放進(jìn)筆記里當(dāng)接口字典第三類項(xiàng)目復(fù)盤時(shí)發(fā)現(xiàn)的問題清單和解決思路。明確了筆記的三類用途后做筆記的時(shí)間直接砍掉了一半還多學(xué)習(xí)效率成倍上升。寫在這里是想提醒大家你需要的不是“好看的學(xué)習(xí)筆記”而是一個(gè)能在關(guān)鍵時(shí)刻幫上忙的知識(shí)索引。3.3 做完練習(xí)不復(fù)盤等于白做第三個(gè)坑是“做完就翻篇”。跟著教程敲完一段代碼運(yùn)行通過了就覺得自己“會(huì)了”。但時(shí)間一長就發(fā)現(xiàn)那些練習(xí)做完之后半個(gè)月再讓我寫一遍我根本寫不出來。原因很簡單跟著教程敲的時(shí)候代碼邏輯是別人鋪好的我只需要按圖施工不需要自己設(shè)計(jì)路徑。這種程度的練習(xí)在認(rèn)知科學(xué)里屬于“被動(dòng)追隨”對(duì)于培養(yǎng)獨(dú)立解決問題的能力作用非常有限。我后來引入了“延遲重寫”的復(fù)盤方法一個(gè)練習(xí)做完了、跑通了之后合上參考資料把代碼刪掉在干凈的編輯器里憑記憶重新寫一遍。寫不出來就看看哪里卡住了針對(duì)性地去查那部分知識(shí)然后隔天再重寫一次。這個(gè)過程堅(jiān)持下來知識(shí)點(diǎn)不再是浮在表面上的“眼熟”而是真正長成了自己的技能。尤其是“第二天重寫”這個(gè)動(dòng)作看起來簡單實(shí)際效果極其驚人。因?yàn)楦袅艘惶於唐谟洃浺呀?jīng)消退了一些這時(shí)候還能寫出來說明它進(jìn)入了長期記憶。4. 項(xiàng)目驅(qū)動(dòng)的上升期從“會(huì)寫”到“能用”的關(guān)鍵轉(zhuǎn)折4.1 我的第一個(gè)真實(shí)項(xiàng)目部門周報(bào)自動(dòng)匯總工具第三個(gè)月的時(shí)候我決定做第一個(gè)真實(shí)項(xiàng)目把部門每周都要人工匯總的周報(bào)數(shù)據(jù)自動(dòng)化成一張統(tǒng)計(jì)表。我當(dāng)時(shí)的想法很簡單每周五要花一兩個(gè)小時(shí)去手動(dòng)匯總十幾份周報(bào)如果這個(gè)活兒能讓腳本去做就能省下不少時(shí)間。但當(dāng)真動(dòng)手的時(shí)候我傻眼了。這個(gè)需求表面上看起來很簡單拆開之后卻是另外一番景象。周報(bào)的數(shù)據(jù)格式不統(tǒng)一有的人寫的是Excel表格有的人貼的是網(wǎng)頁系統(tǒng)里的截圖和數(shù)據(jù)數(shù)據(jù)分散在不同的文件里有一些還需要從內(nèi)部網(wǎng)頁爬取匯總的時(shí)候還要按多個(gè)維度統(tǒng)計(jì)比如按團(tuán)隊(duì)、按任務(wù)類型、按完成狀態(tài)。面對(duì)這個(gè)問題我的第一反應(yīng)就是“這筆復(fù)雜的程度超出我目前的能力不太可能完成”。事實(shí)上我也確實(shí)差點(diǎn)放棄了。轉(zhuǎn)折點(diǎn)出現(xiàn)在一個(gè)特別笨的地方我把這個(gè)看起來龐大的項(xiàng)目拆解成了三個(gè)獨(dú)立的小任務(wù)。第一個(gè)小任務(wù)寫一個(gè)腳本讀取指定文件夾里的Excel文件把每個(gè)文件里的關(guān)鍵列提取出來。第二個(gè)小任務(wù)寫一個(gè)腳本從一個(gè)內(nèi)部網(wǎng)頁上抓取指定區(qū)域的表格數(shù)據(jù)。第三個(gè)小任務(wù)把兩部分?jǐn)?shù)據(jù)合并按條件進(jìn)行匯總統(tǒng)計(jì)。三個(gè)任務(wù)各自獨(dú)立互不依賴。我先分別完成這三個(gè)獨(dú)立的腳本最后再用一個(gè)主腳本把三個(gè)步驟串起來。這個(gè)拆解動(dòng)作做完那個(gè)讓我想放棄的大項(xiàng)目變成了三個(gè)我可以逐個(gè)擊破的小關(guān)卡。4.2 排錯(cuò)的標(biāo)準(zhǔn)鏈路完整報(bào)錯(cuò)信息是關(guān)鍵項(xiàng)目開發(fā)期間遇到報(bào)錯(cuò)的頻率比練習(xí)階段高出一個(gè)量級(jí)。這里我梳理一下自己踩過的上萬次報(bào)錯(cuò)后總結(jié)出來的標(biāo)準(zhǔn)排查鏈路也是我后來推薦給所有新手的路徑第一步復(fù)制完整的報(bào)錯(cuò)信息和堆棧跟蹤而不是只看最后一行。新人最容易犯的錯(cuò)是看到“Error”就開始慌張但其實(shí)報(bào)錯(cuò)里最有價(jià)值的信息往往在中間部分——它告訴你在哪個(gè)文件的哪一行觸發(fā)、調(diào)用了哪個(gè)函數(shù)、經(jīng)過了哪條調(diào)用路徑。第二步把完整的報(bào)錯(cuò)信息直接粘貼到搜索引擎里搜索注意要用原文里的關(guān)鍵字而不是自己意譯出來的關(guān)鍵詞。第三步找到解決方案后別急著照抄先回看自己的代碼搞清楚這個(gè)報(bào)錯(cuò)到底是因?yàn)槭裁匆鸬氖穷愋筒粚?duì)、參數(shù)缺失還是變量未定義自己代碼的哪一行對(duì)應(yīng)報(bào)錯(cuò)的哪一部分。第四步修改完代碼后重跑一遍完整流程確認(rèn)沒有引入新的問題。舉一個(gè)當(dāng)時(shí)的具體案例我在合并多個(gè)Excel文件時(shí)遇到了一個(gè)“KeyError”。報(bào)錯(cuò)信息只提示了一個(gè)字段名稱不存在。如果我只看最后一行就完了但按照鏈路去定位發(fā)現(xiàn)是因?yàn)椴煌珽xcel里這個(gè)字段的名字不完全一致有的表叫“負(fù)責(zé)人”有的表叫“提交人”有的表叫“姓名”。最終用戶需要統(tǒng)一我在匯總腳本里加了一步字段名映射的預(yù)處理。整個(gè)過程不算復(fù)雜但沒有標(biāo)準(zhǔn)排查鏈路的話很容易在錯(cuò)誤的地方反復(fù)橫跳。4.3 一個(gè)典型的“不報(bào)錯(cuò)但結(jié)果錯(cuò)”編碼問題的排查還有一種問題比報(bào)錯(cuò)更磨人程序運(yùn)行順利每一步都沒有報(bào)錯(cuò)但結(jié)果就是不對(duì)。印象最深的是爬取網(wǎng)頁數(shù)據(jù)寫入Excel后所有中文都變成了亂碼。第一次遇到這個(gè)問題我對(duì)著屏幕盯了差不多一個(gè)小時(shí)完全找不到錯(cuò)誤在哪里因?yàn)榇a明明沒有報(bào)錯(cuò)。后來我才搞清楚問題出在編碼格式的一致性和解碼方式不統(tǒng)一。網(wǎng)頁返回的內(nèi)容是使用UTF-8編碼的而我當(dāng)時(shí)使用的Excel寫入組件默認(rèn)的不是UTF-8編碼格式數(shù)據(jù)從讀取到寫入的過程中發(fā)生了不一致的轉(zhuǎn)換于是中文就成了亂碼。這類問題的排查思路和報(bào)錯(cuò)信息類的問題完全不同。它的難點(diǎn)在于系統(tǒng)沒有告訴你錯(cuò)在哪一步因?yàn)槊恳徊蕉肌俺晒Α绷恕N业膽?yīng)對(duì)方法是分段打印中間結(jié)果從數(shù)據(jù)流的入口開始每經(jīng)過一個(gè)處理步驟就把結(jié)果輸出到控制臺(tái)看一遍逐步縮小范圍。這個(gè)過程中我最終定位到了編碼轉(zhuǎn)換的那一步然后把讀取和寫入兩端的編碼格式統(tǒng)一問題就消失了。這個(gè)教訓(xùn)帶給我的習(xí)慣延續(xù)到了現(xiàn)在所有跟數(shù)據(jù)文件打交道的腳本編碼轉(zhuǎn)換的代碼永遠(yuǎn)集中寫在一起并且用注釋標(biāo)注清楚當(dāng)前數(shù)據(jù)是什么編碼、目標(biāo)是什么編碼避免下次再犯同樣的錯(cuò)。5. 刻意練習(xí)怎么安排每周固定的實(shí)操節(jié)奏5.1 每周固定時(shí)間表學(xué)習(xí)、練習(xí)、項(xiàng)目、復(fù)盤互相配合進(jìn)入項(xiàng)目階段之后我對(duì)時(shí)間的安排變得更加精細(xì)。不再像初期那樣“今晚有空就學(xué)一下沒空就算了”而是固定了一套每周循環(huán)周一晚上用于學(xué)習(xí)一個(gè)新知識(shí)點(diǎn)內(nèi)容是語法或某個(gè)庫的一個(gè)模塊時(shí)間控制在90分鐘以“了解用法、看透文檔、跑通一個(gè)小示例”為目標(biāo)。周二晚上用于刻意練習(xí)圍繞周一學(xué)的知識(shí)點(diǎn)在無參考、無提示的情況下獨(dú)立寫出一個(gè)小程序時(shí)間也是90分鐘。周四晚上用于推進(jìn)真實(shí)項(xiàng)目時(shí)間120分鐘只做一個(gè)項(xiàng)目里明確的子任務(wù)而不是漫無目的地改來改去。周末上午專門留出三小時(shí)做項(xiàng)目復(fù)盤回顧這一周在這個(gè)項(xiàng)目里做了哪些決定、遇到了哪些問題、哪些地方可以做得更高效。這個(gè)節(jié)奏最大的好處是每個(gè)晚上都有不同的任務(wù)不會(huì)被某一種形式的任務(wù)搞得厭倦。學(xué)新知識(shí)的時(shí)候是輸入做練習(xí)的時(shí)候是輸出推項(xiàng)目的時(shí)候是綜合應(yīng)用復(fù)盤的時(shí)候是抽象和沉淀。四者互相加強(qiáng)形成了一條比較完整的學(xué)習(xí)鏈。5.2 練習(xí)設(shè)計(jì)的四個(gè)原則練習(xí)的方式直接決定了學(xué)習(xí)效果。我經(jīng)歷了初期“看視頻做練習(xí)”的低效之后總結(jié)出四個(gè)設(shè)計(jì)原則適用于所有以動(dòng)手為主的技能訓(xùn)練第一每次練習(xí)只針對(duì)一個(gè)技能點(diǎn)。不要在一個(gè)練習(xí)里同時(shí)夾帶正則表達(dá)式、文件讀寫、異常處理和爬蟲這樣會(huì)導(dǎo)致每個(gè)點(diǎn)都練不透。第二練習(xí)難度保持在“伸手夠一下”的范圍內(nèi)。難度太低沒有提升太高則會(huì)帶來嚴(yán)重的挫敗感。這個(gè)最佳難度區(qū)間通俗地說就是你覺得自己大概率做得出但又有一些不確定的地方。第三做練習(xí)時(shí)不看任何參考資料。整個(gè)過程可以查報(bào)錯(cuò)、查文檔但絕不能打開參考代碼要讓大腦從一開始就要規(guī)劃整個(gè)程序的邏輯結(jié)構(gòu)。第四練習(xí)完成后必須隔天重寫一遍。這是鞏固效果的關(guān)鍵前面提到過但在這里再強(qiáng)調(diào)一次也不為過。我前期吃過很多苦頭正是因?yàn)樨澬?。希望練?xí)題目不要有挑戰(zhàn)性也希望練習(xí)的時(shí)候能參考代碼。后來嚴(yán)格執(zhí)行這四個(gè)原則之后練習(xí)的質(zhì)量明顯提高了做完一次練習(xí)的踏實(shí)感遠(yuǎn)超以前做個(gè)十次“跟著敲”。5.3 難度分階抄→變→造練習(xí)難度需要和當(dāng)前階段匹配。我把練習(xí)分成了三個(gè)難度等級(jí)第一級(jí)叫“抄”。目標(biāo)是讓代碼正確運(yùn)行適合入門期的零基礎(chǔ)學(xué)習(xí)者。抄的重點(diǎn)是理解別人代碼的每一個(gè)步驟搞清楚每一行的作用。第二級(jí)叫“變”。把參考代碼改造成一個(gè)新功能比如把別人寫的天氣查詢腳本改成抓取新聞標(biāo)題。這一級(jí)的重點(diǎn)是“改造”這個(gè)過程讓人必須理解原代碼的邏輯否則改不動(dòng)。第三級(jí)叫“造”。從零開始獨(dú)立設(shè)計(jì)并實(shí)現(xiàn)一個(gè)小工具只提需求不管實(shí)現(xiàn)方式。這一級(jí)最接近真實(shí)工作場景是上升期的關(guān)鍵。每個(gè)階段的切換時(shí)機(jī)也很重要。我個(gè)人的標(biāo)準(zhǔn)是連續(xù)三次練習(xí)都能在不看參考資料的情況下完成就可以進(jìn)入下一級(jí)。如果你做“變”級(jí)練習(xí)的時(shí)候每次都要翻原代碼那就說明還沒到“造”的時(shí)候。尊重節(jié)奏比盲目挑戰(zhàn)自己更重要。6. 半年復(fù)盤技術(shù)之外的收獲同樣值得記錄6.1 用數(shù)據(jù)說話這半年到底投入了多少、產(chǎn)出了什么復(fù)盤不能靠感覺得靠數(shù)據(jù)。我從開始學(xué)編程的第一天就建了一個(gè)表格記錄每天的學(xué)習(xí)時(shí)間、學(xué)習(xí)內(nèi)容和產(chǎn)出物。半年后統(tǒng)計(jì)出來的結(jié)果是一條比較樸素但真實(shí)的曲線。累計(jì)投入大約是210個(gè)小時(shí)平均到半年每周大約是八個(gè)小時(shí)出頭。產(chǎn)出是三個(gè)完整的小項(xiàng)目、四十多個(gè)練習(xí)腳本以及一個(gè)能穩(wěn)定運(yùn)行的內(nèi)部數(shù)據(jù)處理工具。這個(gè)投入產(chǎn)出比高嗎說實(shí)話不算高效。對(duì)一個(gè)白天全職上班的人來說210個(gè)小時(shí)要擠出來的代價(jià)很大。晚上推掉了很多應(yīng)酬周末減少了很多娛樂。但另一個(gè)角度來看每周八小時(shí)的投入換來了一個(gè)可以反復(fù)使用、幫團(tuán)隊(duì)省下大量重復(fù)勞動(dòng)的小工具這筆賬算下來其實(shí)是值得的。更重要的是在學(xué)會(huì)這個(gè)工具的過程中我掌握了一套真正屬于自己的學(xué)習(xí)和解決問題的方法這個(gè)能力是可以遷移到任何領(lǐng)域的。6.2 比代碼更重要的三個(gè)改變技術(shù)上的進(jìn)步反而是最好量化的部分。我更想說的是這半年學(xué)習(xí)經(jīng)歷帶給我的一些更深層的變化。第一個(gè)改變是我學(xué)會(huì)了和挫敗感共處。剛開始經(jīng)常被一個(gè)報(bào)錯(cuò)折磨一兩個(gè)小時(shí)那種感覺特別容易讓人自我懷疑。后來我逐漸建立起一種信念“不會(huì)”和“暫時(shí)沒找到思路”是兩回事。報(bào)錯(cuò)永遠(yuǎn)有原因只是我暫時(shí)沒有找到。只要我在排查就一定會(huì)找到。這種信念一旦建立面對(duì)問題的焦慮感就少了大半。第二個(gè)改變是我養(yǎng)成了“最小可行行動(dòng)”的習(xí)慣。遇到任何復(fù)雜的任務(wù)以前我的第一反應(yīng)是想一下整體有多大、然后迎面跟它硬碰硬?,F(xiàn)在不一樣我會(huì)下意識(shí)地做一個(gè)動(dòng)作把它拆成最小的可操作步驟然后從第一個(gè)步驟開始動(dòng)手。這個(gè)習(xí)慣后來被我用到了日常工作里處理很多非技術(shù)的問題也明顯更加從容。第三個(gè)改變是我重新理解了學(xué)習(xí)本身。以前我一直認(rèn)為學(xué)習(xí)就是輸入更多信息、看更多書、聽更多課、記更多筆記。但這半年讓我清楚地意識(shí)到真正有效的學(xué)習(xí)永遠(yuǎn)發(fā)生在動(dòng)手解決現(xiàn)場問題的過程中。收藏、筆記、觀看、閱讀都是信息的搬運(yùn)只有動(dòng)手寫、動(dòng)手改、動(dòng)手調(diào)試知識(shí)才會(huì)在腦子里重新生長一遍。6.3 一些寫給同樣想開始的人的實(shí)用建議作為這個(gè)系列的收尾這里分享幾條我個(gè)人認(rèn)為最值得堅(jiān)持的建議。起步階段不要選擇“系統(tǒng)學(xué)習(xí)”作為起點(diǎn)選擇一個(gè)小而真實(shí)的任務(wù)當(dāng)切入點(diǎn)。最簡單的判斷標(biāo)準(zhǔn)是這個(gè)任務(wù)是不是你自己會(huì)從中受益的如果你學(xué)了能幫自己省時(shí)間那么驅(qū)動(dòng)你堅(jiān)持下去的力量就會(huì)強(qiáng)很多。固定每周的學(xué)習(xí)時(shí)間而不是每天“有空就學(xué)”。穩(wěn)定節(jié)奏比一時(shí)熱情重要得多人的意志力是有限資源不要靠意志力維持學(xué)習(xí)習(xí)慣要靠結(jié)構(gòu)和固定的時(shí)間表。遇到問題先搜索搜不到就休息一下再回來不要硬扛。硬扛三個(gè)小時(shí)解決不了的問題隔天再看很可能半小時(shí)就解決了。最后也是最重要的一條不要收藏完就停止。學(xué)習(xí)的成就感不來自于“我擁有了一篇好教程”而來自于“我的代碼終于跑通了”的那個(gè)瞬間。那個(gè)瞬間才是真正喂養(yǎng)動(dòng)力的來源。這篇就先寫到這里下一篇文章我想重點(diǎn)復(fù)盤后半段“如何從半自動(dòng)腳本走向一個(gè)真正可維護(hù)的工具”包括代碼組織、測試和版本管理那些東西等回頭整理好了再繼續(xù)寫。