當前位置:
首頁 > 科技 > 歷時 7 天,我把一萬行 Scala 代碼移植到了 Kotlin 上!

歷時 7 天,我把一萬行 Scala 代碼移植到了 Kotlin 上!

【CSDN編者按】去年,Google 宣布 Kotlin 正式成為 Android 官方開發語言,由此引發了遷移 Kotlin 的一股熱潮。在本文中,作者分享了他在七天內把代碼從 Scala 移植到 Kotlin 的經過,以及從中吸取的經驗教訓。

以下為譯文:

上周出了幾件事,所以我決定把postgresql-async從Scala移植到Kotlin。雖然現在還有好多缺失的部分,但alpha版已經可以用了在這篇文章中我想分享把代碼從Scala移植到Kotlin的經過,以及從中吸取的經驗教訓,希望可以幫助其他開發者解決同樣的問題。而且我也在繼續努力,解決剩下的問題。

首先我想解釋一下為什麼要移植?

在Outbrain我轉到了一個新的團隊,得到的任務之一就是負責將各種模塊從Scala 2.10升級到2.11。這個任務是可行的,但十分痛苦,因為許多包都要求我們必須給所有JVM模塊「打補丁」,就連Java模塊都要!

由於所有模塊都依賴於ob1k-db,而ob1k-db依賴於postgresql-async,後者又依賴於Scala 2.10和2.11下的不同的包。所以,可能更好的做法是幹掉所有模塊中對Scala的依賴……

而且上周,在經歷了一年多的沉默後,終於有一個提交證實了postgres-sql不再提供維護了(https://github.com/mauricio/postgresql-async/commit/5716ac43818b6be0dc4fcc2b2655dde3411cdbe0)。這是壓死駱駝的最後一根稻草。

而且,我們仍然在使用該函數庫的MySQL非同步風格的版本,而且還沒有找到能代替它的東西。

但一個優勢是Scala和Kotlin十分相似,無論是功能還是語法——所以我們很想試試能不能把代碼移植過去。

怎麼做?

在閱讀下面的技術細節之前請訪問下下面的函數庫,然後請給加個星 :

https://github.com/jasync-sql/jasync-sql

轉換本身包括兩個主要步驟:

自動逐行搜索替換腳本內容,節省一些無謂的打字時間;

人工審核代碼,修改所有編譯錯誤,決定怎樣進行轉換,並改進腳本。

腳本

腳本其實是一段非常簡單無腦的kscript代碼(https://github.com/holgerbrandl/kscript),感覺都沒必要貼出來。一些代碼行甚至都沒有替換成合法的語句(比如模式匹配和類型強制轉換的部分)。

話不多說,下面是腳本的簡化版本:

這個腳本是用kscript編寫的(https://github.com/holgerbrandl/kscript),它接受一個參數:可以是擴展名已經改為.kt的Scala文件,也可以傳遞目錄,如果是目錄則該腳本會遞歸轉換目錄中的所有文件。

這個腳本會進行一些非常簡單的逐行查找替換:def替換成fun,trait替換成interface,等等。沒什麼特別的東西。因為我前面說過,兩者語法很相似,這一點起了很大作用。如果轉換成Java則可能會更麻煩。

經驗教訓,以及我做出的決定

我寫這篇文章的目的就是記錄下我做過的事情。一些文件仍然需要轉換,同時項目中還有其他人,所以這篇文章會有用的。

下面的項目順序不分先後,以後也可能會更新。

Future CompletableFuture

原來的代碼大量使用了Scala的Future,所以我需要找個東西來代替。我有許多選擇:

Netty future——似乎語法很複雜,而且已經過時。

JavaRX/Guava/其他future庫——需要額外的外部依賴。

Java 8兼容的Future——至少需要依賴Java 8。

Kotlin deferred——主要用於協程(coroutine),所以功能不太多,也不知道與Java用戶的兼容性如何,對於我來說有點難度。

最後決定使用CompletableFuture作為主要的後端庫。我覺得沒必要在Android中使用響應式的relational-sql庫,而且Java 8在Android之外的應用也非常廣泛。

注意,CompletableFuture替換了Scala的Future和Promise。

依賴

由於這個項目類似於驅動程序,所以我盡量減少外部函數庫的依賴,這個決定也影響了其他的決定。

Finalize

貌似在Kotlin中不需要覆蓋finalize方法。

數據結構

有些我已經忘了,但我記得的轉換有以下這些:

Seq List

IndexedSeq List

ArrayBuffer MutableList

位操作

Kotlin對於byte的處理有點奇怪,還不支持所有的操作符。一些類我轉換成了Java,一些仍然保持Kotlin。希望我處理得沒錯,因為我並不十分確定Scala怎樣處理這些操作。歡迎提意見。

擴展方法和屬性

我一開始並不太理解,但後來意識到我可以使用擴展(extension)讓Kotlin變得跟Scala相似,這一點非常酷。

例如Kotlin的List中有size,而Scala中叫做length。

這些問題都可以用擴展解決。

Try

我決定從Scala+Arrow移植一個相似的類使用。

方法定義和調用中的大括弧

Scala並不強制大括弧,所以有時轉換會很痛苦。

Duration Duration

決定使用java.util.Duration。

執行上下文和隱含參數

我發現這個功能非常混亂,所以我把所有隱含參數都改成了必須。雖然代碼會變得冗餘,但我覺得這樣更清晰。

我使用common pool作為默認的執行上下文,儘管在ob1k中我們使用的是另一個。不管怎樣,我們把它也改成了顯式傳遞。

測試

原來的庫使用了specs2。一開始我想暫時保留Scala的測試,但似乎這樣做也需要很多工作,因為許多內部代碼都改變了。測試的移植依然在進行中,主要工作都由貢獻者們進行。

Option

大部分都用nullable的類型替換了,其中用到了一些擴展的幫助函數:

https://github.com/jasync-sql/jasync-sql/blob/master/db-async-common/src/main/java/com/github/jasync/sql/db/util/NullableUtils.kt

這裡我發現Kotlin的方法更好,因為Scala有時使用Option,有時卻直接使用null。

也可以用Java的Optional替換。

Version KotlinVersion

其中有個專門的邏輯,但這個邏輯似乎很標準,所以我就使用KotlinVersion來替換了。

隱含轉換

隱含轉換是一切的邪惡之源(包括過早優化)。我發現我們的情況中可以很容易地使用擴展方法和Java靜態方法來替換隱含轉換。比如這裡的第25行(https://github.com/mauricio/postgresql-async/blob/master/mysql-async/src/main/scala/com/github/mauricio/async/db/mysql/binary/decoder/BigDecimalDecoder.scala)我們隱含地將ByteBuf轉換成了ChannelWrapper,使用的是這裡的第25行(https://github.com/mauricio/postgresql-async/blob/master/db-async-common/src/main/scala/com/github/mauricio/async/db/util/ChannelWrapper.scala)定義的方法。在Kotlin中,我們在ByteBuf上使用擴展函數(如這裡:https://github.com/jasync-sql/jasync-sql/blob/master/db-async-common/src/main/java/com/github/jasync/sql/db/util/ByteBufExtensions.kt),並將ChannelWrapper變成了靜態方法。

Traits interface + 每個類的委託

似乎traits只是多重繼承的替代品,因為它們有狀態。我成功地用類委託(class delegation,第55行:https://github.com/jasync-sql/jasync-sql/blob/master/mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt)替換了它。缺點是這種實現要求方法拋出異常,所以如果沒有被重載,那麼運行時有可能會出錯。見這裡的第51行(https://github.com/jasync-sql/jasync-sql/blob/master/db-async-common/src/main/java/com/github/jasync/sql/db/pool/TimeoutScheduler.kt)。

以上,感謝閱讀。歡迎大家指正!

原文:https://hackernoon.com/how-i-ported-10k-lines-of-scala-to-kotlin-in-one-week-c645732d3c1

作者:osha1

譯者:彎月,責編:郭芮

微信改版了,

想快速看到CSDN的熱乎文章,

趕快把CSDN公眾號設為星標吧,

打開公眾號,點擊「設為星標」就可以啦!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 CSDN 的精彩文章:

蘋果回應下架iPhone X;滴滴將恢復深夜出行|極客頭條
阿里遊戲之心不死?|暢言

TAG:CSDN |