不久之前玷犹,我看了一篇文章混滔,大意是Kotlin與Java之間的對(duì)比,像這種文章,我一般是直接忽略的坯屿,但是那天我還是打開了油湖,然后就看到一個(gè)非常吃驚的結(jié)果。
里面有一段是關(guān)于Kotlin與Java之間可讀性的對(duì)比的文章领跛,作者的結(jié)論是:Kotlin并不比Java更具有可讀性乏德,所有認(rèn)為Kotlin 比Java更具有可讀性的結(jié)論都是“主觀性”的。
并且作者舉了一個(gè)在我看來(lái)吠昭,不知道該怎么來(lái)描述的例子:
這個(gè)作者的大意是喊括,上面這段文章,你多讀個(gè)兩三遍矢棚,你也會(huì)很快的理解它的意思郑什,所以“對(duì)于熟練的讀者而言,外觀很少會(huì)成為可讀性的障礙蒲肋∧⒄”
我不知道,如果某一天肉津,這個(gè)作者突發(fā)奇想强胰,決定全部使用大寫字母來(lái)寫代碼——所有的類名、方法名妹沙、局部變量成員變量名等等全部使用大寫偶洋,我不知道跟作者合作的同事是不是會(huì)欣然的耐心的把作者所有的代碼先讀它個(gè)兩三遍,然后再來(lái)慢慢的理解它的意思距糖。如果是我玄窝,我不會(huì)。如果在小紅書有個(gè)同事非要執(zhí)意這樣寫代碼悍引,理由是“你多讀個(gè)兩三遍不就好了嘛恩脂?”我想我只能把他開除了。
其實(shí)趣斤,如果一段代碼需要你多讀個(gè)兩三遍才能很好的理解俩块,這本身不就說(shuō)明,這段代碼的可讀性不高嗎浓领?這里的重點(diǎn)是玉凯,這里的這一段大寫的文字你看個(gè)三遍,再看的話联贩,是熟悉了漫仆,但是再看別的用大寫寫的文字片段,你依然要很費(fèi)勁泪幌。所以盲厌,這個(gè)例子是不能代表大寫這種風(fēng)格的可讀性的署照。在比較兩種不同的風(fēng)格的可讀性的時(shí)候,你不能用具體的某一個(gè)一次性的片段來(lái)說(shuō)明吗浩。
另外建芙,這篇文章還暗含了這樣一個(gè)觀點(diǎn),那就是拓萌,代碼的可讀性岁钓,僅僅是指,看到一段代碼微王,能不能理解這段代碼的含義屡限。這是一個(gè)很多人都會(huì)錯(cuò)誤的觀點(diǎn)。
但是炕倘,在真正工作中钧大,代碼的可讀性,恐怕不至這一個(gè)方面罩旋。為了考察所謂代碼的可讀性涉及到哪些方面啊央,我們來(lái)假設(shè)兩個(gè)case:1. 你去到一家新公司,接手一個(gè)新項(xiàng)目涨醋。這個(gè)時(shí)候瓜饥,你的需求是,快速了解某個(gè)類浴骂、某個(gè)模塊乓土、某個(gè)方法做的是什么事情。在這個(gè)基礎(chǔ)上溯警,整個(gè)app趣苏、模塊的結(jié)構(gòu)是怎么樣的。2. 你老板叫你fix一個(gè)bug梯轻,這個(gè)bug是另外一個(gè)同事寫的食磕,今天這個(gè)同事請(qǐng)假了不在。在這個(gè)case里面喳挑,你需要的是彬伦,快速的定位到出問(wèn)題的代碼在什么地方,然后再盡快的了解這個(gè)地方的代碼做了什么事情伊诵,并且保證你的理解是對(duì)的单绑。
所以,總結(jié)一下日戈,代碼的可讀性,可以歸納成三點(diǎn):
- 理解一段代碼的速度
- 找到你關(guān)心的代碼的速度
- 確保正確理解一段代碼的難易程序孙乖。這跟第一點(diǎn)看似一樣浙炼,其實(shí)還真不一樣份氧,下面你會(huì)看到。
下面弯屈,依次解釋一下這三點(diǎn)蜗帜,以及為什么說(shuō),Kotlin的可讀性會(huì)對(duì)Java高资厉。
1. 理解一段代碼的速度
如果大家仔細(xì)的思考下厅缺,你會(huì)發(fā)現(xiàn),我們?cè)诶斫庖欢未a的時(shí)候宴偿,大多數(shù)情況下湘捎,我們是想要了解這段代碼做了什么事情,是這段代碼的意圖(Intention)窄刘,而不是具體這個(gè)事情是怎么做的窥妇。比如一個(gè)Button被點(diǎn)擊了,我們的App做了什么娩践,是做了什么運(yùn)算活翩,發(fā)了網(wǎng)絡(luò)請(qǐng)求,還是保證了一些數(shù)據(jù)到數(shù)據(jù)庫(kù)翻伺。也就是說(shuō)材泄,大多數(shù)情況下,我們關(guān)心的是What吨岭,而不是How拉宗。只有少數(shù)情況下,我們會(huì)關(guān)心“How”未妹,一是出于學(xué)習(xí)的目的簿废,我們想要了解一個(gè)算法是怎么實(shí)現(xiàn)的,一個(gè)效果是怎么實(shí)現(xiàn)的络它,這個(gè)時(shí)候族檬,我們會(huì)關(guān)心“How”。二是當(dāng)這個(gè)“How”出了問(wèn)題的時(shí)候化戳,就是有了Bug单料,我們要去了解這個(gè) “How”,然后再fix過(guò)來(lái)点楼。而且扫尖,即使是在這些少數(shù)情況下,了解“How”的過(guò)程掠廓,也只不過(guò)是了解一個(gè)個(gè)子“What”的過(guò)程换怖。
敏捷開發(fā)和TDD先驅(qū)、JUnit開發(fā)作者和一系列經(jīng)典編程書籍作者Kent Beck提出了一個(gè)著名的“four rules of simple design”蟀瞧,是以下4條:
- Passes the tests
- Reveals intention
- No duplication
- Fewest elements
第一條Passes the test說(shuō)的是程序的正確性沉颂。第二條Reveals Intention条摸,說(shuō)的就是我們這里討論的“What”。
那么铸屉,Kotlin相對(duì)于Java钉蒲,在幫助我們了解“What”,在幫助Reveals Intention這方面彻坛,有什么樣的優(yōu)勢(shì)呢顷啼?
我們看一個(gè)簡(jiǎn)單的例子:
在這段Java代碼例子中,這7行代碼做的事情很簡(jiǎn)單昌屉,就是從personList中找出id值等于somePersonId
這個(gè)變量的值的那個(gè)Person钙蒙,然后賦值給person
這個(gè)變量。要理解這段代碼并不難(其實(shí)后面你會(huì)看到怠益,要確保正確理解這么代碼也沒那么簡(jiǎn)單)仪搔,但是速度并不快,你必須從頭到尾看完這8行代碼蜻牢,就算你說(shuō)最后兩行可以一掃而過(guò)烤咧,那也必須看完前面6行,你才能知道“哦抢呆,原來(lái)這段代碼做的事情是煮嫌,從personList中找出id值等于。抱虐。昌阿。”
下面恳邀,我們來(lái)看對(duì)應(yīng)的Kotlin代碼是怎么樣的:
val person = personList.find { it.id == somePersonId }
是的懦冰,就一行代碼∫シ校看完這行代碼刷钢,你就知道了它做的是什么事情。因?yàn)樵谶@行代碼中乳附,find
這個(gè)單詞就已經(jīng)表達(dá)出了這里做的事情是“找出一些東西”内地,而大括號(hào)里面,就是找出它的條件赋除。也就是說(shuō)阱缓,Kotlin的寫法直接就幫我們表達(dá)出了“What”。如果平均來(lái)說(shuō)举农,一個(gè)人理解一行Java代碼的速度跟理解一行Kotlin代碼的速度是一樣的(雖然在我看來(lái)荆针,理解一行Kotlin代碼會(huì)更容易,因?yàn)镵otlin里面有很多幫助開發(fā)者減輕負(fù)擔(dān)的語(yǔ)法,接下來(lái)會(huì)提到這一點(diǎn))航背,那么在這個(gè)例子中秸妥,一個(gè)人理解Kotlin代碼的速度是理解對(duì)應(yīng)的Java代碼的5~6陪。之所以說(shuō)5~
沃粗,是因?yàn)樵贘ava里面,你還可以寫成foreach語(yǔ)法键畴,如果寫成foreach語(yǔ)法的話最盅,那么Java代碼是5行。但是以我的經(jīng)歷起惕,多數(shù)情況下大家還是會(huì)習(xí)慣性的寫成fori涡贱,因?yàn)檫@兩者差別并沒那么大,優(yōu)勢(shì)也不是那么明顯惹想。
在Kotlin里面问词,Collection
類有一整套像find
這樣,直接可以reveal intention的方法嘀粱,簡(jiǎn)單點(diǎn)的有filter
激挪、count
、reduce
锋叨,map
垄分、any
、all
等等娃磺,高級(jí)點(diǎn)的有mapTo
薄湿、zip
、associate
偷卧、flatMap
豺瘤、groupBy
等等。絕大多數(shù)情況下听诸,所有需要手動(dòng)for循環(huán)的地方坐求,都有對(duì)應(yīng)的更加能“reveal intention”的方法。
當(dāng)然蛇更,如果只有一個(gè)collection
瞻赶,就說(shuō)Kotlin在Reveal Intention
這點(diǎn)上比Java更有優(yōu)勢(shì),那是不夠的派任。Kotlin有一系列的機(jī)制和便利砸逊,能幫助開發(fā)者更好的達(dá)到“Reveal intension”的目。比如null
的處理掌逛,if
师逸、when
表達(dá)式(不是語(yǔ)句),比如循環(huán)的處理豆混,比如所有對(duì)象都有的let
, apply
, run
等方法篓像,比如data class以及它的copy
方法等等等等动知。此外,通過(guò)Extension Function這個(gè)機(jī)制员辩,Kotlin對(duì)Java中絕大多數(shù)的常用類都作了擴(kuò)展盒粮。前面提到的各種Collection
方法,也是使用這種方式來(lái)進(jìn)行擴(kuò)展的奠滑。此外丹皱,就算有一些類沒有你想要的擴(kuò)展,你也可以非常輕松容易的自己寫一個(gè)擴(kuò)展方法宋税,來(lái)讓你的代碼更加“Reveal Intension”摊崭。
相比之下,跟Kotlin相比杰赛,Java代碼更像逼我們?nèi)ネㄟ^(guò)了解“how”之后呢簸,來(lái)總結(jié)歸納出它的“what”。在描述一門語(yǔ)言的時(shí)候乏屯,有一個(gè)術(shù)語(yǔ)叫做抽象程度根时,也就是一門言語(yǔ)表達(dá)“What”、屏蔽“How”的能力辰晕。從這點(diǎn)來(lái)說(shuō)啸箫,無(wú)疑Kotlin的抽象程度是比Java要高的,就像是C語(yǔ)言的抽象程度比匯編要高一樣伞芹。實(shí)際上忘苛,我還還真有個(gè)朋友拿Java比作匯編。他是寫Scala的唱较,有一天他這么跟我說(shuō)
我之前一年多時(shí)間都是寫Scala的扎唾,現(xiàn)在我看到Java代碼,就像在看匯編一樣南缓。
基于Kotlin的抽象程度更接近Scala胸遇,我想寫一年多Kotlin之后,你也會(huì)有類似的感覺汉形。
OK纸镊,第一點(diǎn)講到這里。接下來(lái)我們來(lái)看第二點(diǎn)概疆。
找到你關(guān)心的代碼的速度
當(dāng)談到Kotlin的優(yōu)勢(shì)時(shí)逗威,有一點(diǎn)我相信是公認(rèn)的,那就是Kotlin比Java更簡(jiǎn)潔岔冀。而簡(jiǎn)潔帶來(lái)的好處之一凯旭,就是能夠讓人更快的找到他關(guān)心的代碼株茶,而不用在一堆雜七雜八的沒用的代碼里面去翻找自己在乎的代碼矮烹。我們還是以一個(gè)例子來(lái)說(shuō)明吧美尸,以下兩段代碼继控。
如果說(shuō),要你找出點(diǎn)擊loginButton
以后嫉柴,代碼做了什么事情厌杜,那以上兩段代碼中,無(wú)疑第二段代碼能讓你更快的找到计螺。
上面這個(gè)例子還大大的簡(jiǎn)化了很多東西期奔,實(shí)際開發(fā)過(guò)程中,代碼更加復(fù)雜危尿,Kotlin的優(yōu)勢(shì)也更明顯。
確保正確理解一段代碼的難易程序
這是很多人會(huì)忽略的事情馁痴。能否理解一段代碼谊娇,跟確保正確的理解這段代碼,其實(shí)中間還是有一些差別的罗晕。很多代碼看起來(lái)很簡(jiǎn)單济欢,但是要確保自己正確的理解,其實(shí)還是非常費(fèi)勁的小渊。還是看文章開頭這個(gè)例子:
這一段代碼要確保正確的理解法褥,容易嗎?其實(shí)沒那么容易酬屉,如果你工作年限多一點(diǎn)半等,你一定碰到過(guò)這樣的代碼,在for
循環(huán)里面呐萨,i
是從1開始的杀饵,而不是從0開始的,或者是中間的終止條件是i < personList.size() - 1
谬擦,而不是i < personList.size()
切距,或者最后部分不是i++
,而是i = i + 2
惨远,或者i--
谜悟。很多人更是碰到過(guò)很多bug,就是因?yàn)闆]有看清楚這里面i的起始值北秽、終止條件葡幸,或者是步長(zhǎng)導(dǎo)致的。我就曾經(jīng)碰到過(guò)很多這樣的bug贺氓,也曾經(jīng)因?yàn)闆]有注意這些地方礼患,而導(dǎo)致過(guò)很多bug,最后調(diào)了半天,發(fā)現(xiàn)原來(lái)是因?yàn)閒or里面是i=1
缅叠,而不是i=0
悄泥。那時(shí)候,就只能在心里默默的大叫一聲:FUCK肤粱!
因?yàn)橛羞@些非典型代碼的存在弹囚,所以現(xiàn)在,每次看到這樣寫的for循環(huán)领曼,我心里都會(huì)覺得如履薄冰鸥鹉,會(huì)特別小心翼翼的看得很仔細(xì),確保i
的初始值是什么庶骄,終止條件是什么毁渗,步長(zhǎng)是什么。這在無(wú)形之中會(huì)給人增加特別大的心理負(fù)擔(dān)单刁。然而因?yàn)槭菬o(wú)形之中的灸异,是潛意識(shí)里面的,所以一般人不會(huì)注意到羔飞。畢竟肺樟,大家都這么寫,而且寫了幾十年了逻淌,能有什么問(wèn)題呢么伯?其實(shí),是有的卡儒。這也是為什么Java5增加了Foreach語(yǔ)法的原因田柔,然而可惜的是,大部分人并不清楚具體為什么要使用foreach骨望,而且還聲稱fori比f(wàn)oreach性能更高凯楔,這真是令人遺憾。
說(shuō)回Kotlin锦募,那為什么說(shuō)Kotlin代碼能讓人更容易正確的理解呢摆屯?
讓我們?cè)倏匆幌律厦娴睦訉?duì)應(yīng)的Kotlin代碼:
val person = personList.find { it.id == somePersonId }
在這一行代碼中,你根本無(wú)需擔(dān)心i的初始值糠亩、終止條件虐骑、步長(zhǎng),因?yàn)檫@里面根本沒有這些東西赎线。所以廷没,一個(gè)很大的心理?yè)?dān)負(fù)消失了。你也不用擔(dān)心這里面有沒有break垂寥,或者你是否忘了寫break颠黎。
這就是Kotlin讓代碼更容易理解的地方另锋。同樣的,像這種減輕看代碼的人心理負(fù)擔(dān)的機(jī)制Kotlin里面有很多狭归,這里再介紹一個(gè)很重要的“小”特性:使用val
把一個(gè)變量定義成不可變的“變量”夭坪。我之前一篇文章說(shuō)過(guò),Kotlin的nullsafety是我最喜歡的特性过椎,如果說(shuō)第二喜歡的特性是什么室梅,那就是val
關(guān)鍵字。在團(tuán)隊(duì)里面疚宇,我也一遍一遍的跟同事強(qiáng)調(diào)亡鼠,能用val
的地方就不要用var
。因?yàn)樗鼛?lái)的心理上的relief敷待,是巨大的间涵。我們看以下LinearLayout
里面的代碼。
如果你寫了個(gè)自定義Layout繼承自LinearLayout
榜揖,結(jié)果它表現(xiàn)出來(lái)的樣子不符合你的預(yù)期勾哩,你可能會(huì)去看源碼「校看到上面這段,最后你發(fā)現(xiàn)物蝙,原來(lái)是mBaselineAlignedChildIndex
這個(gè)成員變量的值不對(duì)炎滞。那么,你怎么知道是哪里改變了這個(gè)變量的值诬乞,導(dǎo)致它被賦給了一個(gè)錯(cuò)誤的值呢册赛?你可能要在這個(gè)類里面找出所有會(huì)改變這個(gè)變量的地方,然后一個(gè)一個(gè)去check震嫉,哪里會(huì)走到森瘪,哪里不會(huì)走到。更糟糕的是票堵,也許這個(gè)值在某個(gè)public方法里面被改變了扼睬,這樣的話,你還要去找出所有調(diào)用這個(gè)public方法的地方悴势,然后去確定到底是誰(shuí)窗宇,在哪里調(diào)用了這個(gè)方法,而這些調(diào)用的地方又是誰(shuí)調(diào)用的特纤,導(dǎo)致出錯(cuò)了军俊。這想想就是一件非常頭疼的事情。
但是捧存,如果這個(gè)值是final
的話粪躬,這些麻煩就都不存在了担败。它的值要么是在它定義的地方就確定了,要么是在構(gòu)造方法里面確定的镰官,你只需要檢查兩個(gè)地方就可以了提前,這對(duì)于代碼理解,是一件極大的減少工作量的事情朋魔。這岖研,就是為什么Effective Java里面,建議把所有能用final
修飾的地方都用final
修飾的原因警检。很多人認(rèn)為孙援,使用final
是為了避免多線程同步的問(wèn)題。但是扇雕,誠(chéng)實(shí)的說(shuō)拓售,算了吧,作為安卓開發(fā)的你镶奉,上一次碰到多線程同步的原因?qū)е乱粋€(gè)變量的值出錯(cuò)础淤,是什么時(shí)候的事了呢?final
的真正優(yōu)點(diǎn)哨苛,在于讓人在看代碼的時(shí)候鸽凶,不用到處去找可能會(huì)改變這個(gè)值的地方,也消去“這個(gè)值會(huì)不會(huì)在哪里被改變”的大心理負(fù)擔(dān)建峭。
思考深入的讀者可能會(huì)發(fā)現(xiàn)玻侥,其實(shí)上面的這個(gè)例子有點(diǎn)矛盾。因?yàn)槲艺f(shuō)的是使用final
來(lái)定義變量亿蒸,但是像上面的mBaselineAlignedChildIndex
這個(gè)成員變量凑兰,是不能加final
的,因?yàn)樗褪且勺兊陌”咚褪切枰谀承l件下被重新賦值的啊姑食,這不是矛盾了嗎?
是的茅坛,很多時(shí)候音半,我們不能使用final
來(lái)定義一個(gè)成員變量。但是贡蓖,如果你試著給那些可以加上final
的成員變量加上final
祟剔,你會(huì)發(fā)現(xiàn),其實(shí)大部分成員變量和幾乎所有局部變量都是可以加上final
的摩梧,但是現(xiàn)實(shí)情況是什么呢物延?是幾乎所有的成員變量和局部變量,我們都沒有使用final
來(lái)定義仅父。我們寫代碼的默認(rèn)設(shè)置是叛薯,先不加final
浑吟,如果在哪個(gè)地方編譯出錯(cuò)了----比如寫一個(gè)匿名內(nèi)部類,引用了前面的局部變量----迫使我們使用final
來(lái)修飾一個(gè)變量的時(shí)候耗溜,我們才加上组力。
為什么會(huì)出現(xiàn)這種情況呢?有兩點(diǎn)原因:
-
final
的好處并不為大家所知抖拴,也不是一眼能看出來(lái)的燎字。 - 使用
final
要寫多寫一個(gè)單詞。
當(dāng)一個(gè)東西的優(yōu)勢(shì)不是很容易被識(shí)別(注意阿宅,不容易被識(shí)別候衍,不代表這個(gè)優(yōu)勢(shì)不大,或者不重要洒放,這是兩回事)蛉鹿,同時(shí)又要多付出一些努力的時(shí)候,我們寫代碼的默認(rèn)設(shè)置是不加final
往湿,這就非常合情合理了妖异。
那Kotlin在這點(diǎn)上,又有什么優(yōu)勢(shì)呢领追?Kotlin的優(yōu)勢(shì)有幾個(gè)他膳,先講一個(gè)不起眼的優(yōu)勢(shì):使用val
來(lái)定義“變量”。這里之所以給“變量”加上雙引號(hào)绒窑,是因?yàn)槭褂?code>val來(lái)定義的“變量”一旦被賦值棕孙,是不能被改變的,所以好像稱他們?yōu)椤白儭绷坎淮蠛线m回论。但我又找不到合適的詞來(lái)叫這個(gè)東西散罕,所以暫且還是稱作“變量”吧分歇。
不要小看了這個(gè)優(yōu)勢(shì)傀蓉。當(dāng)你可以使用var
或val
這兩個(gè)看起來(lái)寫起來(lái)都差別不大的方式來(lái)定義一個(gè)東西的時(shí)候,人們自然會(huì)想要去了解职抡,這兩者到底有什么區(qū)別葬燎?我應(yīng)該使用哪個(gè)?這時(shí)候缚甩,就會(huì)有一些討論谱净,有一些標(biāo)準(zhǔn)出來(lái),人們就會(huì)認(rèn)識(shí)到擅威,不可變性(Immutability)原來(lái)有這么大的價(jià)值壕探,原來(lái)是這么好的一個(gè)東西。同時(shí)郊丛,因?yàn)?code>val和var
寫起來(lái)沒有差別李请,所以人們也會(huì)更愿意使用val
來(lái)定義“變量”瞧筛。
當(dāng)然,要我說(shuō)导盅,kotlin這一點(diǎn)做得還不夠较幌。應(yīng)該像Rust一樣,讓可變的變量定義起來(lái)比不可變的變量定義起來(lái)更費(fèi)勁白翻,這才能更加促進(jìn)不可變量這種好的practice的發(fā)揚(yáng)光大乍炉。
在StackOverflow的調(diào)查中(2017,2016)滤馍,Rust連續(xù)幾年被評(píng)為“程序員最喜愛的語(yǔ)言(Most Loved)”岛琼,這不是沒有原因的,它的設(shè)定也不是沒有原因的纪蜒。
除此之外衷恭,Kotlin還使用了一些方式,來(lái)讓原本不能定義為
val
的變量纯续,也可以使用val
來(lái)定義随珠,比如by lazy
和lateinit
,這些機(jī)制綜合起來(lái)猬错,即讓val
寫起來(lái)很容易窗看,也擴(kuò)大了val
的適合范圍。上面花了很多篇幅來(lái)解釋倦炒,Kotlin中
val
的價(jià)值显沈。跟Collection
中的眾多擴(kuò)展方法一樣,這些都是Kotlin中逢唤,一些讓代碼更容易理解的機(jī)制拉讯。像這樣的機(jī)制還有很多,比如說(shuō)在Kotlin中鳖藕,if魔慷、when(Kotlin中的switch)都是表達(dá)式(Expression,會(huì)返回一些值)著恩,而不像在Java中院尔,只是語(yǔ)句(Statement,不會(huì)有返回值)喉誊,比如說(shuō)對(duì)null
的處理邀摆,如果你看過(guò)多層嵌套的null判斷,你就知道那種代碼看起來(lái)有多費(fèi)勁了伍茄。而使用Kotlin栋盹,結(jié)合val
,在定義的時(shí)候把它定義成非null
敷矫,你可以明顯的告訴代碼的讀者例获,也告訴你自己音念,這個(gè)地方是不需要進(jìn)行null判斷的。這就大大的減少了null
判斷的數(shù)量躏敢。由于篇幅的關(guān)系闷愤,這些還有剩下的一些機(jī)制,這里就不展開講了件余。當(dāng)你寫kotlin代碼的時(shí)候讥脐,多思考一下,Kotlin為什么要這樣設(shè)定啼器,你就會(huì)明白旬渠,都是有原因的,多數(shù)情況下端壳,都是有優(yōu)勢(shì)的告丢。
為什么代碼的可讀性這么重要?
以上從三個(gè)方面解釋了什么叫代碼的可讀性损谦,可以看到岖免,無(wú)論在哪個(gè)方面,Kotlin都有比Java更大的優(yōu)勢(shì)照捡。那接下來(lái)的一個(gè)問(wèn)題就是颅湘,So what?可讀性有這么重要嗎栗精?能吃嗎闯参?值多少錢?
別說(shuō)悲立,可讀性還真可以吃鹿寨,而且很值錢!
關(guān)于可讀性的重要性薪夕,其實(shí)上面分析什么叫可讀性的時(shí)候脚草,已經(jīng)提到了,這里歸納一下寥殖,只說(shuō)兩點(diǎn):
- 更快的找到你關(guān)心的代碼玩讳,更快的理解代碼涩蜘。
要知道嚼贡,我們現(xiàn)實(shí)開發(fā)過(guò)程中,大部分時(shí)間是在看代碼同诫,而不是在寫代碼粤策。更快的理解代碼,意味著更高的工作效率误窖,節(jié)省更多的時(shí)間叮盘,時(shí)間就是金錢秩贰,所以更高的可讀性,意味著省錢柔吼《痉眩或者用省下來(lái)的時(shí)間去賺更多的錢。 - 更容易正確的理解代碼愈魏,從而不會(huì)因?yàn)閷?duì)老代碼的理解不到位而改錯(cuò)觅玻,造成新的bug。
大家可以回想一下培漏,過(guò)去有多少bug的發(fā)生溪厘,是因?yàn)閷?duì)遺留代碼的理解不到位,不全面導(dǎo)致的呢牌柄?在小紅書畸悬,這個(gè)比例不少,也造成過(guò)不小的問(wèn)題珊佣。痛定思痛蹋宦,我們現(xiàn)在能做的,就是引以為戒咒锻。寫代碼的時(shí)候妆档,重視可讀性,讓后來(lái)的人虫碉,讓后來(lái)的自己贾惦,不要再吃這樣的虧,不要再背這樣的鍋敦捧。
“人生苦短须板,快用Kotlin,珍愛生命兢卵,遠(yuǎn)離Java”习瑰。這是小紅書安卓客戶端Coding Style的第一條規(guī)則。順便說(shuō)一句秽荤,使用Kotlin之后甜奄,目前我們的app crash原因里面,Top10沒有任何一個(gè)NullPointerException
了窃款,Top20有兩個(gè)课兄,這兩個(gè)都是發(fā)生在系統(tǒng)層面的,也就是說(shuō)晨继,我們自己代碼里面的NullPointerException
烟阐,基本都已經(jīng)消滅了。而在6月份,上Kotlin之前蜒茄,我有統(tǒng)計(jì)過(guò)的一次唉擂,Crash里面Top10有5個(gè)NullPointerException
,Top20里面有12個(gè)檀葛。所以Kotlin的作用玩祟,是非常明顯的。目前屿聋,小紅書總體的Crash率卵凑,除非意外發(fā)生,可以很輕松的保持在0.2%甚至0.1%之內(nèi)胜臊,這在業(yè)界勺卢,即便不是最好的水平,也是個(gè)非常好的水平象对。
在Google聲明Kotlin成為安卓開發(fā)的官方支持語(yǔ)言那一天黑忱,我建了一個(gè)微信群。目前偶爾還是有人在群里面問(wèn)勒魔,Kotlin值得學(xué)習(xí)嗎甫煞?有風(fēng)險(xiǎn)嗎?看到現(xiàn)在還在問(wèn)這樣的問(wèn)題冠绢,我是覺得有點(diǎn)遺憾的抚吠。希望上面的文章能讓你從代碼可讀性的角度,了解Kotlin的優(yōu)勢(shì)弟胀。讓好的技術(shù)在這個(gè)世界盛行楷力,對(duì)技術(shù)人來(lái)說(shuō),是一件非常值得欣慰的事情孵户。