Kotlin與Java之爭 究竟誰更好?
Kotlin
Kotlin 是一門相對比較新的 JVM 語言,JetBrains 自 2011 年以來一直在積極地開發。
多年來,該語言在 Android 社區受到的關注度越來越高,並在 Google IO 2017 大會之後成為 Android 開發領域最熱門的話題。這次大會宣布,Android 正式支持 Kotlin。
遺憾的是,雖然已經有許多關於 Kotlin 的文章,但並沒有多少客觀信息,許多開發人員仍然在苦思冥想,遷移到 Kotlin 是否是一條正確的道路。
在本文的剩餘部分,我將嚐試提供一個在將 Kotlin 作為 Java 的替代項進行評估時需要考慮的更完善的事項清單。
Kotlin 與 Java 的主觀比較
“Kotlin 比 Java 好”,“Kotlin 可讀性比 Java 強”,“Kotlin 開發速度比 Java 快”,類似這樣的陳述缺少相關準確數據的支持,所以都歸為主觀看法一類。
主觀看法是個體開發人員在對與 Kotlin 或 Java 相關的主題作出一個或多個主觀判斷時形成。
開發人員的主觀判斷存在如下問題:
- 沒有與主觀判斷相關聯的量化指標。
- 主觀判斷存在很大的偏見。
- 主觀判斷的偏見在開發人員之間存在很大的差異。
由於沒有與主觀判斷相關聯的量化指標,建立在這些判斷基礎上的觀點隻是反映出了開發人員之前就有的偏見。不同的開發人員可能有著截然不同的偏見,因此,有開發人員認為 Kotlin 是不錯(或糟糕)的 Java 替代者並不意味著其他開發人員也這麼認為。
而且,由於沒有客觀指標,主觀分歧就無法客觀地消除,這經常會導致“口水戰”。
主觀判斷的謬誤
為了說明主觀判斷可能導致的誤解,讓我們仔細審視一個非常常見的主觀看法:
- Kotlin 可讀性比 Java 強
- ——Web 上無數的文章
理論上講,可以設法設計一個度量 Kotlin 和 Java 之間可讀性差異的實驗,但據我所知,沒有任何人真正地開展這樣一個實驗。因此,截至目前,這個看法沒有任何數據支撐。
Kotlin 的語法是許多開發人員稱讚其可讀性的一個原因。他們的邏輯如下:
- Kotlin 有更好的語法,因此它的可讀性更強
- ——Web 上無數的文章
在這句話中,“更好的語法”又是一個主觀判斷,本身就值得商榷,但為了避免爭論,我們假設 Kotlin 的語法確實更好。但是,這就能說明 Kotlin 的可讀性更強嗎?
為了觀察語法對可讀性的影響,請閱讀下這段“文本”:
開始的時候,這段“文本”很難理解,但慢慢地,讀起來會越來越容易。如果你再讀個兩三遍,那麼你根本就不會再注意它是由非標準的字母組成的。準確地說,字母的替換不是句法變化,但這確實可以說明,對於熟練的讀者而言,外觀很少會成為可讀性的障礙。
我們也可以把這個例子擴展到自然語言。我了解三門截然不同的語言。雖然它們之間差別很大,但我發現,當我不理解文本中使用的單詞時,閱讀任何一種語言的文本都非常困難。一旦我認識構成文本的單詞並熟悉上下文——無論它使用了哪一種語言,我讀起來都不困難。
因此,對我而言,語言的選擇並不會影響可讀性,隻要理解內容和上下文就可以了。
編程語言同樣如此。
當我們開始使用一門新語言,我們會有一段時間很難理解源代碼,需要認真領會每個句法結構。但是,隨著我們閱讀和編寫特定語言的代碼越來越多,我們逐漸就熟悉了那門語言的語法,到某個時候,我們就不會再注意句法結構了。
我自己在多門語言上有過這種體驗:Verilog、Bash、Perl、Tcl、Lisp、Java。
根據我使用上述語言的經驗,我可以告訴你:如果一個人適應了 Lisp 的代碼,並且不會再注意到小括號,那麼跟 Java 比起來,Kotlin 的語法完全不能對可讀性產生不可忽視的影響,即使它“更好”。
既然我們在討論這個話題,我就分享下自己對於影響源代碼可讀性因素的主觀判斷。
在讀過其他開發人員使用許多語言編寫的代碼後(上麵隻羅列了我在某個階段精通的語言;我用過的所有語言比這個多),我得出如下結論:如果開發人員使用某一門語言可以編寫出可讀性和可理解性都很好的代碼,那麼他們通常也可以使用其他語言編寫出可讀性和可理解性都很好的代碼。
因此,我根據自己的經驗作出的主觀判斷是,源代碼的可讀性和選擇的語言無關,那取決於代碼編寫者的技能和讀者的技能(編寫者的技能更重要)。
如果你仍然認為主觀看法具有代表性,那麼至少閱讀並思考下 Robert “Uncle Bob” Martin 在 這篇博文 中的觀點。
Kotlin 與 Java 的客觀比較
與主觀比較相反,客觀比較使用量化指標來度量或評估 Kotlin 比 Java 有優勢的地方。
用一套標準客觀地證明一門編程語言是否強過另一門,這種想法非常有吸引力,但是有個問題:據我所知,沒有與編程語言相關的通用客觀指標。
考慮到我們無法進行精確的直接比較,那我們能否客觀地比較 Kotlin 和 Java 呢?能!我們仍然能評估從 Java 切換到 Kotlin 所帶來的積極和消息影響的程度,然後比較結果,並討論它們的影響。
為了評估 Kotlin 所能帶來的最好結果,我們將做如下假設:
- 開發人員可以立即切換到 Kotlin;
- 切換到 Kotlin 後,開發人員不會損失任何技能(例如,有兩年 Java 開發經驗的開發人員可以神奇地獲得兩年的 Kotlin 開發經驗);
- Kotlin 和 Java 一樣穩定;
- Kotlin 工具和 Java 工具一樣成熟。
事實上,上述假設沒有一個是合理的,但在開始的時候,有一個理想化的設定便於說明。然後,我們會拋開這些假設,討論真實世界的效應所帶來的影響。
Kotlin 最佳結果估計
遵循 Steve McConnell 在 Code Complete 一書中提出的模式,我們可以將軟件構建活動分解成三個子活動:詳細設計、編碼與調試、開發測試。
Kotlin 對於詳細設計子活動沒什麼影響(這項活動通常獨立於選用的特定的麵向對象編程語言),因此,在這一部分,Kotlin 和 Java 需要付出同樣的努力。
據我所知,對於開發測試子活動,Kotlin 也沒有提出什麼革命性的東西。因此,開發測試需要付出的努力也一樣。
就剩編碼與調試子活動了。
如果我們用 Kotlin 替換 Java,那麼我在編碼與調試活動中可以節省多少工作量?這個問題很難回答,不同程序員之間這一數值會有很大差異(有些程序員使用 Java 更高效)。不過,既然我們在評估最好的情況,我們不妨假設從 Java 切換到 Kotlin 可以將開發人員在編碼與調試階段的生產力平均提高 10%。
10%的生產力提升是一個不現實到令人吃驚的數值。即使我們在文本編輯器中手工輸入所有代碼,那也是不現實的。考慮到現如今 IDE 的功能,這一數值更是不現實。考慮到有些開發人員使用 Java 更高效,這個數值就毫無道理了。
我不介意使用這樣一個既不現實又對 Kotlin 評估有利的數值,因為我知道,不管它對評估結果產生了怎樣不切實際的積極影響,一旦我們拋開其中部分“理想的假設”,由此帶來的負麵影響會抵消掉那些積極影響。
那麼,在編碼與調試方麵提升了 10%——我們把產品交付給客戶的速度快了多少?
下麵這張圖片來自 Code Complete 一書,展示了軟件項目的各種活動所占的比例:
圖小項目以構建活動為主。大點的項目需要更多架構、集成和係統測試工作來保證項目成功。這張圖沒有顯示需求,因為和其它活動不一樣,需求工作不是直接的程序功能。(Albrecht 1979; Glass 1982; Boehm, Gray, and Seewaldt 1984; Boddie 1987; Card 1987; McGarry, Waligora, and McDermott 1989; Brooks 1995; Jones 1998; Jones 2000; Boehm et al. 2000)
Code Complete ,第二版
根據來自 Code Complete 的這張圖片,在一個較大的軟件項目中(多於 10K 行),編碼和調試隻占項目總工作量的不足 20%。
因此,在一個較大的軟件項目中,我們所假設的編碼和調試效率提升 10%,隻能將完成項目所需的總工作量縮減 2%。
例如,一個需要 5 人年才可以完成的項目(這是相對比較大的 Android 項目),總工作量的 2%為:
- 5 人-年 * 12 * 4 * 5 * 0.02 = 24(人-天)
如果我們真得能夠把項目工作量減少 24 人-天,這會是一個從 Java 切換到 Kotlin 的很好的理由。然而,我們應該還記得,上述積極評估是在理想情況下得出的,其基礎是不切實際的假設。
在真實世界裏,切換到另外一門編程語言會產生不可避免的影響,我們將評估這種影響,並與上述理想化評估作個比較。
開發人員準備
為了評估最好的情況,我們假設開發人員可以立即從 Java 切換到 Kotlin。
實際上,雖然 Kotlin 和 Java 非常類似,但開發人員仍然需要花一些時間來學習,然後再花一些時間來調整開發實踐和工具。準備時間因人而異:有些開發人員可以三四天完成切換,其他人則需要 10 天甚至更多的時間。
讓我們樂觀一點,平均每個開發人員隻要 5 天就可以從 Java 切換到 Kotlin。
一個需要 5 人年才能完成的項目會有 3 到 5 名開發人員(最好的情況下)。平均每個開發人員的切換時間為 5 天,這樣,一個項目總計就需要 15 到 25 個人天的切換時間。
切換到 Kotlin 所節省的工作量(樂觀估計)與切換所需的總工作量似乎差不多。
開發人員技能損失
使用一門特定的編程語言高效工作的能力是一項技能。
我們已經討論了這項技能的其中一個方麵(代碼可讀性),但還有許多其他方麵。當從一門語言切換到另一門時,與舊編程語言相關的部分技能可以運用到新語言上,但該技能的其他部分會損失掉。
為了評估編程語言技能損失對項目工作量的影響,我們將使用源自 Cocomo2 評估模型的“語言與工具體驗”因子:
語言與工具經驗(LTEX)
該指標用於衡量開發軟件係統或子係統的項目團隊使用編程語言和軟件工具的經驗。軟件開發包括借助工具完成需求、表現形式設計與分析、配置管理、文檔提取、庫管理、程序樣式與格式化、一致性檢查、計劃與控製等等。除了項目編程語言經驗外,項目支持工具集的經驗也會影響開發工作。經驗低於 2 個月會獲得一個很低的評級,有 6 個月或多年的經驗則會獲得一個很高的評級,見下表:
Cocomo 2 模型定義手冊
例如,假設我們有一個 Java 開發團隊,團隊成員平均有一年的經驗,我們想遷移到 Kotlin。
由於 Kotlin 和 Java 非常像,與許多 Java 工具兼容。我們可以樂觀地假設,在經過初步的準備後,開發人員就可以歸為有 6 個月開發經驗這一類(而不是低於 2 個月)。根據這個假設,為了評估技能損失所導致的額外工作,項目的額定工作總量應該乘以 1.09。
一個需要 5 人年完成的項目,配備了平均具有 1 年 Java 經驗的開發人員,切換到 Kotlin 所導致的額外工作達到了令人咂舌的 108 人天。
技能損失所導致的額外工作是切換到 Kotlin 所縮減的工作的四倍。
語言和工具的穩定性和成熟度
有個普遍的說法,就是 Kotlin 是一門生產就緒的語言。這種說法也許是有道理的,因為 Kotlin 已經用在了若幹項目裏。
不過,與 Java 相比,Kotlin 是一門並不穩定的年輕語言。
有些開發人員認為,Kotlin 的不穩定性是個優勢——語言在演進,可以更快地提供新特性,更快地改進。在我看來,他們對於這件事的看法過於簡單。
下麵是 Kotlin 1.1.4 發布說明裏的第一句話(寫這篇文章時的最新版本):
- 修複 IntelliJ IDEA 的一項重大性能衰退
- ——Kotlin 1.1.4 發布說明
我不知道這是什麼樣的衰退,有多少項目受到了影響,但我的大腦自動將“重大性能衰退”這個搭配翻譯成了“浪費了許多小時的開發時間。”
此外,如果你讀一遍發布說明的評論,你就會注意到,許多人遇到了遷移問題。在 1.1.2 版本的評論裏,甚至有人指出,這個“補丁”發布引入了破壞性(向後不兼容)的修改。
相比之下,如果你讀一遍 Oracle JDK8 的發布說明 ,你就會發現,它比較穩定。大多數修改都是安全改進方麵的。
因此,與 Java 相比,Kotlin 是一門不穩定且不成熟的語言——遷移到 Kotlin 會對項目產生怎樣的影響?為了回答這個問題,我將使用來自 Cocomo 2 評估模型的“平台波動性”工作因子:
平台波動性(PVOL)
這裏使用“平台”一詞指代軟件產品執行任務時調用的複雜硬件和軟件(OS、DBMS 等)。如果開發的軟件是一個操作係統,那麼平台就是計算機硬件。如果開發的是數據庫管理係統,那麼平台就是硬件和操作係統。如果開發的是網絡文本瀏覽器,那麼平台就是網絡、計算機硬件、操作係統和分布式信息庫。平台包括支撐軟件係統開發所需的編譯器或裝配器。如下表所示,如果平台每 12 個月才有一次重大變更,則評級就會很低,如果每 2 周有一次重大變更,則評級就會很高:
Cocomo 2 模型定義手冊
你可能已經注意到,編程語言並沒有直接出現在該工作因子的描述裏,但出現了編譯器和裝配器。在我看來,這段描述沒有顯式包含編程語言,是因為得出 Cocomo 2 模型的所有項目都使用了穩定的語言。
由於編譯器和裝配器屬於這個工作因子,所以我們也可以推斷出編程語言及相關工具。
根據平台波動性的這種評級範圍,Java 的評級應該是“very low”,而 Kotlin 的評級應該是“low”或更高。Kotlin 的評級可能會更高,因為它內部依賴於其它工具,增加了出現兼容性問題的風險。
由於“very low”沒有提供工作因子,所以我們需要估計。
看下該因子從“very high”到“low”的評分遞減規律,我認為,我們可以放心的假設,“very low”的評分不高於 0.82。
基於這些假設(有利於 Kotlin),如果一個項目需要 5 人年的額定工作量,那麼使用 Kotlin,工作量就變成了 1044 人天,而使用 Java 的總工作量是 984 人天。
選擇使用 Kotlin 而不是 Java 實現這樣一個項目會使總工作量增加 60 人天。
語言和工具不穩定所導致的額外工作是切換到 Kotlin 所縮減的工作的 2 倍多。
綜合所有因素
我當成例子來討論的項目需要 5 人年的額定工作量。
根據上述評估,如果該項目由平均具備 1 年 Java 開發經驗的開發人員使用 Java 實現,則總工作量為:
- 人-年 * LTEX(Java) * PVOL(Java) = 984 (人-天)
如果同樣的項目由幾乎沒有 Kotlin 開發經驗的開發人員使用 Kotlin 實現,則總工作量為
- 5 人-年 * LTEX(Kotlin) * PVOL(Kotlin) * 0.98 + T_ramp_up = 1115 + 5 * N_developers (人-天)
據估計,選擇 Kotlin 替換 Java 所導致的額外工作量為 131 + 5 * N_developers (人-天) 。
評估注意事項
在評估討論的過程中,我們得出了與 Kotlin 和 Java 相關的、便利的工作量單點值。
但實際上,單點值根本不是估計——它們隻是猜測。真正的估計必須有一個相關聯的不確定性。換句話說,估計表示可能性的範圍,而不是單點值。
我們最終使用單點值代替了範圍,那是因為我從估算範圍裏選擇了最有利於 Kotlin 的值,將所有的估計都轉換成了單點值。
例如,當討論 Kotlin 對編碼與調試活動的影響時,我從估計出的可能性範圍 [-5%,10%] 中選擇了最大的生產力提升值 10%。在其他情況下,當我們討論開發人員切換到 Kotlin 的平均時間時,我從估計的可能性範圍 [5 天,21 天] 中選擇了最小的 5 天。
此外,我們使用了 Cocomo 2 估計模型專用的工作因子。這些因子並不是放之四海而皆準的真理,在最一般的情況下,應該也有相關聯的不確定性。我賦給 Kotlin 的評級高於我實際上認為它應得的評級,我希望通過這種方式消除這種不確定性。
不用說,我們獲得的單點值並不是百分百正確。為了得出更完整的估計,我們可以利用真正的估計進行 Monte Carlo 仿真。通過這項技術,我們可以觀察可能結果的分布,弄清楚哪種結果最可能出現。
請記住,由於我們將估計壓縮成了對 Kotlin 而言最為有利的單點值,所以其他可能的結果會顯示出更大的 Kotlin 切換開銷。因此,在所有可能的結果中,我們在上文描述的單點值是最有利於 Kotlin 的。
小結
在文章開頭部分,我們展示了一些可能會對開發人員比較編程語言造成誤導的主觀判斷。
接下來,我們討論了客觀比較編程語言存在的困難,並進行了一係列的估計,以便弄清楚 Kotlin 棧與 Java 棧完成軟件項目所需的總工作量。在執行估計時,我們一直使用估計範圍裏最有利於 Kotlin 的值。
通過我們的分析,從 Java 切換到 Kotlin 似乎會導致完成軟件項目所需的總工作量增加。
更多的工作意味著企業切換到 Kotlin 需要花更多的錢才能獲得同樣的功能,而用戶需要等待更長的時間才能獲得產品。
有些開發人員可能會吃驚,覺得這個結果不容易接受。
在考慮了所有的情況之後,穀歌最終決定支持 Kotlin Anroid 開發。對此,穀歌可能需要相當大的投入——穀歌雲平台團隊是不是沒有人可以做類似的分析,從而弄清楚切換到一門新語言所帶來的負麵影響?
我認為,穀歌員工都是非常聰明的人,我相信他們在決定支持 Kotlin 之前已經進行了非常深入的分析。
本文作者:佚名
來源:51CTO
最後更新:2017-11-02 14:03:46