天天看點

高品質的工程代碼為什麼難寫

轉載自:http://hellojava.info/?p=508

作者:阿裡畢玄

之是以想起寫這篇文章,是因為最近看到的一個著名的開源項目在内部使用時的各種問題,不得不說,很多的開源的東西思想是不錯的,但離真正工程化都有不小的距離,是以沒什麼商業公司采用的開源産品如果要引入的話一定要慎重,通常會有n多的坑等着你去填,而比較成功的開源項目的背後多數都會有商業公司在背後不斷的改進。

遙想我00年開始學習寫asp代碼時,覺得寫代碼也不難呀,無非就是學學文法規則、庫就可以寫出來,記得有一次我實習面試的時候是讓我在一個下午左右的時間寫一個完整的留言闆,那也就是刷刷刷就寫好了,但随着後來工作,尤其是加入阿裡以後,越來越明白高品質的工程代碼為什麼難寫。

在寫代碼初期,最關注的是如何用代碼實作需求,如果是僅僅實作業務需求的話,即使是剛上手的程式員,隻要解題能力還ok,基本上都是可以寫出代碼來的,是以我自己一直認為數學成績是程式員的一個非常重要的要求,數學好的人通常解題和邏輯思維能力是還不錯的。

上面的這個基本的寫代碼的過程中,寫的更好的同學的展現會在對業務的深刻了解以及抽象上,寫出的代碼會具備一定的複用能力,這個在這裡不多加探讨。

但代碼是不是實作了業務需求就結束了呢,其實遠沒有,這其實隻是寫代碼的開始,除了正向的邏輯實作外,任何一個點的異常的分支邏輯怎麼處理才是工程化的代碼中更難處理的部分,這個問題在單機式的系統中會相對還好處理,在分布式的環境會變得非常的複雜,例如調用其他機器的功能逾時了,出錯了,到底該怎麼處理,這也是為什麼有了那麼多的分布式的理論的東西出來,在增加了異常分支的處理邏輯後,通常會發現這個時候正向邏輯的代碼在整個代碼的占比中會大幅下降。

異常分支邏輯處理好後,通常還需要增加必要的日志資訊,以便在出問題時友善排查,而不是到了要排查問題的時候,一點目前系統的狀況都搞不清楚,是以吃掉重要的異常資訊不抛出這種行為在寫代碼中是非常可恥的。

在處理好上面異常的相關動作後,代碼的健壯性也要處理好,這個主要指:

1. 自我保護能力

對外提供的接口是否具備足夠的自我保護能力,就是即使使用的人沒仔細看api文檔随便亂用也不會導緻系統出問題,這種案例非常的多,例如對外提供了一個批量查詢接口,結果使用者一下傳了一個裡面有上千個使用者id的數組,查詢一下直接把記憶體耗光,像這種情況下不能怪使用的人,而應該怪實作api的這一端的保護做的不夠好,按照這樣的标準去看,會發現開源的很多東西的api都不太合格;

還有一種就是能力保護,如果超出了處理的并發量的能力,這個時候會發生什麼;

2. 對資源的使用限制

這也是代碼新手或一些開源産品中做的比較差的地方,很容易出現規模一上去,資源使用量也一直漲,沒有限制,然後導緻系統挂掉,很常見的案例是對線程池的使用,例如像java中的executors.newcachedthreadpool,這個接口很多人會用到,但很多用的人都沒有仔細想過會不會在某種情況下這裡建立出巨多的線程;還有例如用map做cache,也沒考慮大小限制的問題,結果就是随着資料量增長,某天突然就挂了;

健壯性是代碼中比較複雜的部分,通常也是比較展現代碼能力的部分,可能看起來就幾行代碼,但其實背後反映的差距是巨大的。

開源産品除了在健壯性上的差距外,通常還會出現的一個巨大差距就是整個系統的設計的伸縮能力,伸縮能力不夠的話通常會導緻結構性的重構,另外常見的就是在并發的處理上不夠高效,例如鎖的合理使用、無鎖算法的引入等等,而這些需要非常強的系統設計和代碼功底能力。

除了上面說的這些外,高品質的工程代碼還需要考慮可維護(例如監控資訊暴露)、安全性等,對我而言,我一直認為所謂的工程化其實就是把一些玩具性質的代碼變成可在商業系統中真正健壯運作的代碼。

上面的内容寫的比較簡略,不過應該也能看出,對于高品質的工程代碼而言,其實實作業務邏輯隻是其中占比很小的一部分,甚至花的時間是相對最少的一部分,是以我确實非常贊同面試的時候讓同學寫代碼,這個時候很容易看出同學寫代碼的功力;有些時候為了考察同學寫代碼的熟練程度,我會問問ide的快捷鍵,或者讓手寫一段不是太複雜的代碼。

高品質的工程代碼為什麼難寫