Friday, October 12, 2018

first class

現在一些比較新的 programming language 有時候都會在語言裡加入新的 first class element 。對我來講,這個詞彙 first class ,總是讓我覺得有「理解的困難」,到底什麼才叫 first class 呢?

有一回,我終於在 SICP Distilled 看到定義了。

In general, programming languages impose restrictions on the ways in which computational elements can be manipulated. Elements with the fewest restrictions are said to have first-class status, an idea originally due to Christopher Strachey
Some of the “rights and privileges” of first-class elements are that they may be:
  • Named by variables
  • Passed as arguments to functions
  • Returned as the results of functions
  • Included in data structures
Lisps, unlike other common programming languages, awards functions full first-class status. This poses challenges for efficient implementation, but the resulting gain in expressive power is enormous.


Software Engineering Task Orders


Stage 1
(1) end-to-end test
(3) CI/CD -> cloud formation
(4) linter

Stage 2
(1) unit test
(2) cloudwatch filtering/alarm

Stage 3
(1) integration test
(2) profiling
(3) automatic document generation


開發軟體總是需要做一些軟體工程的事情,不過,通常總是有一些壓力讓我沒有辦法事事做到完美。於是我自己弄了一個排序。如果有時間的話,先做哪些、後做哪些。 stage 1 是我覺得最重要、最該先做的。 stage 2 是我覺得可以拖一下的。stage 3 是行有餘力才做的。

為什麼 stage 2 可以拖一下呢?
(*) 以 unit test 來講,如果已經有 end to end test 並且加上可以用環境變數關閉的 debugging log ,某種程度來講,也可以把該測的程式碼測到乾淨。沒有 unit test 似乎也沒有這麼嚴重了,因為已經有了替代方案了。

(*) cloudwatch 的 filtering/alarm 的話,這個通常是設計用來抓出某些本來預期不會發生的錯誤、或是超大的流量發生的情況。但是,專案剛開始發展的時候,流量有時候也不大,所以可以拖一下。在 Erlang  的設計哲學裡,這部分設計應該算是所謂的「故障曝光性質」 (failure status property) 與「持久存儲性質」 (stable storage property)  ,算是直接要設計在 programming language layer 的東西,而不是要設計在 infrastructure layer 的東西。

為什麼 stage 3 可以拖更晚呢?
(*) 專案在「探索期」的時候,對資料庫的查詢,可能會快速地一直更換,太早加上 integration test ,有時候也太費力了,因為加上去了,總是要維護吧?
(*) 如果專案沒有效能瓶頸,profiling 沒有做也還好吧?
(*) 如果專案還沒有長太大,沒有自動產生的文件,似乎也不太嚴重。

Friday, October 5, 2018

cooperative multitasking

過去初學 event-driven 或是 cooperative multitasking 時,沒有特別想清楚 。等到後來,多寫了一些 Nodejs 的 async/await ,還有 Clojure 的 go-block 之後,才覺得這個 cooperative multitasking 真的大有文章在。

這邊有一個參考資料,比較了兩種 cooperative multitasking 不同的實作方式:

實作一: 讓語言本身的排程器可以被 I/O 觸發,在 I/O blocking 的同時,自動做出 context-swtich 。這是 golang 的實作法。
實作二:讓 I/O 呼叫變成 non-blocking 的。這是 Nodejs, Python, Clojure 的實作法。

原文如下:
For cooperative concurrency to work well with I/O, the language should either make the scheduler aware of the I/O calls (to be able to switch to another context while blocking) or the I/O should be non-blocking. The former requires runtime support in the language, like Go; the latter is what programming environments like Python (with asyncio) and Node.js (with its fully non-blocking standard library) do. The same applies to Clojure, where core.async is just a library without actual runtime support.

在 golang ,如果要應用語言本身提供的同步特性,常見的寫法是:
將有 I/O 呼叫的函數,放在一個被 go 關鍵字修飾的函數裡頭 (即放在一個獨立的 goroutine 裡),並且透過 channel ,將 I/O 呼叫的結果送出來。