今年是 Java 問世的25週年,雖然 Java 寶刀已老,但還沒有凋零。目前還都是前三名的程式語言,版本的更新也持續進行中,自從 Java 9 開始每6個月都會更新。目前最新的版本為 Java 15 。 ( 不過Android 最高只能用到 Java 8 )
JCConf (Java Community Conference) Java 社群研討會,雖然名稱裡面只提到了 Java ,但是 JVM 相關的內容也都會包含在這次的議程當中,其中當然包括 Kotlin。
前一陣子參與了由 JetBrains 技術傳教士 聖佑舉辦的 Kotlin 線上讀書會,我跟隨著讀書會將 Kotlin 完整的研究了一遍,在讀書會的期間,了解 Kotlin 除了可以用在 Android 上,還可以應用在其他方面,如 Server。
下面是我今天參加的主題:
用 Kotlin 跨入 Serverless 世代 - 范聖佑
Migrating to JUnit 5 - Joanna Hu
Kotlin Flow Application and Testing on Android - 吳于豪
Kotlin & Android Performance @Mozilla - Nevin
Functional Programming in Java- 古君葳
Porting Spring Cloud Application to Kubernetes - Vincent Huang
在這一場演講中,講者用 Kotlin 完成 Production 功能,並且在各個 FaaS (Function as a Service)上嘗試部署。
現在各大雲端服務器都有 IntelliJ 的 plugins,所以部署的方式幾乎都是在 IDE 上面完成。差別只在於每個服務都有不同的設定值。使用者需要根據不同的服務設定不同的設定值。
因此 JetBrains 開發團隊開發了一個 Framework - Kotless,利用 Kotless,可以輕鬆的將服務器部署至指定的 FaaS 雲上,不需考慮各服務器的不同設定值。
心得:微服務是一個很有意思的議題,該如何將原本的服務切成微服務,且每一個服務的粒度要切多小(或多大),都是需要被考慮的。當使用微服務架設後,原本在單一伺服器上每一個 API 的回覆都可以輕鬆的處理,用微服務器處理後,由於一個 API 呼叫所需要處理的項目可能分佈在不同的微服務上,那麼有可能會變得更加麻煩。
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit 4 定位為 Testing Framework,而 JUnit 5 則為Testing Platform。
那麼,如果用 JUnit 4 好好的,為什麼要升級成 JUnit 5 呢?
JUnit 5 增加了許多新功能:
- Nested Tests:將相關的測試放在一起,測試結果輸出的時候就會比較清楚。
- Display Name:受限於 Java 的特性,一般我們在命名測試的時候,若要將測試的目的完整地寫出,可能會包含許多下底線,用 Display Name 這個功能,可以在測項的上方加上 DisplayName Annotation ,在裡面可以輸入任意一段文字,最後在測試的輸出就會以這個文字作為輸出,而不是測試的函數名。
- Parameterized Tests:在測試的時候,我們經常會在相同的條件之下,輸入不同的參數,利用 Parameterized Test 這項功能,我們可以在測項的上方填入預計測試的輸入值,JUnit 5 就會依序的將參數傳入。有了這個功能,我們就不需要針對不同的參數定義不同的測試函數了。
- Multiple Runner:在 JUnit 4 時,每一個測試類都只能使用一個Runner,在 JUnit 5 中,可以同時定義多個 Runner。
JUnit 5 相容 JUnit 4、JUnit 3,在進行升級時,不需要一口氣將所有的測試都改為 JUnit 5 ,可以按照『新加的測試用 JUnit 5 寫,舊的測試有空才改成 JUnit 5 』這個規則,如此就可以一步一步的慢慢替換舊版的 JUnit 到 JUnit 5。
最後,IntelliJ 是一個強大的 IDE,所以當然也內建了一件升級 JUnit 5 的功能,如果想要一口氣自動升級 JUnit 5,不仿考慮使用 IntelliJ 內建的功能吧。
心得:學習單元測試也一段時間了,一直以來都是使用 JUnit 4,這場演講介紹如何將 JUnit 4 升級成 JUnit 5。聽完之後,便迫不期待的想要將自己專案內的單元測試轉換成 JUnit 5。
在 Kotlin 中,我們可以利用 Coroutines 做異步處理,如果有多個異步方法,且需要等待所有的異步方法完成之後,才能夠計算,此時 Flow 就能夠派上用場。
What is Flow? A new stream processing API。
Flow 的特性:
- Simple:簡單使用
- Language feature support:支援語言的特性
- Flows are cold:跟 Sequence 一樣,存放在 Flow 的東西,只有呼叫 collect 之後才會被執行。
如何定義一個 Flow 呢?
- flow builder
- flowOf builder:用來建立固定數量的 flow
範例:利用 flow bulder
https://gist.github.com/1626640a33b8f26c9ea87db1ad855efe
範例:利用 flowOf builder
https://gist.github.com/7bf855259116018beca0d1a2a09abdb2
flowOn 運算子
利用 flowOn 運算子切換執行的 Thread。
包含了三個 Dispatchers
- IO
- Main
- Default
如何測試?
- Mocking Framework
- Flow Assert / Turbine
心得:異步處理一直都是程式語言中,一個很重點的項目,這次有機會認識了 Flow ,加上它是以 Kotlin 作為開發語言的,所以相當吸引我來學習,聽完演講之後,我也打算將原本專案裡面使用的 RxJava 換成 Flow 試試看。
另外,這場是一場全英文的演講,講者並非不會說中文,只是他是想要給自己一個挑戰,我認為這是一件非常屌的事情。
有一種慢,叫做客戶覺得慢
在 Kotlin 上,如何提升效能?
- 在使用 Coroutine 上,選擇正確的 Dispatcher
- 資料量很大的時候,使用 Sequence
- Compiler Optimization + ART inline
在Android 上,必須要知道瓶頸在哪?
- CPU
- Memory
- Disk
- Network
- Thread Pool
Tip
- Set debuggable = false
- Enable StrictMode
Tools
- In the wild
- Firebase performance
- Android Vitals
- In the lab
- Profiling tools
- Android Studio Profiler
- Customized tools
- Profiling tools
從哪邊開始進行?
- 隨機挑選一個有問題的地方
- 根據 Google Play Review
- Vitals, Manual QA
- Performance Regression Caught in CI
心得:如何提升效能?要從兩個方向來看:第一,程式碼是否還有改善的空間,我們可以使用 StrictMode 來協助我們找到程式碼有問題的地方。第二,如果程式碼已經沒有辦法改善了,是否可以找到目前效能較低的地方,並且看看是否有方法可以突破該瓶頸。
測試效能的方法,用工具是比較有效率的方式,如上所說,可以使用內部的工具如 Android Studio Profiler 或是外部的工具 Firebase performance 等等...
聽完演講後,隔天立刻在專案開啟 StrictMode,哇賽,Camera 的 Surface 居然要呼叫 release(),這個漏洞居然跟了這個專案三年了 XD,不知道有多少條 bug 都是死在忘記釋放 Surface 。
什麼是 Functional Programming (FP) ?
簡單來說,一個函數可以作為參數帶入另一個函數,也可以當作輸出類型。就是函數式程式語言。
FP 無疑是目前最夯的編程範式,且在眾多語言都有支援,但其實FT不是一個新的概念,在80年代就已經出現,不過後來物件導向比較流行,所以就被大家暫時遺忘,那麼為什麼現在又會重出江湖呢?原因是FP 具有不變的特性,相同的輸入永遠會輸出相同的結果,寫函式的時候不需要定義一個類別...
在Java8 新增了 Lambda 表達式(Lambda expression),我們可以將函式的參數以 Lambda 表達式表示。
https://gist.github.com/e7a846269ec4214453807dc4860872ae
其中 apple→apple.getColor().equals(“red”))
則是 Lambda 表達式。
我認為這場演講精彩的地方在,為了解決「函式因應不同的需求,產生出許多類似卻又不完全相同的函式」,首先,將判斷的部分改成以參數傳入:行為參數化 (Behavior Parameterization),也就是策略模式 (Strategy Pattern),最後將 Lambda 表達式引入,最後就成為上面我們看到的範例。
可以發現上面的例子,先將 appleList 轉為 Stream,在Stream 中,我們可以針對輸入的 “資料流”,做出不同的事情,例如 filter 、map ... 最後在呼叫 collect 之後,資料才運算然後輸出。要特別注意的是,輸出的結果是一個新的 List,不是修改原本的 List。
心得:在 Kotlin 讀書會的尾聲,我們剛好也讀到 Kotlin 的 FP,所以我對這場演講充滿了興趣,想知道在 Java 的 FP 是否有不一樣的內容。第一眼看起來沒有太大的不同,因為 Kotlin 也支援 Lambda 表達式,所以在 Kotlin 上,也可以將 FP 寫的類似如同上面的範例一樣。
Porting Spring Cloud Application to Kubernetes - Vincent Huang
這場很精彩,Vincent 把 Spring Cloud Application 部署到 Kubernetes 會遇到的問題都講得很清楚,不過由於我對 Spring 不熟,這場只是來看看讀書會的 Vincent 大大而已XD
不過,對我來說本場最重要的概念就是「剛好就好」,以 Design Pattern 為例,不一定每一個地方都需要套用某一個 Design Pattern ,否則有可能會過度設計,一定要把「剛好就好」四個字記在心裡。
從七月開始的讀書會,開啟了我對 Kotlin 的興趣開關,這次的 JCConf 有很多讀書會的同伴也到了現場,所以也間接促成我參加這次的 JCConf,畢竟難得有這個機會能夠見到本人XD
話說回來,參加 Confrence 可以學習到不同的項目,也可以順便知道目前的趨勢是如何,我認為 Kotlin 前景一片看好,2021 我也是會以 Kotlin 為主。
參考投影片:
Kotlin Flow Application and Testing on Android