程式語言學習心得 (完全版) -- 不要害怕遺忘和混淆

2021-02-28 蔡超談軟體

引子

年初和極客邦一起錄製了關於Go語言學習的視頻:《Go語言從入門到實踐》。這門課程的想法就是幫助那些已經掌握了一門程式語言的工程師快速學習Go語言。在課程中為了便於有編程基礎的朋友快速掌握Go,我採用了諸如類比等的講述方式,非常高興這門課程得到了很多朋友的肯定。也從留言中看到了大家的學習熱情,這些都是對我最大的鼓舞。

對於計算機從業者而言不論你的母語是什麼語言,中文,英語或是法語,西班牙語等,你的第一工作語言都是程式語言,你一定聽說過那句話 「talk is cheap show me the code"。所以,快速學習和掌握程式語言一直以來都是每一個工程師夢最想要擁有的超能力。

我從小學開始學習編程,在後來17年的職業生涯中也主動和被動的學習了一眾程式語言,如C/C++,Java,Python,Haskell,Groovy,Scala,Clojure,Go等等,在這期間付出了很多努力,取得了不少經驗,當然也走過了更多彎路。下面分享一下自己的學習心得,希望可以對大家的學習有所幫助和借鑑。

掌握編程範式優於牢記語法

各種程式語言裡的獨特語法簡直是五花八門,下面就隨便選取了其中幾種語言,看看你們知道他們都是什麼語言嗎?

1.

def biophony[T <: Animal](things: Seq[T]) = things map (_.sound)def biophony[T >: Animal](things: Seq[T]) = things map (_.sound())

2.

quicksort [] = []quicksort (x:xs) =                let smaller = [a|a<-xs,a<=x]                   larger = [a|a<-xs, a>x]               in quicksort smaller ++[x]++ quicksort larger

3.

my @sorted = sort {$a <=> $b} @input;my @results = map {$_ * 2 + 1} @input;

很多工程師往往把學習語言的重點放在了學習不同語言的語法上,而忽略了語言背後的思想及適合的應用場景。

其實對於程式語言的學習,意義最大,收穫最大的就是對於編程思想的學習。正如著名的計算機學者,首位圖靈獎獲得者,Alan Perlis說的那樣如果一個程式語言不能夠影響你的編程思維,這個語言便不值得學習。

「A language that doesn’t effect the way you think about programming, is not worth knowing.」 - Alan Perlis

正確有效的學習程式語言對於我們編程思維的提高有著很重要的影響,即使是去學習的一些暫時還用不到的程式語言。

「Lisp很值得學習,你掌握它以後,會感到它給你帶來極大的啟發。這會大大提高你的編程水平,使你成為一個更好的程式設計師,儘管在實際工作中極少用到Lisp.」 — 《黑客與畫家》

程序語言的編程思想主要受到編程範式的影響,如果了解這點你就會發現很多新語言其實是新瓶裝老酒。

至於編程範式(programming paradigm),官方的定義是:A programming paradigm is a style, or 「way,」 of programming. (一種編程風格和方式)

以下是目前廣泛應用的一些編程範式:

結構化 (Structured)

函數式 (Functional)

面向對象 (Object Oriented)

關於這些典型編程範式相信你已經有所耳聞,也可以在網絡上找到很多詳細的相關資料,這裡就不再贅述,僅通過一些簡單的實例對比,來讓大家認識到不同編程範式對程序設計思想的影響。

結構化  vs. 函數式

我們通過快速排序的實現來看看這兩種編程範式的差別:

快速排序 結構化實現:Groovy語言實現

class QuickSort {          private static void exch(int pos1,int pos2,List data){             int tmp=data[pos1];             data[pos1]=data[pos2];             data[pos2]=tmp;       }       private static void partition (int lo,int hi, List a){                                if (lo<0||hi<0||lo>=hi-1){                    return;             }             int midValue=a[lo];             int i=lo+1;int j=hi;             while (true){                    while(i<hi&&a[i]<midValue){                           i++;                    }                    while(j>lo&&a[j]>midValue){                           j--;                    }                    if (i>=j) break;                    exch(i,j,a);                     }             exch(i,lo,a);                    partition(lo,i-1,a);                          partition(i+1,hi,a);                    }       public static List sort(List a){             int lo=0; int hi=a.size()-1;             partition(lo, hi, a);                   return a;           }}

快速排序 函數式實現:Groovy實現

def quickSort_fp(List list){       if (list.size()==0){             return []       }       def x=list[0]        def smaller=list.findAll{it<x}       def mid=list.findAll{it==x}       def larger=list.findAll{it>x}           return quickSort_fp(smaller)+mid+quickSort_fp(larger)       }

快速排序 函數式實現:Haskell實現

quicksort [] = []quicksort (x:xs) =                let smaller = [a|a<-xs,a<=x]                   larger = [a|a<-xs, a>x]               in quicksort smaller ++[x]++ quicksort larger

通過以上比較你會發現:對於結構化編程,我們要通過程序來告訴機器怎麼做,而函數式編程則更像是通過程序告訴機器我們想要什麼。

函數式 vs 面向對象

這裡我們通過實現一個通用的計算過程計時功能來比較。大家可以細細體會其中的不同。

面向對象 Go語言實現

以下利用Decorator模式來為不同的Caculator實現的Caculate過程計時 (如果對於下面程序有些疑惑,建議先回顧一下設計模式裡的Decorator模式)

type Caculator interface {  Caculate(op int) int}
type TimerDecorator struct { innerCal Caculator}
func NewTimerFn(c Caculator) Caculator { return &TimerDecorator{ innerCal: c, }}
func (td *TimerDecorator) Caculate(op int) int { start := time.Now() ret := td.innerCal.Caculate(op) fmt.Println("time spent:", time.Since(start).Seconds()) return ret}
type SlowCal struct {}
func (sc *SlowCal) Caculate(op int) int { time.Sleep(time.Second * 1) return op}
func TestOO(t *testing.T) {   tf := NewTimerFn(&SlowCal{}) t.Log(tf.Caculate(10))}

函數式 Go語言實現

以下也是通過類似於Decorator的思路來為不同的方法實現添加運行過程計時

func timeSpent(inner func(op int) int) func(op int) int {  return func(n int) int {    start := time.Now()    ret := inner(n)    fmt.Println("time spent:",      time.Since(start).Seconds())    return ret  }}
func slowFun(op int) int { time.Sleep(time.Second * 1) return op}
func TestFn(t *testing.T) { tsSF := timeSpent(slowFun) t.Log(tsSF(10))}

通過上面的比較大家可以有個簡單認識,在函數式編程中函數是第一公民可以作為參數和返回值,而在面向對象編程中對象才是第一公民。

可以類比,但不要翻譯

在學習程式語言時,如果我們已經了掌握了一種語言,通過類比,尤其是比較不同點,可以有助於我們更快的掌握另一種新的語言。

要注意的是學習程式語言也和我們學習自然語言一樣,要掌握不同語言的特點,習慣用法,否則就會出現類似於中式英語這樣的問題。不管後來學習了什麼語言,都是先用熟悉的語言的方式實現,然後翻譯成另一種語言,我們常常可以看到C++語言描述的C程序,Go語言描述的Java程序等。

下面給大家舉幾個例子:

例1:

是關於在方法運行結束後返回多個值。由於Java不支持多返回值,我們通常會把多個返回值打包成一個對象返回。

package demo;
class Result{ private int part1; private int part2; public Result(int part1, int part2) { this.part1 = part1; this.part2 = part2; }
public int getPart1() { return part1; }
public int getPart2() { return part2; } public String toString() { return String.format("(%d,%d)", part1, part2); }}public class Example { public Result returnMultiValues() { return new Result(1,2); } public static void main(String[] args) { Example e= new Example(); System.out.println(e.returnMultiValues());  }}

一些Java的程式設計師,在學習Go語言時,常常會寫出下面的程序,在Go中仍是通過一個結構體來返回多個值。

package main
import "fmt"
type Result struct { Part1 int Part2 int}
func returnMultiValues() Result { return Result{1, 2}}
func main() { fmt.Println(returnMultiValues())}

實際Go語言是支持多返回值的,程序完全可以簡化為下面這樣:

package main
import "fmt"
func returnMultiValues() (int, int) { return 1, 2}
func main() { fmt.Println(returnMultiValues())}

例2

讓我們來生成一副撲克。

Java中的實現:

public static void main(String[] args) {     List<String> cards = new ArrayList<>();     for (int i=2;i<12;i++){       cards.add(String.valueOf(i));     }     cards.addAll(List.of("J","Q","K","A"));     System.out.println(cards);  }

Java程式設計師,學習了Python以後,通常會實現成這樣

cards = ['J','Q','K','A']for n in range(2,11):  cards.append(str(n))print cards

上面的Python代碼雖然也可以準確的實現功能,但在一個Python程式設計師眼中上面的代碼總覺得不是那麼地道,下面是地道的p ython程序

cards = [str(n) for n in range(2,11)] + list('JQKA')print cards

專注語言特性而不是語法糖

上面談到寫地道的程序,學好程式語言中的「語法糖」,通常可以讓我的代碼更簡化和「看上去」很地道,因此也有很多程式設計師非常熱衷於此,猶如對於IDE的快捷方式的熱衷,似乎這些是一個資深,高效程式設計師的標誌。

什麼是語法糖呢?

語言中某種特殊的語法

對語言的功能並沒有影響

對程式設計師有更好的易用性

增加程序的可讀性

一些語法糖的例子:

Python中union兩個list

上面由語法糖帶來的地道我之所以用了「看上去」這個詞來修飾,就是因為要想真正的寫出地道的程序,比掌握語法糖更重要的是掌握語言的特性。

什麼是語言的特性呢?

下面我們以Go語言為例,來聊一下:

首先,一點就是主流程式設計師轉Go時都有的一個問題:Go的面向對象支持。面向對象程序設計幾乎是現在所有主流程式設計師的標準思維模式。但也正因為這樣,當你上手Go語言的時候,要特別關注Go在面向對象方面的特性。

Go在這方面的確是非常獨特的,以至於目前大家常常會討論Go到底是不是面向對象語言,來讓我們看看Go官方的回答:

「 Is Go an object-oriented language? 

Yes and no. 

Although Go has types and methods and allows an object oriented style of programming, there is no type hierarchy. The concept of 「interface」 in Go provides a different approach that we believe is easy to use and in some ways more general.

Also, the lack of a type hierarchy makes 「objects」 in Go feel much more lightweight than in languages such as C++ or Java.

「 -- https://golang.org/doc/faq

簡單來看就是說:

Go不支持繼承

Go以一種不同方式實現了接口機制

這裡我們從Go的接口機制來看看語言特性對編程的影響,更多內容大家可以參考我的Go語言視頻課程。

試想如果我們把上面這個程序進行分包,我們希望分為一個主要邏輯包(Task)和一個插件包(包含不同的Programmer的實現,如:GoProgrammer);

從上圖你會發現,由於Java中具體實現的代碼會依賴於接口的聲明你並不能簡單的分成兩個包,否則就會出現上圖中循環依賴。所以,這種情況我們通常是分三個包。

而Go語言的接口實現,則不需要在代碼中顯式的聲明對於接口定義的依賴,採用的是Duck type的方式。

看完了語法特性,我們再來看看語言中並發機制特性。

1 基本並發單元

Go中採用獨特的協程(Goroutine)作為基本並發單元,這一定會讓Java程式設計師聯想起線程(Thread),並不免在編寫Go並發程序時引入很多編寫多線程程序的思維,實際由於兩者間存在著很多差異,直接以多線程的編程思想來編寫多協程的程序有時是不適合的。

先讓我們簡單看看兩者的差異:

雖然,我們沒有完全列出兩者的差異,但是你也可以發現像Java程序中常見的線程池,在Go程序中很多情況下並不會帶來像Java中那樣的性能提升。

再來看看他們的並發機制,Java通常採用共享內存機制來進行並發控制,而Go中則支持了CSP(Communicating Sequential Processes)機制。

下面通過典型的生產者和消費者並發任務來比較兩種方式不同的特性:

共享內存方式(Java實現)

import java.util.LinkedList;import java.util.Queue;import org.junit.jupiter.api.Test;
class Producer implements Runnable {  private Queue<Integer> sharedData; public Producer(Queue<Integer> sharedData) { this.sharedData = sharedData;
}
@Override public void run() { for (int i = 0; i < 100; i++) { synchronized (this.sharedData) { try {
while (this.sharedData.size() != 0) { this.sharedData.wait(); } this.sharedData.add(i); System.out.printf("Put data %d \n", i); this.sharedData.notify(); } catch (InterruptedException e) { e.printStackTrace(); }
} }
}}
class Consumer implements Runnable {  private Queue<Integer> sharedData; public Consumer(Queue<Integer> sharedData) { this.sharedData = sharedData; }
@Override public void run() { while (true) { synchronized (this.sharedData) { try { while (this.sharedData.size() == 0) { this.sharedData.wait(); } System.out.println(this.sharedData.poll()); if (this.sharedData.size() == 0) { this.sharedData.notify(); } } catch (InterruptedException e) { e.printStackTrace(); } }
    } }}
class ProducerConsumer { @Test void test() throws InterruptedException { Queue<Integer> sharedData = new LinkedList<>(); new Thread(new Producer(sharedData)).start(); new Thread(new Consumer(sharedData)).start(); Thread.sleep(2 * 1000);  }}

利用共享的Queue來實現生產者和消費者之間的數據傳遞,為了保證數據在多線程間同步,我們使用了鎖。

CSP方式 (Go實現)

package Demoimport (  "fmt"  "testing"  "time")
func Producer(ch chan int) { for i := 0; i < 100; i++ { fmt.Printf("put %d \n", i) ch <- i } close(ch)}
func Consumer(ch chan int) { for { select { case i, ok := <-ch: if !ok { fmt.Println("done.") return } fmt.Println(i)
} }}
func TestFn(t *testing.T) { ch := make(chan int) go Producer(ch) go Consumer(ch) time.Sleep(time.Second * 3)}

Go這是利用CSP機制中的channel在生產者和消費者之間傳遞數據。

好的代碼風格不能代替好的設計

代碼是軟體實現的最終形式。但是對於更為複雜的軟體而言,我們僅僅在代碼層面整潔,復用及高可讀性還是遠遠不夠。

人們總是通過更高層次的抽象來實現簡化。猶如,程式語言由機器語言,到彙編語言,再到高級語言不斷演進,抽象層次不斷提高。更高的抽象層次,能夠更加有助於人們去了理解和構建更複雜的軟體。

所以,在每個抽象層面,都要考慮簡潔,復用和易理解。而且軟體的設計過程及人們理解軟體設計的過程也通常是自頂向下的。這就產生了指導人們做好高層抽象的設計模式,甚至更高抽象層面的架構模式。

作為合格程式設計師光學習代碼的整潔之道是不夠的,還有學習更高層面的整潔和復用。

下面我們還是用一個例子來說明

這裡模擬我們要實現一個可以擴展使用不同支付方式的支付過程:

type PayChannel int
const ( AliPay PayChannel = 1 WechatPay PayChannel = 2)
func payWithAli(price float64) error { fmt.Printf("Pay with Alipay %f\n", price) return nil}
func payWithWechat(price float64) error { fmt.Printf("Pay with Wechat %f\n", price) return nil}
func PayWith(channel PayChannel, price float64) error { switch channel { case AliPay: return payWithAli(price) case WechatPay: return payWithWechat(price) default: return errors.New("not support the channel") }}

上面的代碼在編碼風格上是整潔的,可讀性也不錯。但我們會發現每增加一種支付模式我們都要修改PayWith這個方法,在switch中加入一個對應的分支。

通過利用面向對象中的命令模式的設計思想,我們可以將代碼優化為如下(當然這裡是採用函數式編程來實現這個命令模式的思想的)

type PayFunc func(price float64) error
func payWithAli(price float64) error { fmt.Printf("Pay with Alipay %f\n", price) return nil}
func payWithWechat(price float64) error { fmt.Printf("Pay with Wechat %f\n", price) return nil}
func Pay(payMethod PayFunc, price float64) error { return payMethod(price)}

現在可以看到,新增支付方式時,Pay方法完全不用做任何修改。

這裡給大家推薦兩本設計模式方面的經典書籍

不要害怕遺忘和混淆

「學了也用不上,很快就忘記了」常常會成為很多程式設計師拒絕學習新的程式語言的藉口。

遺忘和混淆都是正常的,人類記憶就是這樣。

這是遺忘曲線,在一開始的遺忘率是最高的。對於語言學習,我的經驗是我們會很快忘記我們學到的特殊語法,留存下來會是我們對語言編程範式,編程特性的理解。所以,正如前面我們已經提到過的《黑客與畫家》中觀點:學習了Lisp,即使你在工作中極少使用到它,你也會成為一個更優秀的程式設計師。

如果你是按照我們前面所說的方式充分掌握每種語言的特性並了解編程範式,你所遺忘和混淆的更多的是語法。通過寫上一,兩天,甚至幾小時的程序,你很快就會發現所有那些對於這種語言的技能就都回來了。這好比練過健身的人,一段時間不練,肌肉會有流失,但是與從來沒有練過的人不同,他們通過訓練,肌肉很快能夠恢復原有的狀態,就是所謂的肌肉記憶,我們的大腦記憶也是這樣的。

所以,不要因為害怕遺忘和混淆就不去學習新的語言,他們不僅可以拓寬你的編程思路,一旦需要你便可以經過較短時間從回巔峰!

「Stay hungry,stay foolish." -- Steve Jobs.

相關焦點

  • 程式語言學習心得 (精簡版) -- 不要害怕遺忘
    所以,快速學習和掌握程式語言一直以來都是每一個工程師夢最想要擁有的超能力。我從小學開始學習編程,在後來17年的職業生涯中也主動和被動的學習了一眾程式語言,如C/C++,Java,Python,Haskell,Groovy,Scala,Clojure,Go等等,在這期間付出了很多努力,取得了不少經驗,當然也走過了更多彎路。下面分享一下自己的學習心得,希望可以對大家的學習有所幫助和借鑑。
  • 如何解決知識遺忘,以及學習新知識的方法
    ,也就是關於編程學習的一些方法!直到有一次我請教了幾位大佬前輩,得到以下兩句話:1、不要把知識遺忘當成問題去解決,你解決不了的,知識遺忘是一件正常的事情 不管有沒有,反正我今天要和你分享一下,所以等下看完記得點讚哦!你覺得最好的學習新知識的方法是什麼?對於編程來說,我們大致把它分為理論和實戰,就是你學習的知識,後期是可以用到的,那這個該如何學習?
  • 零基礎如何學習編程?
    今年的8月,剛好工作上想要開發一個基於微信的英語學習網站,藉此機會,我決定好好學習一下編程。在此之前,我所有關於程序的知識僅僅來源於兩部分,一是本科時期的C語言必修課,現在已經忘的一乾二淨,不過好歹我從中明白編程是怎麼回事;第二部分是大概兩年前由於工作關係學的一些Python,不過只是皮毛,現在忘的七七八八。
  • 男孩子天生就比女孩子更適合學習編程嗎?
    在大眾的潛意識裡,學習編程似乎自帶性別壁壘,「男孩子天生就比女孩子更適合學習編程」「男孩子思維更敏捷學編程優勢更大」。難道男孩女孩間的思維差異,天生就有文理之分嗎?回答當然是:NO!可見,編程並不是男生獨佔的天下。如今,也有越來越多的女孩們,在計算機、編程和開發應用軟體上展現出她們的才華,以實際成績來改變人們的偏見。
  • 兩年,我學會了所有的程式語言!
    本文想要探討的一個話題是:作為一個程式設計師,如何看待這麼多的程式語言?是不是要學習?該怎麼學習?其實很多人都有這樣的體會,當你學會了一門語言以後,再去學習新的語言,難度會大大降低,因為很多概念是一樣的, 只是換了一種包裝形式,但是每一門語言都有自己獨特之處,比如Ruby可以輕鬆地在運行時「打開」一個類,對這個類增加行為,還有method_missing的處理,這種特性,讓它特別適合去實現DSL,RoR的火爆也就不足為怪了。
  • 編程入門寶典,剛開始學習編程新手必看的5點建議!
    1、選擇程式語言  編程首要還是選擇好適合自己的語言。  程式語言有:C/C++、java、VB、python、actionscript3、javascript、html、css、js等。  有人覺得,C/C++是入門的首選語言,入門簡單。但是,如果你要精通它,怎麼說也需要大概十年的功夫。
  • Wolfram語言入門
    同時,我們的在線文檔也在不斷擴充,隨著大量新範例在 2007年的引入,印刷版將達上萬頁.Wolfram|Alpha於2009年誕生,其獨特的自然語言界面無需任何說明或文檔.但接下來,對由Mathematica和Wolfram|Alpha融合而成的Wolfram語言,我們有必要再次給出文檔並對其進行說明.
  • 初學者的編程自學指南
    使用Google的基本搜索功能就能夠解決大部分問題了,當然,如果想要學習更加高級的技巧,這裡有一份指南:如何用好Google等搜尋引擎?。  英語  你不得不承認,目前為止,編程世界的主流語言還是英文,所以英語能力的好壞決定了你編程能力的上界。中文資料和英文資料相比,實在是太匱乏了,就質量而言,也相對較低。
  • 我是如何自學C語言的(一個菜鳥的學習路)
    utm_source=copy 首先,本人也是一個菜鳥,目前依然還在學習,當初在我開始自學C語言的時候,走過了好多彎路,如果你看到這篇文章,希望你不要走我走過的彎路,這也是我寫這篇文章的目的。我只是把自己覺得是坑,是彎路的地方,結合自己的看法,複述給你聽,希望你有自己的理解,能對你有一點幫助。
  • 從C、C++、Java到Python,編程入門到底學什麼語言好?
    雖然一門計算機語言從編譯器、語法、基礎庫到在程式設計師的圈子中普及,並不是短時間可以一蹴而成,但蘋果仍然以一己之力將Objective-C和Swift帶入了程式語言的主流市場,由此可見,程式語言和一個產品的生態規模息息相關。
  • 我的編程能力從什麼時候開始突飛猛進的?
    迷茫的大一我在大學之前完全沒有編程經驗,高考後,填的專業前幾個也是清一色的傳統工科,被軟體工程錄取純碎是意外。當時甚至很擔心完全沒有編程基礎的我,上大學會不會跟不上,還因為考慮過復讀,現在想想也是天真。
  • 如何學習好R語言?【全套R語音書籍+視頻下載】
    包括了閱讀經典的教材、代碼、論文、學習公開課。 - 通過牛人來學習。 包括同行的聚會、討論、大牛的博客、微博、twitter、RSS。 - 通過練習來學習。 包括代碼練習題、參加kaggle比賽、解決實際工作中的難題。 - 通過分享來學習。 包括自己寫筆記、寫博客、寫書、翻譯書,和同伴分享交流、培訓新人。# 全套R語音書籍下載。關注公眾號後,回覆:R語言
  • 老外總結的編程技巧
    學習一門新的程式語言(Learn a new programming language)學習一門新的程式語言將有助於你開拓新的思維方式,特別是當你使用不熟悉的語言時,你將學習到很多種思維方法應用到語言中。而所學習到的新思維方式,你可以運用在你所熟知的語言中。
  • 【學習心得】情緒管理心得體會
    通過學習網絡學院第四季度的必修課《情緒管理的快速實踐方法》,使我對情緒管理又有了全新的認識和透徹的理解。目前,各行各業的工作者都面臨著極大的壓力,適當的壓力可以促進我們更好地完成工作,但過度的壓力會直接影響我們工作的態度和情緒,這樣就間接導致了工作效率下降,因此管理好自己的情緒就顯得尤為重要,及時調整好情緒和狀態會事半功倍。
  • 一個資深C語言工程師說如何學習C語言
    今天本人就與大家一起談談如何學習C語言或者說學習C語言應從哪幾方面著手。了解一些基本知識一.C語言的背景就個人感觸,無論學習哪門語言首先應該了解一下自己所學語言的背景,也可以說它的發展史。C語言屬於高級程序語言的一種,它的前身是「ALGOL」。其創始人是布朗·W·卡尼漢和丹尼斯·M·利奇。
  • 作為入門基礎的C語言,怎麼自學?
    C語言是幾乎所有程式語言的先驅與靈感的來源,Perl,PHP,Python和Ruby都是用它寫的,同樣什麼Microsoft Windows
  • 文言文程式語言來了 可是好像比英文更難寫了
    近日有開發者開源了一門新的程式語言,吸引了大量開發者的目光,短短幾天獲得了 3k+ star。
  • 我的R語言學習方法
    有朋自遠方來,不亦樂乎,並誠邀入群,以達相互學習和進步之美好心願。通過運營R語言公眾號,認識了各行各業在學習和使用R語言的朋友們。經常會遇到這些問題:我是R新手,要怎樣學習R語言?我要學習R語言,需要學習那些內容?王老師,R語言學習,有什麼書籍或者視頻推薦和分享嗎?等等。
  • 怎樣學習C語言(獻給迷茫的C愛好者)!
    各種嵌入式設備,如手機、PDA也都是C語言開發的。C語言歷史悠久,其內容也絕非譚浩強老師的《C語言程序設計(第二版)》所描寫敘述的那麼簡單——那本書僅僅是針對中國國情的教學入門書而已。    學生總喜歡問:那種語言好?學那種語言有前途?這樣的問題天天在討論,永無休止。
  • 【值得收藏】老外的牛逼編程技巧
    (Learn a new programming language)學習一門新的程式語言將有助於你開拓新的思維方式,特別是當你使用不熟悉的語言時,你將學習到很多種思維方法應用到語言中。你可以和其他人一起工作,當遇到不熟悉的代碼時,你將會去研究,學習理解一個不熟悉的代碼庫(這應該是很有挑戰性的)4.解決編程難題(Solve programming puzzles)你應該試圖去解決代碼問題;程式設計師在編程過程中總是嘗試用最少的步驟來解決遇到的難題,而在這過程中,你可以學到語言的更深奧和更特殊的功能,從而你會不得不思考代碼的創造性