你居然寫出這樣的代碼

上週開會時,跟同事在討論,什麼是好的代碼。前端

什麼是好的代碼,怎麼定義好的代碼。程序員

往簡單了說,本身剛寫的代碼都是好的代碼,別人寫的都是垃圾。 往復雜了說,高內聚,低耦合,OCP、SRP、ISP,各類概念能寫一本厚厚的書。其實這事就跟評價程序員的工做同樣,一天寫1000行代碼的程序員必定比一天寫100行代碼的程序員好嗎?編程

大佬們閒着無聊也在討論這個問題,而已已經爭論了幾十年,其中以Martin大叔的這句話最爲經典。後端

衡量代碼質量的惟一有效標準:WTF/min —— Robert C. Martin設計模式

再配上這幅經典的圖,幾乎能夠完美的定義,什麼是好的代碼。markdown

沒有最好的代碼,只有捱罵的代碼,捱罵的多少,決定了代碼的好壞。架構

那麼怎麼才能寫出少捱罵的代碼呢。

從宏觀上來說,就是「整潔」二字,這也是《代碼整潔之道》這本書的核心。框架

整潔的代碼有幾個核心:函數式編程

  1. 風格整潔
  2. 邏輯整潔

首先,寫代碼最好有一些潔癖,變量命名前綴、函數名、換行空行,這些最基本的格式,最好能作到團隊統一,至少是我的統一,每次寫完一部分代碼,經過格式化來統一風格。函數

整潔的代碼如同優美的散文。—— Grady Booch

寫代碼其實跟文學創做同樣,古人做詩,首先看的平仄對仗,音律押韻,只有風格統一,才能在看的時候有一種賞心悅目的感受。

其次,寫代碼要先思考,程序員寫的代碼其實並非給機器看的,而是給人看的。好的代碼、很差的代碼,在機器看來,其實並無太大的區別(除了效率之外),無非都是機器碼。

任何一個傻瓜都能寫出計算機能夠理解的代碼。惟有寫出人類容易理解的代碼,纔是優秀的程序員。—— Martin Fowler

寫代碼不是爲了炫技,一段難讀的代碼,老是會招致更多的WTF。這也是爲何Kotlin的語法糖在有些場合常常被WTF的緣由,團隊內的每一個人的思考角度、思路可能都不相同,因此有時候最簡單的代碼反而是最好的代碼,Java的代碼雖然語法冗長,廢話多,可是讀上去就像是白話文,更容易理解、維護。而反觀Kotlin,若是對語法糖理解不夠深刻、對函數式編程的理念模棱兩可,就很容易寫出四不像的代碼,俗稱Java風格的Kotlin代碼,不少人寫Kotlin,僅僅是爲了使用那些語法糖,少寫幾行代碼而已。

以上,咱們能夠總結下,從宏觀上看,怎麼寫好代碼。

  1. 規範命名風格,好比說公開變量與私有變量的區分,資源命名統一拼音仍是翻譯,至少不要寫出generateWoDeDaiMa這樣的命名
  2. 通用流程統一代碼模板,好比說請求接口,展現列表數據,刷新與加載更多,這樣的操做盡可能統一一種寫法,避免千人前面
  3. 函數單一職責,儘可能函數式編程,作到函數無反作用,減小成員變量、全局標記變量的使用

那麼再具體一點,從移動端的角度來看看什麼是好的代碼。

移動端,或者說是大前端,與後端有很大的不一樣,後端代碼偏邏輯代碼,界面不多,大部分的維護,也是邏輯上的改動,而大前端則相反,UI和邏輯幾乎綁的很死,大部分時間的修改,都是在處理UI。

在理解了這一點以後,你就能站在一個更高的維度來嘲笑那些爲了選擇使用MVC、MVP、MVVM仍是MVVVVVIP而爭論不休的人了,其實這些爭論的出發點就有問題,站在前端的角度,這些所謂的分層,很難在全部代碼中都合適,藉助大佬的一句話「軟件工程沒有銀彈」。

在後端架構中,經過MVC這些分層架構的解耦,確實可讓總體利於維護、拓展,可是在前端,不論是MVC仍是MVP,都必須針對特定的使用場景。

移動端的業務場景,大體能夠分爲兩類,業務邏輯代碼和功能邏輯代碼。

對於功能邏輯代碼來講,與後端相似,良好的架構可讓這部分代碼變的更加健壯,而對於業務代碼來講,這些架構反而容易顯得多餘,相信不少人都有被Presenter弄瘋的經歷,本來很是簡單的業務邏輯,因爲使用了MVP,在修改的時候,須要冗餘的修改一堆代碼。因此,偏業務邏輯的代碼,咱們的思路是——寫容易刪除的代碼。

業務邏輯代碼一般不包含太多複雜的邏輯(若是有,那就應該拆入功能邏輯代碼),並且大部分狀況下,這些要處理的邏輯和UI綁定在一塊兒,因此,這個時候,寫容易刪除的代碼,可讓業務變得更加容易維護,畢竟在如今的迭代條件下,沒有一段無辜的代碼能夠活過下個大版本。

那麼有鋼筋會說了,難道這些大師這麼多年的經驗都毫無用處了嗎?

固然不是,架構必須結合具體的業務來設計,前面講了,邏輯功能業務,該怎麼架構怎麼架構,設計模式什麼的,能寫多少寫多少。而純業務功能,設計模式,則是能寫多少寫多少。

對於業務功能來講,一般只在合適場景的局部使用這些設計模式或者說分層架構思想。

舉個例子,APP中有些組件的設計是有殊途同歸之妙的,這些東西,能夠被稱之爲組件,好比統一彈窗、統一按鈕、對話框、再好比大一點的,起點讀書,書架列表中的一欄,這些東西可能在不少地方都有使用,這時候,MMVM中的VM,就能夠派上用場了,經過抽取ViewModel,可讓UI的複用性增強,經過builder、策略模式、工廠模式等設計模式,能讓代碼的複用度更高、使用性更好。

那麼再再具體一點,具體的代碼,要怎麼寫,纔是好的代碼呢

資深程序員楊過曾經也在思考什麼是好的代碼這個問題,想不通跳崖了,不過好在最後塞翁失馬,朝聞道,夕可死矣。

紫薇軟劍,三十歲前所用,誤傷義士不祥,乃棄之深谷

玄鐵重劍,重劍無鋒,大巧不工,四十歲前恃之橫行江湖

四十歲以後,不滯於物,草木竹石都可爲劍,自此精修,漸進於無劍勝有劍之境

這實際上就是程序員的真實寫照,剛畢業的程序員,意氣風發,拿着鍵盤準備開天闢地,代碼怎麼寫牛逼就怎麼寫,套上各類框架、各類分層、各類設計模式,寫完還不忘加上註釋,這是一段獨孤求敗的代碼。再以後,被業務的毒瘤磨平了棱角,開始返璞歸真,每一行代碼都寫的穩如狗。最後,寫代碼已經進入忘個人摸魚境界,常常幾天不寫一行代碼,一寫就是好幾行。

因此,楊過在四十歲的時候才理解的真諦,咱們如今要早點理解了,否則35歲可能就失業了。

首先,沒有一種思想是永恆的。十年前,面向對象纔是編程的王道,十年後,函數式編程異軍突起。十年河東十年河西的事情,在軟件開發界太多了,誰能想到C#中的協程概念,竟然在多年後,被Kotlin帶火了,年輕的程序員們不要爲了站隊那種思想而爭論不休,能解決問題的思想纔是好的思想,多去了解不一樣的思想,讓它們在你體內碰撞碰撞,說不定就一團漿糊了(徹底理解了)。

其次,想好再碼,先作到胸中有碼,才能眼中無碼,寫代碼前先花點時間整理下邏輯,理清楚分支狀況和異常狀況,而後再去動手,不急着那一點時間,又不是比誰敲得快。

再次,慎用繼承,這個要單獨拎出來講了。

繼承,面向對象開發的三大核心原則之一。繼承,規範了子父類具備相似行爲的類,可是也帶來了著名的香蕉猴子叢林(Banana Monkey Jungle)問題,相信不少開發者都遇到過這種問題,當你準備從另外一個項目中copy一個類到現有的工程,或者修改一個新引入的類時,你會發現,還須要copy它的父類,甚至還有父類的父類,以及一連串的類,更不要提繼承的菱形問題了。

面嚮對象語言的問題在於,每一個類都隨身攜帶了一個隱形環境。您想要香蕉,可是獲得的是一隻拿着香蕉的猴子和整個叢林。

因此,繼承要慎用,可是怎麼解決呢?其實能夠從兩方面來解決,一個是經過修改架構,儘量避免無效、過分的繼承設計,另外一個是經過接口來進行行爲的約束而不是經過繼承,儘量經過組合的方式來進行架構。

在Flutter/Dart中,這種方式被表現的淋漓盡致,Flutter的總體設計思想就是組合,萬物基於組合,另外還提供了mixin來提供功能的混入,在毫無壓力的狀況下使用其它類的功能,而不是經過繼承。

古今之成大事業、大學問者,必通過三種之境界: 「昨夜西風凋碧樹,獨上高樓,望盡天涯路。」 此第一境也。 「 衣帶漸寬終不悔,爲伊消得人憔悴。」 此第二境也。 「 衆裏尋他千百度,驀然回首,那人卻在,燈火闌珊處。」此第三境也。

對Flutter感興趣的朋友能夠加入個人Flutter修仙羣。

相關文章
相關標籤/搜索