1. 程式人生 > >刻意練習的三種思維方式——Phodal

刻意練習的三種思維方式——Phodal

作者:Phodal,工作三年,著有《自己動手設計物聯網》、《全棧應用開發:精益實踐》。 作為技術專家審閱了《Angular 2 Services》、《Smart IoT》等四本外語書。 在 GitHub 開源有《Growth:全棧增長工程師指南》等七本電子書,並譯有《物聯網實戰指南》。

一、如何通過練習來提高

學習新框架的最好姿勢是:基於現有的業務來學習。即從工作中學習,從實踐中學。但是,如果一直只使用新的框架來重寫舊的業務,成長也會趨近於0。第一次,使用新框架時收穫可能頗豐;第二次,收穫的東西更少;第三次,你可能已經學不到東西。

因此,在業餘的練習時間裡,不要一直練習新的框架,不要再拿 Vue、React Native 去高仿一些應用。當且僅當,你所處的專案正在使用新的框架,這種練習才是有意義的。

經過上面的練習,提高了工作效率。但要成為更加專業的程式設計師,還需要提高頂層的能力。下面介紹一些,比較有效的提升方法:

  • 閱讀開源軟體與重構程式碼。

  • 造自己的輪子來重寫應用。

  • 結合設計模式。

  • 引入其它領域的思想。

總的來說,收穫還是蠻多的,特別是造輪子,能有更大的提升。與其他的練習稍有不同的是,因為涉及到程式碼設計,這裡的練習有些難以衡量。這時,我們應該是保持著練習的心態,並意識到我們是在做這方面的練習。

1.閱讀開源軟體與重構程式碼

如果在工作環境中,沒有程式碼寫得比較好的人,那就只能從開原始碼中去學習。這裡,我建議閱讀開源軟體程式碼的方式是:

  • clone 某個專案的程式碼到本地。

  • 檢視這個專案的 release 列表。

  • 找到一個看得懂的 release 版本,如1.0或者更早的版本。

  • 讀懂上一個版本的程式碼。

  • 向後閱讀大版本的原始碼。

  • 讀最新的原始碼。

可只讀這些程式碼,不能讓我們的水平顯著提高,應該結合“重構”這個技能來練習。從我的練習經驗看來,對於重構的練習是最有意思的。我們可以見證,一段不好的程式碼在我們的調教之下,煥發出新的光彩。當重構一段壞味道的程式碼,對比重構前後的程式碼,會發現自己竟然有這樣的潛力。

如果找不到合適的練習專案,可以到 GitHub 上找一些 star 多,但是沒有測試、缺少 CI 等的專案練習,這樣的專案在 GitHub 上也是蠻多的。

有一次,我在尋找一個迷你的 Markdown 解析器,看到 GitHub 有一個精巧的實現。它有 100+ 的 star,但是沒有測試、四百行的程式碼裡,有一個方法有三百多行等的壞味道。於是,便花了幾天的時間,邊思考邊重構這個專案。這樣對編碼的提升比較大,因為工作的時候,完成任務是第一優先順序,然後才是質量。

因此,對於練習來說,我們只需要:

  • 找一個不錯的開源庫。

  • 閱讀其中的程式碼。

  • 找到程式碼中設計不好的地方。

  • 自己認為設計得不好的程式碼重構。

  • 結合《重構》一書,來改進設計。

需要注意的是:不同的人對於程式碼設計,有著不同的觀點。如果因為程式碼的設計不好,而不是程式碼裡有各種壞味道(code smell),那麼,就不應該去給別人的程式碼提 Pull Request。

2.造自己的輪子來重寫應用

與閱讀程式碼、重構相比,造一個自己的輪子,來實現同樣的功能,便是一個更不錯的選擇。在 Web 開發領域,大部分的開發框架本身都是『通用型』的框架。即它擁有相當多的功能,其中有很多的功能都不會用到。如你使用 jQuery 的時候,你可能只會使用到其中的 Ajax、Event 等功能,那麼你就可以寫一個新的框架,相容這兩個介面。

練習時間充裕的時候,便可以自己動手去做一個。上面說到的閱讀框架程式碼,是一種好的方法。除此無論是前端還是後端,我們都可以找到從零建立框架的資料,來幫助我們理解框架的組成。

通過閱讀諸如 Python 裡的 Flask、 Ruby 裡的 Sinatra 等輕量級的框架,我們就能理解一個框架所需要的元素,並模仿他們做出一個新的系統。這些框架的關注點是:處理 HTTP 請求的 CGI、與資料庫互動的 ORM、控制邏輯的 Controller 層、返回 HTML 的 View 層等。除了相關的框架,我們還能在 GitHub 上看到很多人模仿這些框架。做一個這樣的後臺框架,搭建自己的部落格,就可以理解好這一系列的邏輯了。

對於前端來說,也是類似的,諸如 Building React From Scratch,可以讓我們在 250 行理解 React 的原理,並做出一個類似的框架。除了 MVC,還有模組化設計、資料請求等的內容。在兩三年前,《JavaScript 框架設計》就是這方面一個不錯的選擇。

我曾經造過一個名為 Lettuce 的前端框架,它的主要目的就是用於:學習前端框架的設計,可以在自己的多個業餘專案上使用這個框架。而在前端領域,定製自己的 UI 框架、CSS 框架也是一個不錯的選擇。再用到自己的部落格上,寫上『自豪地採用xx框架』,豈不是更加的自豪?

在底層領域,又有各式各樣的《自制作業系統》、《自制程式語言》、《自己動手設計物聯網》的書籍,它們都能讓我們從底層去理解一個系統的組成。除此,還有各種各樣的剖析類書籍,可以讓我們理解底層機制的同時,還能製作出一個框架。

最後,我們只需要能不改寫或少數改寫程式碼,將我們的應用執行在上面,便是成功的仿造了一個輪子。

3.結合設計模式

設計模式,不同的人有不同的看法。在我看來,一個優秀的程式是要能“看懂”的。即不一定要精通,但要能識別出來,它是一種設計模式。當我們看到了一次又一次的相似設計時,應該猜想到,其背後應該是一種設計模式。例如,在前端開發框架中的“雙向繫結”,它實際上就是釋出-訂閱模式,又或者稱觀察者模式的一種實現。

在筆者看來,模式就是一種高階的語言。當別人一說“工廠模式”,多數人瞬間就明白了,不猶得會發出:原來如此,這樣的感嘆。認識了一些模式後,遇到特定的場景,我們就能一下子套用這種模式。

可只憑閱讀 GoF 的《設計模式》一書,又或者《Head First 設計模式》、《重構與模式》等設計模式書籍,我們所學的知識便是有限的。我們要做的是:

  • 先熟悉書本上的示例程式碼,來對不同的設計模式有一個大的瞭解。

  • 識別日常程式碼中的設計模式。

  • 練習這些設計模式,並掌握常見的設計模式。

  • 嘗試在日常的程式碼中,套用設計模式。

  • 重構現有的程式碼到設計模式。

要對設計模式進行練習,不是一件容易的事。在模稜兩可時,即適合使用 A 模式,又適合使用 B 模式的情況下。可能是為設計而設計,因此要儘可能貼近現有情況。

4.引入其它領域的思想

不同的領域裡,都有自己領域的優秀思想。比如我們熟知的設計模式,便是受建築領域的《建築的永恆之道》中描述的 253 個建築模式的啟發。又如今天流行的精益思想,最早是來自汽車製造業,可它對軟體行來說,有著令人受益匪淺的啟發。好的框架、軟體是會相互學習,如 iPhone 與 Android,都在不斷地借鑑——通知中心,但是又在那之上做一些改進。

又比如,今天的前端框架裡,很多思想都是從後端“借鑑”過來的。如 Angular 中採用的依賴注入,便是深受 Java 語言的影響。近一點來說,Redux,框架最初是用在 React 上,但是它已經被推廣到了 React 和 Vue.js 上。

因此,當我們發現一個新的優秀思想產生時,便可以嘗試引入到自己的領域裡。又或者我們所處的領域,正遇到一些難題,答案可能就在別的領域裡。但在這方面的練習,往往都是一些創新性的練習。多數時候,我們的探索可能沒有結果,但對自己可能有很大啟發。

二、找到合適的時間練習

每天能有半小時、一小時甚至更長時間的穩定練習,比三天打魚兩天晒網的效果要好得多。清理出一些固定的時間,用來提高自己。

如果不能的話,那麼我們也可以嘗試去擠出一些時間,如從上下班的通勤時間。即使是同一公司,不同的人都有不同的上下班時間,所花費在路上的時間也有所不同。有的人,需要在幾環外坐個一個多小時的地鐵,再轉公交才能到公司;有的人,只需要出門左轉,走個十分鐘就到公司了。因為在路上花費的時間不同,也在一定程度上影響了學習、練習的時間。

因此,如果可能的話,應該減少花費在上班路上的時間,才能避免繼續陷入這樣一個惡性迴圈:租不起近的房子,花費大量的時間在路上,沒有時間提升技能。

早上

早上的練習,是一種慢慢進入一天工作狀態的感覺。一旦上班時間到來的時候,就已經進入工作姿態了。對於“資本家”來說,可謂好事一件。早晨剛醒來,總會想不起昨天專案做到哪一步,便更容易反思哪裡做得有問題。

有時候,可以有半小時的練習時間,將這些時間浪費在夢裡總是有些可惜。同時,提前半個小時到公司,寫一些開源軟體的程式碼,也是個不錯的選擇。

需要注意的是:練習時不要關注時間,重點關注怎樣提高。目標是:讓每天進步一點。

中午

吃完飯後容易犯困。這個時候,身體會妨礙我們進行練習。可如果你的午休時間比較長,就可以做一些練習,再去休息片刻。

碎片時間

對著螢幕寫程式碼,時間一久,集中力就開始渙散,應適當休息會兒。刷刷資訊、朋友圈,又或者收集各種資料,拓展一下視野。接收各種新的知識,擴充套件自己的格局,以便於瞭解整個市場水平。

常見的方式有:

閱讀個人部落格、微信公眾號。

維護自己的 Awesome 列表——尋找自己覺得好的開源專案。

IT 新聞、技術文章聚合網站——我很不喜歡聚合網站,大部分的聚合站點的行為無異於文章抄襲。

GitHub Trending

將這些內容儲存到 Evernote、WunderList、OneNote 等各式各樣的雲筆記裡,然後定期清理、定期清理、定期清理。收集只是一種方式——沒有啥用的方式,因此建議先讀完一遍,再去收藏這樣的文章。多數時候,我們會發現自己收藏了很多內容、買了很多的書,但卻沒有時間讀。

晚上

經歷了漫長的加班,回到住的地方,可能只想睡覺。如果白天沒時間練習,晚上也不能抽出時間練習,長此以往,一年的工作經驗就要分成五年來用了。

晚上練習的時候要注意:在睡覺前 30~60 分鐘停止編碼,否則上床時,腦子裡可能還是這些程式碼,容易失眠。萬一靈感一來,還要爬起來繼續寫。晚睡之前,可以閱讀一些相關或無關書籍、資料。在閱讀的過程中,儘管大腦已經不再思考了,但潛意識還在運轉中,這時很容易抓住一些靈感。

最後,睏倦的時候,就盡情休息吧!

三、怎樣才能持之以恆

在上文裡,我們只談論一些方法和技巧,然而沒什麼用。每個人都知道“一萬小時理論”,但真要堅持下來,很難。

我們需要從娛樂時間裡抽出一部分,原本舒適的玩遊戲、睡覺、刷微博時間,現在要成為另外一種“痛苦”?可是,既然這些“無聊的事情”都能上癮,那麼是不是代表我們還沒有找到合適的路?

1.設定目標與 SMART 原則

練習可以分為:日常固定時間的練習,及針對某一特定主題的練習等多種型別。當我們開始練習某一個具體的技術、框架、模式時,最好能制定一個簡單的練習計劃,如每幾天練習某一內容、多少天內用某一個框架實現什麼功能。

先設計一個小的目標,並且能在短期實現。當發現自己可以輕鬆地堅持下來時,再慢慢的擴大目標,直至我們能做得更好。可是,設定一個練習目標也不是一件簡單的事,需要考量很多。

之前的一個內訓,讓我學到了一個用於制定任務、目標的 SMART 原則:

  • 具體的(Specific)。即我們要有一個明確的目標,如在一週內用 Django 寫一個部落格系統,而不是用 Django 寫個東西。

  • 可度量的(Measurable)。即衡量是否達成目標,我們只需要能建立、檢視、刪除部落格,那麼我們就算完成了這樣的任務。它可以用來不斷地突破自己。

  • 可實現性(Attainable)。即這個目標一定是可以實現的,不能實現的目標沒有啥意義。與此同時,練習初期定下的目標不能困難。

  • 相關性(Relevant)。即目標與其他目標的關聯情況,例如,我們練習 Django 是為了提高 Django 或者後臺的技能。如果我們的大目標是提高前端技能,那麼這個目標對於當前的意義並不是太大。

  • 時限(Time-based)。即時間限制,如上面提到的一週內用 Django 寫一個部落格系統的期限。

經常能在微信朋友圈看到,朋友的 100 天英語閱讀計劃,這樣的目標就是合理的——可實現的、具體的、有時間限制、可度量的。

如果我們想每天固定時間進行練習,那麼我們應該做一個短暫的嘗試,如7天,再慢慢的不斷擴大時間目標,21天、兩個月,隨後再擴大到一個更大的目標。

2.堅持與激勵自己

我們可以使用 GitHub 上的 Contributions 來激勵自己,每一天的痕跡都很明顯,甚至可以拉攏一些小夥伴,與我們一起參加類似的活動。GitHub 本身具有社交屬性,可以讓我們看到別人做了什麼,做了多久。

上文中提到的朋友圈 100 天英語閱讀計劃,也是相似的,它可以讓別人監督你是否完成——前提是,有人一起和你做相同的事,因此可以找個人和你一起練習,相互監督

剛開始練習的時候,練習的內容基本上很充實。時間一長,可能就會陷入一些瓶頸:要麼找不到合適的練習內容,要麼覺得練習過於乏味。這時,可以切換不同型別的練習專案,例如,做一些自己覺得有意思的小專案。又或者,當我們完成一個目標時,給自己一些獎勵,用來鼓舞自己。

alt text