天天都看到不少對編程感興趣的人在問是否是能夠自學軟件開發,或者應該怎麼自學編程才能入門。在這篇文章裏,我將嘗試重現一個初學者在學習計算機編程時可能會碰到的問題,並儘可能提供相應的解決思路,但願對初學者有所幫助。若是你在看完這篇文章後仍是有些疑惑,歡迎點擊 這裏 諮詢我。java
答案是確定的,並且自學是學習軟件編程極其重要的一個途徑。不過最好的方式是自學的同時,有一個能夠幫助解決問題的同事或者老師,這樣能夠避免卡在一個問題上太長時間。數據庫
如今有不少途徑能夠自學,例如IT圖書,或者在線視頻教程,咱們的網站 也提供一些面對初學者的免費的在線互動課程,能夠邊學習邊實踐, 你也能夠嘗試一下:編程
簡單地說,只要具有正常的思惟能力,就能夠學習編程。後端
讓咱們從一個實際的梗來理解這一點:如何把大象裝進冰箱裏?服務器
你也許知道這個搞笑問題的搞笑答案:網絡
這就是編程所須要的最基本的思惟能力:把一個大的問題分解爲若干個小的問題,解決了小的問題,大的問題就解決了,這種分而治之的思考方法是一種至關工程化的思惟,也是科學技術在過去的兩百年裏的統治性思惟。機器學習
回憶一下,你在生活中難道不就是這麼作的嗎?編程實際上就是把生活中常見的思惟活動用編程語言表達出來的一個過程。編程語言
若是把計算機當作一我的,編程語言就是你和計算機對話的語言,你須要用計算機能聽懂的語言才能和計算機對話,就像你須要用當地的語言才能和老外溝通一個道理。函數
不過因爲發明一種新的編程語言的成本至關低,而成就感至關高,所以目前已經出現了太多的編程語言。即有針對娃娃的圖形化編程語言,也有中文的編程語言,更有針對不一樣計算平臺的編程語言,試圖學習全部的編程語言是不明智的,也是毫無必要的,由於編程最重要的是思惟,語言只是向計算機表達你的思惟的一個手段而言。oop
在和計算機溝通時,一次說一句話是比較低效的,由於它會處理的很是快,大量的時間浪費在等待咱們的輸入上。因此一般是寫不少句話一併告訴計算機照着作,這就是咱們常說的計算機程序。例如,對於前面說到的把大象放進冰箱這個任務,能夠編寫以下包含三句話的計算機程序:
openFrigDoor putElephantIntoFrig closeFrigDoor
基本上就是咱們的操做步驟的翻譯,對吧?
雖然編程語言不重要,可是初學者選擇合適的編程語言卻很是重要,由於它會影響你的學習效果和成就感的達成,並且,你終歸須要選擇一種編程語言才能開始學習編程。
就像你們都喜歡學英語而不是非洲某個國家的法語變種同樣,一般你選擇一個你們都在用的編程語言是不會有大的問題的,例如看一下權威的TIOBE編程語言排行榜2019年3月的統計:
<table class="table table-striped table-top20"> <thead><tr> <th>Mar 2019</th> <th>Mar 2018</th> <th>Change</th> <th>Programming Language</th> <th>Ratings</th> <th>Change</th> </tr></thead> <tbody> <tr><td>1</td><td>1</td><td></td><td>Java</td><td>14.880%</td><td>-0.06%</td></tr><tr><td>2</td><td>2</td><td></td><td>C</td><td>13.305%</td><td>+0.55%</td></tr><tr><td>3</td><td>4</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/up.png" alt="change"></td><td>Python</td><td>8.262%</td><td>+2.39%</td></tr><tr><td>4</td><td>3</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/down.png" alt="change"></td><td>C++</td><td>8.126%</td><td>+1.67%</td></tr><tr><td>5</td><td>6</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/up.png" alt="change"></td><td>Visual Basic .NET</td><td>6.429%</td><td>+2.34%</td></tr><tr><td>6</td><td>5</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/down.png" alt="change"></td><td>C#</td><td>3.267%</td><td>-1.80%</td></tr><tr><td>7</td><td>8</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/up.png" alt="change"></td><td>JavaScript</td><td>2.426%</td><td>-1.49%</td></tr><tr><td>8</td><td>7</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/down.png" alt="change"></td><td>PHP</td><td>2.420%</td><td>-1.59%</td></tr><tr><td>9</td><td>10</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/up.png" alt="change"></td><td>SQL</td><td>1.926%</td><td>-0.76%</td></tr><tr><td>10</td><td>14</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/upup.png" alt="change"></td><td>Objective-C</td><td>1.681%</td><td>-0.09%</td></tr><tr><td>11</td><td>18</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/upup.png" alt="change"></td><td>MATLAB</td><td>1.469%</td><td>+0.06%</td></tr><tr><td>12</td><td>16</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/upup.png" alt="change"></td><td>Assembly language</td><td>1.413%</td><td>-0.29%</td></tr><tr><td>13</td><td>11</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/down.png" alt="change"></td><td>Perl</td><td>1.302%</td><td>-0.93%</td></tr><tr><td>14</td><td>20</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/upup.png" alt="change"></td><td>R</td><td>1.278%</td><td>+0.15%</td></tr><tr><td>15</td><td>9</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/downdown.png" alt="change"></td><td>Ruby</td><td>1.202%</td><td>-1.54%</td></tr><tr><td>16</td><td>60</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/upup.png" alt="change"></td><td>Groovy</td><td>1.178%</td><td>+1.04%</td></tr><tr><td>17</td><td>12</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/downdown.png" alt="change"></td><td>Swift</td><td>1.158%</td><td>-0.99%</td></tr><tr><td>18</td><td>17</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/down.png" alt="change"></td><td>Go</td><td>1.016%</td><td>-0.43%</td></tr><tr><td>19</td><td>13</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/downdown.png" alt="change"></td><td>Delphi/Object Pascal</td><td>1.012%</td><td>-0.78%</td></tr><tr><td>20</td><td>15</td><td><img src="http://blog.hubwiz.com/2019/03/25/how-to-learn-coding/downdown.png" alt="change"></td><td>Visual Basic</td><td>0.954%</td><td>-0.79%</td></tr> </tbody> </table>
不過貿然地從衆選擇並不適合全部的狀況,每種編程語言都有它特定的優點領域和優點生態, 我嘗試根據你學編程的目的以及特定領域從業企業的主流選擇給出適合初學者的幾種選擇, 但更細化地分析遠遠超出了本文的範圍:
<table class="table table-striped"> <thead> <tr><th>學習目的</th><th>推薦編程語言</th><th>推薦理由</th></tr> </thead> <tbody> <tr><td>只是玩玩</td><td>JavaScript</td><td>隨處能夠找到運行環境,容易得到成就感</td></tr> <tr><td>開發網頁應用或網站</td><td>JavaScript</td><td>只有JavaScript能夠支持單一語言先後端全棧開發</td></tr> <tr><td>開發安卓應用</td><td>kotlin、java</td><td>Kotlin是趨勢,Java更通用</td></tr> <tr><td>開發蘋果應用</td><td>Swift、Object-C</td><td>Swift是趨勢,初學者不要選Object-C</td></tr> <tr><td>開發遊戲</td><td>C#、JavaScript、C/C++</td><td>C#是由於Unity的存在,JavaScript更適合網頁遊戲,C/C++更適合網絡端遊</td></tr> <tr><td>開發數據分析或機器學習應用</td><td>Python、Julia、R</td><td>Python是這一領域當之無愧的王者,Julia是值得關注的趨勢語言,R在數據分析上有本身的價值</td></tr> <tr><td>開發企業應用</td><td>Java、C#</td><td>去偏傳統的IT公司工做的最佳語言是Java和C#,工做機會很是多</td></tr> <tr><td>開發嵌入應用</td><td>C、Assembly Language</td><td>穿戴設備或IOT軟件的運行環境受限,須要這種底層的語言</td></tr> <tr><td>開發服務端應用</td><td>JavaScript、Go</td><td>JavaScript是由於NodeJS的存在,Go是由於它爲網絡服務應用開發專門進行了優化</td></tr> </tbody> </table>
若是你目前尚未明確的學習目的或者傾向性,我推薦兩種語言:JavaScript和Python。 這兩種語言都有很好的生態,意思是當你須要幫助或者須要使用第三方代碼時比較容易獲取。若是你有意向數據分析/機器學習/人工智能方向發展,那麼選擇Python,其餘狀況,選擇JavaScript。
不管如何,仍是建議你首先考慮本身學習編程的目的是什麼,有哪一個方向是本身感興趣而且願意付出時間和努力的,畢竟,興趣是最好的老師。
在機器學習成爲顯學以前,傳統的編程思惟只有一條主線,就是邏輯的表達:把你解決問題的思惟,用特定的編程語言表達出來,整理出程序讓計算機去執行。這須要你把目標問題分解成一個一個的已經解決的小問題,而後再把這些小問題的解決方案整合成最終的完整解決方案。
理論上只須要三種整合手段就能夠實現任何計算任務:順序、條件判斷和跳轉:
第一種就是咱們解決大象問題時用到的,順序整合邏輯,依次執行分解後的解決方案就能夠獲得最終的解決方案。順序執行是最基本的整合邏輯,它爲程序的編寫奠基了基礎。
第二種關鍵的整合手段是條件判斷,意思是須要根據執行時的實際狀況判斷是執行方案A仍是執行方案B,這個看起來極其簡單的判斷邏輯事實上是程序展示出變幻無窮的核心所在。你能夠在不少軟件裏觀察到條件判斷的存在,例如高鐵的煙感探測軟件只有在檢測到有人在車箱內抽菸時纔會報警,而遊戲只有在你擊殺大BOSS以後纔會通關,或者12306檢測到你成功識別了它至關有情趣的驗證碼以後才容許你登陸...
第三種整合手段是跳轉,這使得程序能夠改變執行的前後流程,從而改變程序的運行效果。實際上條件判斷以後執行的就是一種規範化的跳轉,例如跳過方案A的片斷或者跳過方案B的片斷。
循環則是另外一種常見的規範化跳轉,它可讓咱們將一個方案重複執行若干次,而不是在程序中將這個方案複製若干次。例如,當須要咱們編寫程序實現猴子吃香蕉的任務時,能夠看到使用樸素的順序整合與循環整合的區別:
所以,在傳統意義上的編程,其核心思惟就是目標任務的分解與解決方案的整合,將目標任務 分解細化到你已有的解決方案層面,再使用以上三種手段進行整合。
在機器學習興盛以前,幾乎全部的軟件都是規則邏輯的表達,開發者須要對任務進行分解,理清每個細節的解決方案,而後再整合到一塊兒。雖然技術不斷地更迭,也不斷出現新的開發語言和領域模型,可是這一基本的思路是歷來沒有變化過的。
不過機器學習尤爲是最近十年深度學習的興起,已經逐漸產生了一種新的軟件開發範式,這種新的範式被Tesla的AI主管Andrej Karpathy稱爲 軟件2.0 。若是你學習編程的目的是要進入人工智能領域,但願這部分的內容對你有所幫助。
在傳統的編程中,開發者是規則的制定者,這些規則以程序的形式存在,而計算機則僅僅負責執行,也許因爲開發者的某個疏忽可能會致使程序的運行出人意料,但總體上來說開發者是程序的強力操控者,全部的執行邏輯是開發者的思惟的展現。
可是在軟件2.0中,開發者只是實現一個基準的程序,而大量具體化的處理規則是這個基準程序經過對大量數據的處理而得出的,也就是說,程序執行的規則一部分由開發者設定(被稱爲模型的超參數),而另外一部分規則倒是由程序本身經過與數據的磨合優化出來的。
例如,人臉識別已經從早期的手工設計用於識別的特徵進化到由深度神經網絡自動從大量標註數據中提取特徵:
在軟件2.0中的基準程序須要更高層級的抽象,而不侷限在一事一議的具體問題解決的邏輯表述上。在目前這一層主要是利用人工神經網絡來實現的,程序自主學習的規則體如今神經元的鏈接權重調整上。所以軟件2.0的開發範式,其核心思惟就是設計適合問題領域的模型,而後用數據來優化出模型的參數。
軟件2.0還處於極其早期的萌芽階段,但很是值得初學者關注,它的發展也許會最終改變軟件開發的模式,雖然我確信在至關長的時間內編程做爲一種工做而言都不會消失。
編程是須要熟練的掌握一些基本技能的,由於須要用這些基本技能來組合出來針對特定問題的解決方案。當你仍是一張白紙的時候,即便了解了順序、條件判斷或者跳轉、循環之類的思惟也解決不了具體問題,由於分解到最後仍是找不到可用的武器。
編程語言是你的第一個武器,要用好這個武器,就須要儘量多的瞭解一個編程語言的能力。能夠參考下面的問題探索編程語言的能力:
一、這個編程語言怎麼定義變量、函數或者類?
變量是讓同一段程序可以適應各類執行環境的必備品,在程序中順利地使用變量意味着你有了初步的抽象能力。幾乎全部的編程語言都支持變量,那麼先了解一個編程語言如何定義變量、如何給變量賦初值是理所應當的。
例如,你要編寫的程序可能有不少個註冊用戶,而你的程序核心邏輯並不須要根據用戶的不一樣而區別對待,那麼將註冊用戶抽象成一個變量來編寫你的程序邏輯就是合理的選擇:
函數(或者過程)是組織可複用代碼的一種經常使用手段。若是有一個功能你會在多個地方使用,那麼把這個功能封裝到一個函數裏是常見的代碼複用手段,這樣就避免了一樣的實現代碼在程序的不一樣地方重複出現,優化了代碼,也更容易維護。
若是說函數是對計算機原生的順序過程化思惟的一種優化組合方法,那麼類則是面向對象的軟件設計思惟的優化組合方式,不妨簡單地把面向對象視爲對現實世界中的實體對象以及相互關係的模擬,例如能夠把全部的用戶視爲一個類,由於在咱們的程序中這些用戶有一些共同的特性和方法。
二、這個編程語言怎麼表達順序、條件判斷、跳轉或循環邏輯?
就像前面說到的,這些組合手段用來把程序的各部分拼裝在一塊兒,所以是必須掌握的。
三、這個編程語言提供了哪些基準解決方案?
所謂基準解決方案就是能夠解決某個單一問題的方案,例如:怎麼輸出一句話、顯示一個圖片或者訪問服務器上的數據庫。一般一個編程語言都會提供一些內置的基準解決方案,以函數或者類的形式提供給開發者,這些函數或者類,就是咱們常說的API —— 應用開發接口。
所以在瞭解了編程語言的基礎語法以後,須要學習的就是編程語言提供的API的使用方法。雖然不須要逐個驗證每一個API的功能,可是強烈建議你設定一些問題,而後帶着這些問題找出能夠解決這些問題的API進行練習 —— 這些API是你解決具體問題的基礎。
四、這個編程語言有哪些優秀的第三方開發包?
大多數的編程語言都採用開發包的形式支持第三方提供擴展解決方案,以便開發者能夠根據本身的領域需求進行選擇。瞭解你選擇的編程語言有哪些經常使用的開發包是很是重要的一件事,這能夠避免你從新發明輪子,提升學習效率。
例如,一樣是學習Python,若是你的目標是要開發Web應用,那麼須要瞭解的就是Flask之類的Web開發包,而若是你的目標是要開發機器學習/深度學習應用,那麼須要瞭解的就是numpy、scikit-learn這些開發包了:
毋庸置疑,和學習其餘知識或技能同樣,學習編程也須要掌握正確的方法。
第一個學習方法就是多實踐,只有思路是遠遠不夠的。過於強調看書看視頻而忽略實踐的結果就是眼高手低。你看到一個問題,思路上以爲行得通,可是卻怎麼也實現不出來。這是由於編程須要精確地考慮並實現每個細節,若是隻是粗線條的理解,是很難達到學習目標的。
那麼怎麼才能多實踐?應該多模擬一些實戰項目嗎?
不是這樣的。在早期的學習中,不該該參與複雜的實戰項目,而是應該儘量多的瞭解編程語言的能力,好比練習它的基礎API的使用方法、練習它的擴展包的API的使用方法。一個實踐任務必定不要包含太多的代碼,最好聚焦於一個API,儘量地理解它的用法,以及它對應的抽象模型的內在機制。
有的時候一個API用起來很簡單,可是它有對應的抽象模型存在,這個模型並不容易一下理解。例如當你學習JavaScript操做網頁的時候,就會接觸到文檔對象模型、Flex盒模型等諸多抽象,在這種狀況下,建議你先遵循黑盒法則,就是先了解這個模型的做用,掌握API的使用方法,而暫時忽略其內部運行機制,而後將這個不理解的問題暫且記到小本本上,留待往後解決。
因此,咱們說的多實踐,不是實戰項目的實踐,而是在很細粒度上的實踐,理想的粒度是在單一API上完成一個實踐,由於API自己就體現了編程語言或開發包的設計者的初衷。
第二個學習方法就是在學習的過程當中,多問本身一些爲何,有意識地設計一些問題挑戰本身,把一時解決不了的問題記錄下來,帶着問題繼續學習。
第一種問題是在學習過程當中自發產生的,好比前面提到的,如今學習的某個知識點可能涉及到了另外一個以前不瞭解的知識點,若是那是一個比較難理解的知識點,那麼仍是先記錄下來,不要打斷當前的學習思路。
第二種問題是有意識的發問。例如當你練習一個API的使用時,不妨考慮一下這幾個問題:這個API可能在什麼場景下能用到?爲何這個API須要這些參數?這個API和以前學的哪些API常常一塊兒用?
可以主動地向本身提出問題是很了不得的進步,這意味着你真正進入了主動思考的狀態。
在實踐API的時候,咱們的目標就是理解並掌握這個API的使用方法。當初步熟悉了編程語言的API以後,就能夠設定下一級的目標,嘗試着用已經掌握的知識去實現這個目標。不須要完成一個大程序,對於大多數狀況而言,這時候試着編寫一個諸如貪吃蛇這樣的小遊戲是合適的:
固然這種階段性的目標也是與你的最終學習目標相關的,例如,若是你的學習動力是要開發網頁應用,那麼這個階段試着實現一個簡單的圖片分享或者博客系統都是能夠的;而若是你的目標是人工智能,那麼這個階段能夠試着用神經網絡解決一下文本分類的問題。總之階段性的分級目標的設定是爲了給本身一個前進的動力,太高或者太低都很差。
學習編程的目標是否是學習,而是開發出有價值的程序。所以徹底脫產的學習終究會告一段落,你可能會投入到繁忙的編程工做中去。不過這並不意味着你再也不須要學習,事實上,技術的演變是極其快速甚至劇烈的,所以別忘了:
保持積極學習的心態和敏銳的好奇心,在戰鬥中學習戰鬥!
原文連接:編程入門自學指南 — 匯智網