Tuesday, February 19, 2019

用 Graalvm 製作 clojure native image

在 ubuntu 18 做的實驗:
1.  下載、安裝 Graalvm 

2. 在 ~/.lein/profiles.clj 裡增加
{:user {:plugins [[io.taylorwood/lein-native-image "0.3.0"]]
        :native-image {:graal-bin "/path/to/graalvm-1.0.0-rc1"}}}
如此,就可以使用 lein native-image 這個指令

3. Graalvm 需要下列的套件
sudo apt-get install gcc
sudo apt-get install zlib1g-dev

4.  lein native-image  之後,就可以得到 native image 。

Friday, February 8, 2019

從 SQL 到 Datomic query (datalog)

要理解新的概念,一般而言,用舊的、已經熟悉概念來加以連結新的概念,會是比較容易的方法。另一方面,要讓人們去接受新的解決方案,先確定舊的問題都可以在新的解法中解決,也是有效增加人們信心的作法。

當我使用 SQL 來開發 web application 時,最常用的 SQL query 是什麼呢? 其實未必是複雜的 join operation 。最常用的,反而是樸實無華的查看單一或是多個 rows:
(1) SELECT * FROM A
(2) SELECT * FROM A WHERE A.col = b

那麼,這麼簡單的 SQL query ,如果是在 Datomic 的世界,又是怎麼對應呢?我在 datomic 官方的 mbrainz-sample 找出的一段 query 。用了之後,覺得非常容易可以對應上述的兩種情境。sample code  在下方
舉例來說明:
如果有一個「使用者」的概念,要用資料庫加以建模。使用者有電子郵件、密碼、名字三種屬性。同時,我們需要一個資料庫查詢 (query) ,可以根據電子郵件來查出對應的使用者

1. 用 RDB 來建模的話,這個 sql query 會長成這樣子:
SELECT * FROM user WHERE user.email = "ecoboy@qwerty.com";

2. 用 Datomic 來建模的話,一旦利用上述的 utility functions ,這個 query 就可以用下列的函數產生。
(find-by db :user/email "ecoboy@qwerty.com")

附註:
(a) 在 SQL best practices 裡,因為要考慮效率,往往不建議用 select * 這種 query 直接放在 production code 裡。
(b) 在 Datomic  best practices 裡,因為 datomic 的 query 並不需要往返 client-server ,同時 Entity 有 lazy evaluation 的特性,一般而言,推荐的作法是直接取回 Entity ,相當於 SQL 裡的 row 概念。

Monday, February 4, 2019

From REST to CQRS with Clojure, Kafka, and Datomic

Clojure/conj 2015 年的 conference talk --- From REST to CQRS with Clojure, Kafka, and Datomic 是我 2019 年所看到第一篇深受啟發的 talk ,也有 youtube  影片。

首先作者先探討 Restful API  的一些問題:
1.  modeling - jamming every operation into CRUD on some resources is often unnatural, creating impedance mismatch. 
Restful API 可以視為是模仿 Database 的 CRUD 介面 (post, get, patch, put) ,然而,這個 modeling 在本質上,未必適合對各式各樣的問題做建模。
2. mutability semantics
Restful API 隱含了 mutable 語意
3. the kingdom of nouns for distributed system 
最後就是有太多的 API ,然後需要有類似 swagger 之類的 API document 系統 …
4. integration 
integration by API 比 integration by ETL 好一些,但是,還是有許多缺點

然後,作者 (Bobby Calderwood) 提出了一個應用 CQRS + Event sourcing 來設計系統的架構 (Commander Pattern),如下圖:



















新的架構處理了許多舊有的問題:
1. modeling 
web services 的部分只對 communication semantic 做建模,所以只有三種,而非 resources * CRUD 。communication semantic 是指 /command /update /query 三種語意。
2. immutable semantics
/command API 會寫入 command log 。這個 command log 對使用者的 intention 做完整地記錄,相較於儲存進資料庫裡的資料, command log 有更完整的 command story
3. too many APIs
因為新架構的 http endpoint 只有三種: /command /update /query 。
4. integration
新的架構裡可以 integration by events ,因為有儲存下 command log 。要整合的時候,其它系統去訂閱 command log 就可以完整地拿到系統的 states

心得感想:
(*) end-to-end principle
在這個架構裡, Web services 層只用來處理 communication 。 Restful API 的 resources 名稱,其實算是一種 domain semantics,應該要放到 Business Logic 層來實現。這其實很像網路世界的 end to end principle ,因為 Client 與 Business Logic 就像是溝通的兩個端點 ,針對應用 (application) 設計的種種特性 (features),應該要在這兩端來加以實現,而不是在中間的 Web services 層實現。

(*) We shape our tools and thereafter our tools shape us. 
Restful API 的設計,有點像是使用了 SQL/relational database 之後的思維模型會構思的設計。而這個 Commander Pattern 則是使用了 Datomic 之後的思維模型會構思的設計。