一份擁有良好可讀性和拓展性的代碼是項目里的良藥,它不僅看著舒服,改起來也方便,甚至還能重用,各模塊邏輯分明。“見碼知功底”,而要達到高手那種簡潔有力的境界,需要進行大量的總結和練習,今天我們就來談談如何寫出優美的代碼。 命名 好的命名應該具有如下特征: 1,意思正確。這是最基本的要求,不要掛羊頭賣狗 ...
一份擁有良好可讀性和拓展性的代碼是項目里的良藥,它不僅看著舒服,改起來也方便,甚至還能重用,各模塊邏輯分明。“見碼知功底”,而要達到高手那種簡潔有力的境界,需要進行大量的總結和練習,今天我們就來談談如何寫出優美的代碼。
命名
好的命名應該具有如下特征:
1,意思正確。這是最基本的要求,不要掛羊頭賣狗肉,詞不達意,要一眼就知道什麼意思。就算一眼看不出來,複製到有道詞典翻譯一下也能知道什麼意思;
2,單複數分明。如果是一個數組,要麼加s/es結尾表明其是複數,要麼加入list表示它是一個數組。如cars,carList都可以表達一個車的列表;
3,慎用縮略詞。縮略詞可以讓我們的命名更加簡潔,但是一!定!要!是!業!界!通!用!縮!略!詞!比如info原意為information,msg原意為message,fn原意function,conf原意config等等,這些縮略詞都是業內傳統了,大家都知道什麼意思,切記不要自己亂造縮略詞;
4,有具體含義。根據業務場景去命名,而不是根據抽象命名;比如getUnreadMsgList,一看就知道是獲取未讀消息列表的意思,而getData這種說了跟沒說一樣,缺乏具體含義。
註釋
有表達力的代碼是不需要註釋的。比如一個init函數,一看就知道是用於做一些初始化的工作,沒必要寫多餘的註釋來說明。
但是有一些場景註釋是非常有必要的,下麵幾種場景要添加註釋:
1,一些針對特殊業務場景而訂製的特殊邏輯。比如當我們更新個人信息的時候,由於後端的問題,需要少傳一個諸如生日的信息,或者更新頭像時要多傳一個時間戳來供其他業務以後使用。這些莫名其妙的增刪屬性,如果不加以註釋,將導致後續自己都無法理解;
2,可能會出現隱患的代碼。由於自身水平所限,或者本身技術上就無法實現,只能通過一些特殊技巧來仿製一些效果,往往會存在安全隱患,比如:用戶操作太快會出問題,網路太慢會出問題,某個介面調不通這頁面會全掛了,一些特殊的操作會引起的暫時無法解決的bug等等場景,都需要註釋說明;
3,涉及到某些高深的或者生僻的技術知識。這種也要註釋,以提醒自己和其他開發者。
一般來說,註釋基本上都是在表達“這裡我為什麼這麼做”,很少有註釋會去表達“我是一個什麼玩意兒”,如果是後者的註釋,只能說明命名沒做好。
函數
函數是代碼的靈魂,也是寫邏輯的載體,以下幾個要求是判斷一個開發者函數寫的好不好的標準。
1,是不是單一職責。一個函數應該只做一件事,而這件事應該能通過函數名就可以清晰的展示。這是一個非常好的特性,一個辣雞的函數可能動輒幾百行代碼,各種邏輯堆積在一起,看得人頭腦發暈,甚至開發者自己都理不清楚;判斷這個函數是不是單一職責的技巧很簡單:看看它還能不能再拆分。
2,有沒有層級之分。函數與函數之間是有身份地位之分的,有負責整體大局觀的高級函數,也有專註細節的打工仔低級函數。如果不建立起層級結構,就容易迷失在細節的海洋里。比如:
對於做一頓飯這個函數來說,他不需要關心諸如買菜時反覆挑選這種細節,它只需要知道,大概有三個大步驟就行了。所以這段邏輯會根據其地位拆分出不同等級的函數,假設沒有層級之分,那麼從第一步的“搭公交”一直寫到最後一步的“倒垃圾”,這東西會變得極難維護。
3,承載的場景是否足夠簡單。有時候我們會遇到這樣一種場景:一個函數在很多地方都會用到,但是不同地方傳入的參數不一樣,這樣我們為了函數的通用性,就針對入參做了很多種場景的識別,導致入參非常多,裡面還需要根據不同的場景做邏輯上的細微調整。所以單單是取傳入參數都夠嗆了,一堆的if else或switch case。
這個函數太難了,而且這已經違背了函數的單一職責原則,它在裡面做了多種場景的判斷,從而表現出不同的行為,但這些行為又不是完全不同,而是“大體相同”,如果重寫好像又會增加很多的重覆的代碼。解決的方法是做更小粒度的拆分,將那些真正與業務脫鉤的部分抽離出來,而不同場景對應不同的處理函數,剛剛抽離的業務脫鉤函數正好作為這些不同場景函數公共部分!