【技術思路】極客時間-左耳聽風-開篇詞2

11 | 程序中的錯誤處理:錯誤返回碼和異常捕捉

傳統的錯誤檢查

  • 傳統的方式:處理錯誤最直接的方式是經過錯誤碼。

多返回值

因而,有一些語言經過多返回值來解決這個問題,好比 Go 語言。Go 語言的不少函數都會返回result, err 兩個值。javascript

  • 參數上基本上就是入參,而返回接口把結果和錯誤分離,這樣使得函數的接口語義清晰;
  • Go 語言中的錯誤參數若是要忽略,須要顯式地忽略,用_ 這樣的變量來忽略;html

  • 由於返回的 error 是個接口(其中只有一個方法Error() ,返回一個 string ),因此能夠擴展自定義的錯誤處理。java

資源清理

  • C語言方式:

這樣的處理方式雖然能夠,可是會有潛在的問題。最主要的一個問題就是你不能在中間的代碼中有 return 語句,由於你須要清理資源。在維護這樣的代碼時須要格外當心,由於一不注意就會致使代碼有資源泄漏的問題。python

#define FREE(p) if(p) { \
                    free(p); \
                    p = NULL; \
                 }
main()
{
    char *fname=NULL, *lname=NULL, *mname=NULL;
    fname = ( char* ) calloc ( 20, sizeof(char) );
    if ( fname == NULL ){
        goto fail;
    }
    lname = ( char* ) calloc ( 20, sizeof(char) );
    if ( lname == NULL ){
        goto fail;
    }
    mname = ( char* ) calloc ( 20, sizeof(char) );
    if ( mname == NULL ){
        goto fail;
    }
    
    ......
 
    
fail:
    FREE(fname);
    FREE(lname);
    FREE(mname);
    ReportError(ERR_NO_MEMORY);
}
  • C++方式

C++ 的 RAII(Resource Acquisition Is Initialization)機制使用面向對象的特性能夠容易地處理這個事情。RAII 使用 C++ 類的機制,在構造函數中分配資源,在析構函數中釋放資源。git

// 首先,先聲明一個 RAII 類,注意其中的構造函數和析構函數
class LockGuard {
public:
    LockGuard(std::mutex &m):_m(m) { m.lock(); }
    ~LockGuard() { m. unlock(); }
private:
    std::mutex& _m;
}

// 而後,咱們來看一下,怎樣使用的
void good()
{
    LockGuard lg(m);                // RAII 類:構造時,互斥量請求加鎖
    f();                             // 若 f() 拋異常,則釋放互斥
    if(!everything_ok()) return;     // 提前返回,LockGuard 析構時,互斥量被釋放
}                                    // 若 good() 正常返回,則釋放互斥
  • Go語言

在 Go 語言中,使用defer關鍵字也能夠作到這樣的效果:github

func Close(c io.Closer) {
    err := c.Close()
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    r, err := Open("a")
    if err != nil {
        log.Fatalf("error opening 'a'\n")
    }
    defer Close(r) // 使用 defer 關鍵字在函數退出時關閉文件。

    r, err = Open("b")
    if err != nil {
        log.Fatalf("error opening 'b'\n")
    }
    defer Close(r) // 使用 defer 關鍵字在函數退出時關閉文件。
}

異常捕捉處理

try - catch - finally編程模式。算法

try {
    ... // 正常的業務代碼
} catch (Exception1 e) {
    ... // 處理異常 Exception1 的代碼
} catch (Exception2 e) {
    ... // 處理異常 Exception2 的代碼
} finally {
    ... // 資源清理的代碼
}

這樣的異常處理方式有以下一些好處。編程

  • 函數接口在 input(參數)和 output(返回值)以及錯誤處理的語義是比較清楚的。
  • 正常邏輯的代碼能夠與錯誤處理和資源清理的代碼分開,提升了代碼的可讀性。
  • 異常不能被忽略(若是要忽略也須要 catch 住,這是顯式忽略)。
  • 在面向對象的語言中(如 Java),異常是個對象,因此,能夠實現多態式的 catch。
  • 與狀態返回碼相比,異常捕捉有一個顯著的好處是,函數能夠嵌套調用,或是鏈式調用。好比:int x = add(a, div(b,c));Pizza p = PizzaBuilder().SetSize(sz) .SetPrice(p)...;

但有個致命的問題,那就是在異步運行的世界裏的問題。try 語句塊裏的函數運行在另一個線程中,其中拋出的異常沒法在調用者的這個線程中被捕捉。promise

錯誤返回碼 vs 異常捕捉

前面也比較過二者的優缺點,整體而言,彷佛異常捕捉的優點更多一些。應該從場景上來討論這個事纔是正確的姿式。錯誤可分爲三個大類:網絡

  • 資源的錯誤:程序運行環境的問題,代碼去請求一些資源時致使的錯誤,好比打開一個沒有權限的文件,寫文件時出現的寫錯誤,發送文件到網絡端發現網絡故障等錯誤。關鍵性資源不能知足的狀況,內存耗盡、棧溢出、一些程序運行時關鍵性資源不能知足等。

  • 程序的錯誤:好比:空指針、非法參數等。這類是本身程序的錯誤,要記錄下來,寫入日誌,最好觸發監控系統報警
  • 用戶的錯誤:在用戶的API層上出現的問題,好比解析一個XML和JSON文件,或是用戶輸入的字段不合法類的錯誤。

能夠這樣來在邏輯上分類:

  • 對於咱們並不指望會發生的事,咱們可使用異常捕捉;
  • 對於咱們以爲可能會發生的事,使用返回碼。

12 | 程序中的錯誤處理:異步編程以及個人最佳實踐

異步編程世界裏的錯誤處理

在異步編程的世界裏,由於被調用的函數是被放到了另一個線程裏運行,這將致使:

  • 沒法使用返回碼:由於函數在異步狀態中,只是把返回的處理權交給下一條指令,而不是把函數運行完的結果返回。
  • 沒法使用拋異常的方式:由於除了上述的函數立馬返回的緣由以外,拋出的異常也在另一個線程中,不一樣線程中的棧是徹底不同的,因此主線程的 catch 徹底看不到另一個線程中的異常。

幾種處理錯誤的方法:

對此,在異步編程的世界裏,咱們也會有好幾種處理錯誤的方法,最經常使用的就是callback 方式。在作異步請求的時候,註冊幾個 OnSuccess()OnFailure()的函數,讓在另外一個線程中運行的異步代碼來回調回來。

JavaScript 異步編程的錯誤處理

function successCallback(result) {
  console.log("It succeeded with " + result);
}

function failureCallback(error) {
  console.log("It failed with " + error);
}

doSomething(successCallback, failureCallback);

經過註冊錯誤處理的回調函數,讓異步執行的函數在出錯的時候,調用被註冊進來的錯誤處理函數,這樣的方式比較好地解決了程序的錯誤處理。而出錯的語義從返回碼、異常捕捉到了直接耦合錯誤出處函數的樣子。

Java 異步編程的 Promise 模式

在 Java 中,在 JDK 1.8 裏也引入了相似 JavaScript 的玩法 —— CompletableFuture

鏈式處理:

CompletableFuture.supplyAsync(this::findReceiver)
                 .thenApply(this::sendMsg)
                 .thenAccept(this::notify);

Go 語言的 Promise

首先,先聲明一個結構體。其中有三個成員:第一個 wg 用於多線程同步;第二個 res 用於存放執行結果;第三個 err 用於存放相關的錯誤。

type Promise struct {
    wg  sync.WaitGroup
    res string
    err error
}

而後,定義一個初始函數,來初始化 Promise 對象。其中能夠看到,須要把一個函數 f 傳進來,而後調用 wg.Add(1) 對 waitGroup 作加一操做,新開一個 Goroutine 經過異步去執行用戶傳入的函數 f() ,而後記錄這個函數的成功或錯誤,並把 waitGroup 作減一操做。

func NewPromise(f func() (string, error)) *Promise {
    p := &Promise{}
    p.wg.Add(1)
    go func() {
        p.res, p.err = f()
        p.wg.Done()
    }()
    return p
}

而後須要定義 Promise 的 Then 方法。其中須要傳入一個函數,以及一個錯誤處理的函數。而且調用 wg.Wait() 方法來阻塞(由於以前被wg.Add(1)),一旦上一個方法被調用了 wg.Done(),這個 Then 方法就會被喚醒。

喚醒的第一件事是,檢查一下以前的方法有沒有錯誤。若是有,那麼就調用錯誤處理函數。若是以前成功了,就把以前的結果以參數的方式傳入到下一個函數中。

func (p *Promise) Then(r func(string), e func(error)) (*Promise){
    go func() {
        p.wg.Wait()
        if p.err != nil {
            e(p.err)
            return 
        }
        r(p.res)
    }()
    return p
}

下面,定義一個用於測試的異步方法。這個方面很簡單,就是在數數,而後,有一半的機率會出錯。

func exampleTicker() (string, error) {
    for i := 0; i < 3; i++ {
        fmt.Println(i)
        <-time.Tick(time.Second * 1)
    }
    
    rand.Seed(time.Now().UTC().UnixNano())
    r:=rand.Intn(100)%2
    fmt.Println(r)
    if  r != 0 {
        return "hello, world", nil
    } else {
        return "", fmt.Errorf("error")
    }
}

下面,來看看實現的 Go 語言 Promise 是怎麼使用的。

func main() {
    doneChan := make(chan int)
    
    var p = NewPromise(exampleTicker)
    p.Then(func(result string) { fmt.Println(result); doneChan <- 1 }, 
            func(err error) { fmt.Println(err); doneChan <-1 })
            
    <-doneChan
}

錯誤處理的最佳實踐

  • 統一分類的錯誤字典:創建一個錯誤字典,不管是使用錯誤碼仍是異常捕捉,都須要認真並統一地作好錯誤的分類。最好是在一個地方定義相關的錯誤。好比,HTTP 的 4XX 表示客戶端有問題,5XX 則表示服務端有問題。
  • 同類錯誤的定義最好是能夠擴展的:經過面向對象的繼承或是像 Go 語言那樣的接口多態能夠很好重用已有的代碼。
  • 定義錯誤的嚴重程度:好比Fatal 表示重大錯誤,Error 表示資源或需求得不到知足,Warning 表示並不必定是個錯誤但仍是須要引發注意,Info 表示不是錯誤只是一個信息,Debug 表示這是給內部開發人員用於調試程序的。
  • 錯誤日誌的輸出最好使用錯誤碼,而不是錯誤信息:打印錯誤日誌的時候,應該使用統一的格式。但最好不要用錯誤信息,而應使用相應的錯誤碼,錯誤碼不必定是數字,也能夠是一個能從錯誤字典裏找到的一個惟一的可讓人讀懂的關鍵字。這樣會很是有利於日誌分析軟件進行自動化監控,而不是要從錯誤信息中作語義分析。好比:HTTP 的日誌中就會有 HTTP 的返回碼,如:404。使用PageNotFound這樣的標識,這樣人和機器都很容易處理。
  • 忽略錯誤最好有日誌:否則會給維護帶來很大的麻煩。
  • 對於同一個地方不停的報錯,最好不要都打到日誌裏:否則這樣會致使其它日誌被淹沒了,也會致使日誌文件太大。最好的實踐是,打出一個錯誤以及出現的次數。

  • 不要用錯誤處理邏輯來處理業務邏輯:不要使用異常捕捉這樣的方式來處理業務邏輯,而是應該用條件判斷。若是一個邏輯控制能夠用 if - else 清楚地表達,那就不建議使用異常方式處理。異常捕捉是用來處理不指望發生的事情,而錯誤碼則用來處理可能會發生的事。

  • 對於同類的錯誤處理,用同樣的模式:好比,對於null對象的錯誤,要麼都用返回 null,加上條件檢查的模式,要麼都用拋 NullPointerException 的方式處理。不要混用,這樣有助於代碼規範。
  • 儘量在錯誤發生的地方處理錯誤:由於這樣會讓調用者變得更簡單。

  • 向上儘量地返回原始的錯誤:若是必定要把錯誤返回到更高層去處理,那麼應該返回原始的錯誤,而不是從新發明一個錯誤。
  • 處理錯誤時,老是要清理已分配的資源:使用 RAII 技術,或是 try-catch-finally,或是 Go 的 defer 均可以容易地作到。
  • 不推薦在循環體裏處理錯誤:這裏說的是 try-catch,絕大多數的狀況你不須要這樣作。最好把整個循環體外放在 try 語句塊內,而在外面作 catch。
  • 不要把大量的代碼都放在一個 try 語句塊內:一個 try 語句塊內的語句應該是完成一個簡單單一的事情。
  • 爲你的錯誤定義提供清楚的文檔以及每種錯誤的代碼示例:若是你是作 RESTful API 方面的,使用 Swagger 會幫你很容易搞定這個事。
  • 對於異步的方式,推薦使用 Promise 模式處理錯誤:對於這一點,JavaScript 中有很好的實踐。
  • 對於分佈式的系統,推薦使用 APM 相關的軟件:尤爲是使用 Zipkin 這樣的分佈式跟蹤系統來幫助收集時間數據關聯錯誤。

13 | 魔數 0x5f3759df

數學的基礎知識。數學真是須要努力學習好的一門功課,尤爲在人工智能火熱的今天。

可是對於系統化學習追求者來講,這篇文章並不具有必定的視野價值。

14 | 推薦閱讀:機器學習101

在機器學習(Machine learning)領域,主要有三類不一樣的學習方法:

監督學習(Supervised learning)、

非監督學習(Unsupervised learning)、

半監督學習(Semi-supervised learning),

監督學習:經過已有的一部分輸入數據與輸出數據之間的對應關係,生成一個函數,將輸入映射到合適的輸出,例如分類。 
非監督學習:直接對輸入數據集進行建模,例如聚類。 

半監督學習:綜合利用有類標的數據和沒有類標的數據,來生成合適的分類函數。

文章中做者描述機器學習主要來講有兩種方法,監督式學習(Supervised Learning)和非監督式學習。

監督式學習

提供一組學習樣本,包括相關的特徵數據以及相應的標籤。程序能夠經過這組樣原本學習相關的規律或是模式,而後經過獲得的規律或模式來判斷沒有被打過標籤的數據是什麼樣的數據。

在監督式學習下,須要有樣本數據或是歷史數據來進行學習,這種方式會有一些問題。好比

  • 若是一個事物沒有歷史數據,那麼就很差作了。變通的解決方式是經過一個和其相似事物的歷史數據。我之前作過的需求預測,就屬於這種狀況。對於新上市的商品來講,徹底沒有歷史數據,好比,iPhone X,那麼就須要從其相似的商品上找歷史數據,如 iPhone 7 或是別的智能手機。
  • 歷史數據中可能會有一些是噪音數據,須要把這些噪音數據給過濾掉。通常這樣的過濾方式要經過人工判斷和標註。舉兩個例子,某名人在其微博或是演講上推薦了一本書,因而這本書的銷量就上升了。這段時間的歷史數據不是規律性的,因此就不能成爲樣本數據,須要去掉。一樣,若是某名人(如 Michael Jackson)去世致使和其有關的商品銷售量很好,那麼,這個事件所產生的數據則不屬於噪音數據。由於每一年這個名人忌日的時候出現銷量上升的可能性很是高,因此,須要標註一下,這是有規律的樣本,能夠放入樣本進行學習。

非監督式學習

對於非監督式學習,也就是說,數據是沒有被標註過的,因此相關的機器學習算法須要找到這些數據中的共性。由於大量的數據是沒有被標識過的,因此這種學習方式可讓大量未標識的數據可以更有價值。

好比,一個在某一年齡段區間的女生購買了某種肥皂,有可能說明這個女生在懷孕期,或是某人購買兒童用品,有可能說明這我的的關係鏈中有孩子,等等。因而這些信息會被用做一些所謂的精準市場營銷活動,從而能夠增長商品銷量。

在監督式的學習的算法下,咱們能夠用一組「狗」的照片來肯定某個照片中的物體是否是狗。而在非監督式的學習算法下,咱們能夠經過一個照片來找到與其類似事物的照片。這兩種學習方式都有各自適用的場景。

如何找到數據的規律和關聯

機器學習基本就是在已知的樣本數據中尋找數據的規律,在未知的數據中找數據的關係。

機器學習中的基本方法論

  • 要找到數據中的規律,你須要找到數據中的特徵點。
  • 把特徵點抽象成數學中的向量,也就是所謂的座標軸。一個複雜的學習可能會有成十上百的座標軸。
  • 抽象成數學向量後,就能夠經過某種數學公式來表達這類數據(就像 y=ax+b 是直線的公式),這就是數據建模。

機器學習文章:

Machine Learning is Fun!
https://medium.com/@ageitgey/machine-learning-is-fun-80ea3ec3c471
中文翻譯版
https://zhuanlan.zhihu.com/p/24339995

相關算法

對於監督式學習,有以下經典算法。

  1. 決策樹(Decision Tree)。好比自動化放貸、風控。
  2. 樸素貝葉斯分類(Naive Bayesian classification)。能夠用於判斷垃圾郵件,對新聞的類別進行分類,好比科技、政治、運動,判斷文本表達的感情是積極的仍是消極的,以及人臉識別等。
  3. 最小二乘法(Ordinary Least Squares Regression)。算是一種線性迴歸。
  4. 邏輯迴歸(Logisitic Regression)。一種強大的統計學方法,能夠用一個或多個變量來表示一個二項式結果。它能夠用於信用評分、計算營銷活動的成功率、預測某個產品的收入等。
  5. 支持向量機(Support Vector Machine,SVM)。能夠用於基於圖像的性別檢測,圖像分類等。
  6. 集成方法(Ensemble methods)。經過構建一組分類器,而後根據它們的預測結果進行加權投票來對新的數據點進行分類。原始的集成方法是貝葉斯平均,可是最近的算法包括糾錯輸出編碼、Bagging 和 Boosting。

對於非監督式的學習,有以下經典算法。

  1. 聚類算法(Clustering Algorithms)。聚類算法有不少,目標是給數據分類。
  2. 主成分分析(Principal Component Analysis,PCA)。PCA 的一些應用包括壓縮、簡化數據,便於學習和可視化等。
  3. 奇異值分解(Singular Value Decomposition,SVD)。實際上,PCA 是 SVD 的一個簡單應用。在計算機視覺中,第一我的臉識別算法使用 PCA 和 SVD 來將面部表示爲「特徵面」的線性組合,進行降維,而後經過簡單的方法將面部匹配到身份。雖然現代方法更復雜,但不少方面仍然依賴於相似的技術。
  4. 獨立成分分析(Independent Component Analysis,ICA)。ICA 是一種統計技術,主要用於揭示隨機變量、測量值或信號集中的隱藏因素。

上面的這些相關算法來源自博文《The 10 Algorithms Machine Learning Engineers Need to Know》。

https://www.kdnuggets.com/2016/08/10-algorithms-machine-learning-engineers.html

相關推薦

學習機器學習有幾個課是必需要上的,具體以下。

除了上述的那些課程外,下面這些資源也很不錯。

值得翻閱的圖書。

  • 《機器學習》,南京大學周志華教授著。它是一本機器學習方面的入門級教科書,適合本科三年級以上的學生學習。
  • A Course In Machine Learning,馬里蘭大學哈爾·道姆(Hal Daumé III)副教授著。 這本書講述了幾種經典機器學習算法,包括決策樹、感知器神經元、kNN 算法、K-means 聚類算法、各類線性模型(包括對梯度降低、支持向量機等的介紹)、機率建模、神經網絡、非監督學習等不少主題,還講了各類算法使用時的經驗技巧,適合初學者學習。此外,官網還提供了免費電子版。
  • Deep Learning,麻省理工學院伊恩·古德費洛(Ian Goodfellow)、友華·本吉奧(Yoshua Benjio)和亞倫·考維爾(Aaron Courville)著。這本書是深度學習專題的經典圖書。它從歷史的角度,將讀者帶進深度學習的世界。深度學習使用多層的(深度的)神經元網絡,經過梯度降低算法來實現機器學習,對於監督式和非監督式學習都有大量應用。若是讀者對該領域有興趣,能夠深刻閱讀本書。本書官網提供免費電子版,但不提供下載。實體書(英文原版或中文翻譯版)能夠在網上買到。
  • Reinforcement Learning,安德魯·巴託(Andrew G.Barto)和理查德·薩頓(Richard S. Sutton)著。這本書是強化學習(Reinforcement Learning)方面的入門書。它覆蓋了馬爾可夫決策過程(MDP)、Q-Learning、Sarsa、TD-Lamda 等方面。這本書的做者是強化學習方面的創始人之一。強化學習(結合深度學習)在圍棋程序 AlphaGo 和自動駕駛等方面都有着重要的應用。
  • Pattern Recognition and Machine Learning ,微軟劍橋研究院克里斯托夫·比肖普(Christoph M. Bishop)著。這本書講述了模式識別的技術,包括機器學習在模式識別中的應用。模式識別在圖像識別、天然語言處理、控制論等多個領域都有應用。平常生活中掃描儀的 OCR、平板或手機的手寫輸入等都屬於該領域的研究。

15 | 時間管理:同扭曲時間的事兒抗爭

主動管理

  • 你要主動管理的不是你的時間,而是管理你的同事,管理你的信息

仿照一下之前在 Outlook 裏設置工做日程的方式,把你的工做安排預先設置到一個能夠共享的日曆上,而後分享給你們,讓你們瞭解你的日程。

學會說「不」

  • 給出另外一個你能夠作到的方案,而不是把對方的方案直接回絕掉
  • 我不說我不能徹底知足你,但我說我能夠部分知足你

我不能說不,可是我要有條件地說是。並且,我要把你給個人壓力再反過來還給你,看似我給了需求方選擇,實際上,我掌握了主動。

「積極主動的態度下對於不合理的事討價還價」。只有學會了說「不」,你纔可以控制好你的時間。

加班和開會

開會,不是討論問題,而是討論方案,開會不是要有議題,而是要有議案。

16 | 時間管理:如何利用好本身的時間?

投資本身的時間

  • 花時間學習基礎知識,花時間讀文檔:系統地學習一門技術是很是關鍵的,因此這個時間是值得投資的。
  • 花時間在解放本身生產力的事上:花時間在解放本身的事上是最有意義的了
  • 花時間在讓本身成長的事上
  • 花時間在創建高效的環境上

規劃本身的時間

  • 定義好優先級:有 to-do list 並非什麼高深的事。更重要的是,你要知道什麼事是重要的,什麼事是緊急的,什麼事重要但不緊急,什麼事又重要又緊急。
  • 最短做業優先:先把能夠快速作完的事作完,看到 to-do list 上劃掉一個任務,看到任何的數據在減小,對於本身也好,對於老闆也好。老闆能夠看到你的工做進度飛快,一方面有利於爲後面複雜的工做爭取更多的時間。
  • 想清楚再作:對於一些沒想清楚的事,或是本身不太有信心的事,仍是先看看有沒有已有的成熟解決方案或是找更牛的人來給你把把關,幫你出出主意,看看有沒有更好、更簡單的方式。
  • 關注長期利益規劃:要多關注長遠能夠節省多少時間,而不是當前會花費多少時間。長期成本會比短時間成本大得多。因此寧肯在短時間延期,也不要透支將來。學會規劃本身的行動計劃,不是短時間的,而是一箇中長期的。按季度來規劃,這個季度作什麼,達到什麼目標,一年往前走四步,而不是隻考慮眼下。

用好本身的時間

  • 將軍趕路不追小兔:學會過濾掉與本身目標無關的事,不要讓那些無關的事控制本身。知道哪些是更有效的路徑,是花時間改變別人,仍是花時間去尋找志同道合的人。不與不如本身的人爭論,也不要嘗試花時間去叫醒那些裝睡的人,這些都是很是浪費時間的事。多花時間在有產出的事上,少花時間在說服別人的事上。
  • 造成習慣:將文章中提到的方法和幾個要點,寫在某本書或者筆記本的扉頁上,方便查看,時刻提醒本身。
  • 造成正反饋:要讓本身有正反饋,那就須要把時間花在有價值的地方,好比,解決本身和他人的痛點,這樣你會收穫別人的讚賞和鼓勵。
  • 反思和觸類旁通:能夠嘗試每週末花上點時間思考一下,本週作了哪些事兒?時間安排是否合理?還有哪些能夠優化提升的地方?有點兒相似於咱們常說的「覆盤」。而後思考一下,下週的主要任務是什麼?並根據優先級規劃一下完成這些任務的順序,也就是作一些下週的工做規劃。

17 | 故障處理最佳實踐:應對故障

目前沒有遇到實際場景,略過。

18 | 故障處理最佳實踐:故障改進

目前沒有遇到實際場景,略過。

19 | 答疑解惑:咱們應該可以識別的表象和本質

本質上來講,並非只有找到了相應的工做咱們才能夠學好一項技術,而是,咱們在經過解決實際問題,在和他人討論,得到高手幫助的環境中,才能更快更有效率地學習和成長。

關於技術和價值

一項有價值的技術,並不在於這項技術是否有技術含量,而是在於:

  • 可否低成本高效率地解決實際問題;

軟件天生就是用來完成重複勞動的,天生就是用來作自動化的。

  • 是否是衆多產品的基礎技術;

基礎技術老是枯燥和有價值的。數學、算法、網絡、存儲等基礎技術吃得越透,就越容易服務上層的各類衍生技術或產品。

  • 是否是能夠支持規模化的技術。

能規模化低成本高效率解決實際問題的技術及其基礎技術,就算是很 low,也是頗有價值的。

### 關於趨勢和將來

這個世界的技術趨勢和將來實際上是被人控制的,因此對於咱們這些在這個世界裏排不上號的人來講,只能默默地跟隨着這些大公司所引領的趨勢和將來。對一些缺錢缺人的創業公司,惟一可以作的,也許只是兩條路,一是用更爲低的成原本提供和大公司相應的技術,另外一條路是在細分垂直市場上作得比大公司更專更精。等着本身有一天長大後,也能加入第一梯隊從而「引領」將來。

20 | Git協同工做流,你該怎麼選?

Git一直在使用,略過。

相關文章
相關標籤/搜索