
終於寫到最後一篇了,從 myForEach 一路到 Contract,中間好幾次覺得自己是不是題目開太大,是不是要省略中間的幾篇 XD
會挑這個題目的原因 day 01 講過了,這裡就不重複。簡單說就是當年上 91 的 C# 進階設計課程留下的印象,用重構跟測試把 LINQ 一個一個長出來
真的用 kotlin 做完才發現,當初以為的「應該差不多吧」跟實際寫下去差很多。map 是很像 Select 沒錯,可是手刻到 Grouping 跟 Sequence 那幾篇的時候,已經是另一個世界了,這些都不是看 API 名字看得出來的
話說回來,這次做完了也不代表 Kotlin 就變得很厲害,下次每一個都寫得出來,真要憑空默寫 myAggregate 那個 first 旗標怎麼判斷,大概也是會卡住
我覺得重點在於了解底層的那些邏輯,能不能完整的寫正確是另一回事,以後在專案裡用到某個 API,行為跟預期不一樣的時候,腦中還有一點模糊的印象,知道「這個好像跟哪件事有關」,再回來翻自己寫過的文章就好,文章都是寫給未來的自己看的
day 19 的 Grouping 是整個系列唯一自己定義介面再實作的一篇。Grouping 本身不做事,它只是一份「要怎麼分組」的說明書,真正的動作都在 aggregate 裡
day 31 的 Sequence 效能是另一種難。難的不是寫程式,是 benchmark 要做得公平。資料量、有沒有提前終止、中間操作疊幾層、JIT 有沒有暖機,任何一個變因都可能讓數字翻盤,比起「Sequence 比較快」這種結論,我更想提醒另一件事,以後看到別人丟出來的效能數字,先問清楚他測的到底是什麼情境
day 35 的 Contract 則是另一種感覺,有點微妙。這東西 C# 基本上沒有,而從 Kotlin 1.3 到現在還掛著 @ExperimentalContracts,可是 stdlib 自己用得很開心,let、run、require 底下全都是 contract,官方一邊說還在實驗,一邊在自家程式碼裡大量使用,這讓函式庫作者蠻兩難的
另外還有一種難是預期之外的。很多篇手刻完之後,我會去翻 stdlib 原始碼比對,然後就會看到「喔,原來官方多考慮了這個」。像 xxxTo 那一系列讓呼叫端自己帶目標集合、OrNull 跟拋例外兩種版本並存的設計,都不是我第一版會想到的事情。這個比對,反而是整個系列我收穫最多的部分
在語法層面,不得不說 Kotlin 比 C# 靈活太多了。trailing lambda、帶 receiver 的 Lambda、infix、Scope Functions,這些東西組合起來,可以把 API 寫得非常貼近自然語言,extension function 兩邊都有,但 Kotlin 這邊可以直接掛 infix、可以當 receiver 用,能玩的花樣就是多一些
不過這樣比其實也不太公平。兩者出生的年代差很多,而且 Kotlin 是後來者,可以避開前人踩過的坑重新設計,本來就比較有機會設計得好一點 (吧 ?)。C# 身上背著很長的相容包袱 (從 .NET Framework 到 .NET Core),我猜很多地方不是不想改,而是改不動,不然也不會有 .NET Core 的出現 XD
另外,我覺得 JetBrains 在 Kotlin 推廣上蠻積極的,官方文件、KEEP 提案、YouTrack 都很公開,版本更新也很勤
day 01 就先講過,這個系列雖然是用 TDD 寫的,但不走 baby step,而是把測試案例集中放在每篇前面,看完再進實作
36 篇寫完,好處很明顯,文章讀起來乾淨很多,一次看完所有邊界條件,也比較容易抓到這個函式該有的行為,要是每篇都把紅燈綠燈的過程原原本本記下來,篇幅大概會膨脹兩三倍,主角就從 Kotlin 語法變成 TDD 流程了
如果想自己練一次的話,還是建議把每篇前面那組測試拆開拆細,一次只寫一個,實際跑起來的感覺跟看文章會差很多
同步刊登於 Blog
圖片來源:AI 產生