對接口編程, 不要對結構編程 ---- Python 經驗對 C 編程的考慮

通常, 如果幾行SHELL可以搞定, 不會用 Python. 幾行 Python 可以搞定的, 也就懶得用 C 了.

Python 最好用的是語言級的 list 和 dict 支持. 還有如 generator 可以帶來另外的編程範式, C 裏類似的效果, 常伴隨理解困難和BUG. 另外一個是Python的文件模塊化, 對象抽象和各種類似于Decorator的東西, 不僅是編程方便, 也提供了編碼工程上必須的分離. lambda 表達式也是 C 裏尚沒有的.

前時, 泛讀了 C Interfaces and Implementations (是的, 窮人的電子版), 突然對以前在哪看過的一句話非常贊同起來: 編程, 對外暴露接口, 不要暴露數據結構. 如此相反的觀點, 任何抽象都太重, 曾經左右我.

如果能接受腳本語言, 自然能接受C語言裏抽象的接口, 而隱藏數據結構. Python 的方便其實也自此而來.

Python 相比 C 的問題主要是運行慢, C 相比 Python 的問題主要是編碼慢, 易錯, 調試難, 缺泛強大的標准庫.

如果有熟悉的 LIST, Hash-Table, AVL, Sequence 的實現, 熟悉到可以像 Python 的 list, dict 那樣隨手拈來, 用 C 編碼也是很快的. 這些數據結構的通用實現, 自然要求隱藏數據結構. 這樣, 只要接口不變, 你可以方便的換一個實現, 只是需要重新編譯, 或者, 再加一層, 用來轉發到具體的實現, 像在很多 C++ 代碼裏見到的 FooInterface, FooImpl.

喜歡 Generator 的人不好應付一些. C 裏有一些 coroutine 的庫, 但在各堆棧跳來跳去是此編程方式的BUG發源地. 用事件狀態機加多線程是C的經典且易理解的編程方式, 我放棄協程這一條, 就像 Lambda 一樣.

程序, 大部分處理數據, 部分生成數據(處理需要理解, 比生成困難), 小部分是生成不可預測的數據, 也就是 BUG 隱藏地和隨機數的生成地.

在所有的調試方法裏, 某些人偏好 printf 和 assert. 對一個函數的前件和後件多作一些 assert, 很多BUG可以不寫測試也能發現. 程序正確性証明的一個方法就是証明不變量, 對不變量作 assert, 就會c對程序的正確性自信得多.

半年用 Python 的經驗是 Python 更容易寫錯誤的代碼, 多半是運行時才會發現. 只是Python會打印一個錯誤堆棧和出錯位置, C 裏同樣的功能可以設置 core 文件大小限制來得到.

No comments: