Programming - FrankNine/franknine.github.io GitHub Wiki
講者推薦
一切的根源:SICP
- SICP 中文字幕(1986)
- Structure and Interpretation of Computer Programs
- 第一版課本 Lisp(1985)
- Structure and Interpretation of Computer Programs - JavaScript Edition
- 第二版課本 JavaScript(2022)
- SICP Language
筆記
- 大型軟體系統工程不像其他工程受材料物理特性限制,僅受人類心智處理複雜度能力限制
- 人類心智能力有限才需要分層與抽象,機器自己不需要整理程式,Program Counter 一直跳就能執行
(甚至切分對機器還是累贅所以才有 Compiler Inlining)
- 人類心智能力有限才需要分層與抽象,機器自己不需要整理程式,Program Counter 一直跳就能執行
- 三個抑制複雜度的方法
- 黑箱抽象
- 將人承受的資訊量減少,隔絕下層資訊對人心智造成的負擔
- 要素
- 基礎元素(Primitive Elements)
- 合成的方法(Means of Combination)
- 抽象的方法(Means of Abstraction)
- 把複雜的東西裝進黑箱
- 加以命名使其像是基礎元素
- 繼續往上構建(使用者應該要無法區分基礎元素跟抽象過的合成元素)
- 通用介面
- Metalinguistic Abstraction
- 建立一門語言,解決一類問題。這們語言在上層需求改變時能承接住變化,使變化不繼續往別層擴散
(重見於 Patterns of Enterprise Application Architecture 的 Layering 跟 Gorking Simplicity 的 Stratified Design) - Lisp 的能力可以改造文法,甚至是改到不同範式(Paradigm)(想像以這個能力做 DDD)
(John Carmack 的 反對使用 這種可塑性,覺得 Scale Up 後會有一塊難以理解的語言核心不方便交給不夠資深的人。可能範例:Continuations: The Swiss Army Knife of Flow Control 你要懂 call/cc 才能知道為什麼要檢查 call/cc 的回傳是不是procedure?
)
- 建立一門語言,解決一類問題。這們語言在上層需求改變時能承接住變化,使變化不繼續往別層擴散
- 黑箱抽象
- Wishful thinking
- 想像還沒動工的下層,已經做成上層最想要的介面
- (Top-down Approach,重見於 Programing to Interface、TDD)
- 想像還沒動工的下層,已經做成上層最想要的介面
- 從沒有狀態的 Lisp 進到有狀態的 Lisp,感受狀態有多難實作跟處理
- 狀態在硬體是自然,在計算理論是難以維護。什麼地方要給機器自然取硬體的力量,什麼地方要給人推論自然?
OO:Sandi Metz
- Nothing is Something
if
關鍵字可以以對物件送if_true
Message 替代if ( 1==1 ) puts 'true' end
class TrueClass define if_true yield self end end (1==1).if_true { puts 'true' }
if
對 Procedure 自然,對 OO 不自然(重構:以多型取代條件表示式)- Null Object Pattern
- Active Nothing
- if null then do something => 在 null 的位置放一個收到共通 Message 會跟 null 一樣 do something 的物件
- Inheritance is for specialization, not for sharing code
- 將繼承到卡在多重繼承的程式,觀察出有演算法跟 "沒做事演算法" 兩種行為,抽出這兩者改成可 Composition 物件替代繼承
Object plays as the thing that varies
- 0 的概念類似於這裡的 Nothing
- 99 Bottles of OOP
- 以小歌唱遊戲逐步加入規則示範 TDD 跟 Refactor 應對需求改變
Test:Ian Cooper
- TDD, Where Did It All Go Wrong
- 有寫測試的人就是比 Move Fast and Break Things 的人慢交付商業價值
- Duct Tape Programmer 短期更受青睞,非技術人員就是愛 Shipping,不管 Code 好不好
- 以 Developer Test 代稱 Unit Test。Unit 的定義已經混砸,原本是指 Test 不是指一個 Class
- 用到 Mock 就是測到實作細節,Refactor 定義上只改實作細節不改行為,理不應造成測試需要修改
- 沒有非技術客戶願意跟你一起讀 Fitness、Gherkin、SpecFlow
- 在整個 Feature 開發週期 ATDD 都是紅的,沒有在過程提供任何幫助
- 開發者也不想寫,他們只想建構程式,ATDD 沒有可見的好處
- 回到 Kent Beck 的 TDD,移除後來加的違建
- 原初 TDD:避免測試實作細節,測試行為(Avoid testing implementation details, test behaviours)
- 以加入一個 Method 開始 TDD 循環是錯的,TDD 觸發條件應該是實作一個 需求 (我想要軟體做到的事、Use Case、Stroy)(客戶沒有給你希望某個內部實作 Utility 方法執行結果正確的需求)
- 測 Public(Exported)API (API 非 HTTP 或是 ATDD)
- 測試單位不是一個 Class(Class 不是 Unit,太在意要單獨測 Class 導致 Mock 過度),是整個模組向外的 Export
- BDD 名詞不應該存在,一開始 TDD 就該測 Behaviour,而不是測錯成實作再喊 Test Behaviours 繞回來。BDD 名詞本身只是重造 Kent 的輪子
- Test First 等於是預先設想還不存在的 API 該怎麼樣才好互動(SICP 的 Wishful Thinking)
- 隔絕的單位(Unit of Isolation)是測試,測試間隔絕影響,不是把單位當成一個 Class 把它 Mock 到出來(也不要把非 API 的欄位弄成 Public 或是使用
InternalsVisibleTo
,測試就是只到 API) - Red-Green-Refactor
- Red:證明沒有實作測試會失敗,寫的測試有鑑別力
- Green:求測試通過,手段多髒都可以,速度要比美上面討人厭的 Duct Tape Programmer。過程中學習該如何實作(Speed Trumps Design)
- Refactor:把 Duct Tape 在有測試保障的情況下理成好 Code,速度完不要留垃圾禍害人
- 不能寫任何新測試,Refactor 照定義沒有改並沒有改變行為,沒有新行為就不應該有新測試
- Refactor to Pattern,知道怎麼做到功能(Green),才能 Apply Pattern
- 你很難同時寫對跟跟寫好,改求分開兩次:一次寫對/探索理解問題的答案(Green),一次寫好(Refactor)
- 在 Port and Adaptor 的 Port Unit 測試(以測試夾住 Impure-Pure-Impure 的 Pure)
- 往外以 Integration Test 處理 Impure
- 最後使用者最外層 End-to-End System Test
- 不應該測試時使用 IoC Container,有需要代表結構不對沒有做到 Dependency Rejection
- 檔位,高檔位程式太簡單直接寫,低檔位問題困難要寫額外測試輔助(寫實作的輔助測試,完成後要刪除,不能留下,理由同上沒有新行為不應追加測試)
- 有寫測試的人就是比 Move Fast and Break Things 的人慢交付商業價值
- TDD Revisited
Functional (業界):Kevlin Henney
- Refactoring to Immutability - Kevlin Henney
- Structure and Interpretation of Test Cases
- 如同 SICP 的引言,測試應該為了想要理解程式的人寫,剛好能被機器執行跟驗證
- 測試如同文件,SOLID Refactor 測試過頭會妨礙文件的功能,測試跟 Production Code 不一樣
- Unit Test 執行成功與否應該只取決於 Unit Test 本身跟 Unit under Test 的正確性
- 才對測試有功效有信心,才能加速開發
- 引入 Side Effect(檔案讀寫、網路...)後就無法滿足這個定義,系統一定有 Side Effect 所以一定有無法 Unit Test 部分
- 如何用程式傳達觀念?
- 反對 Test Case 三段命名,改以類似說故事方式撰寫
- 如同 SICP 的引言,測試應該為了想要理解程式的人寫,剛好能被機器執行跟驗證
Dependency Injection 的替代:Mark Seemann
- From Dependency injection to dependency rejection
- Impure - Pure - Impure 三明治
- 又稱 Clean Architecture、Hexagonal Architecture、Port and Adapters... 但重點一直是識別 Pure / Impure
- 很多時候你想做 Dependency Injection 只是因為你想在三明治內層 Pure 的部位打 Side-effect,往兩頭外層推就不需要注入了(Dependency Rejection)
- Haskell IO type 明確標示 Side-effect 就不像 F# 能在 Pure 裡面混雜 Impure(IO Type mismatch),用 Haskell 寫會自然產生 Impure - Pure - Impure
- From dependency injection to dependency rejection
- Impure - Pure - Impure 三明治
- Favor real dependencies for unit testing
Functional (學界):James Koppel
Functional DDD:Scott Wlaschin
- Domain Modeling Made Functional
- 使用 Sum Type 做 DDD 效過遠好過沒有的語言使用繼承
- Domain Modeling Made Functional
- Railway Oriented Programming
-
Twitter:Monad 不難,但是他沒有現實中的比方。看到在打比方的教學就直接關掉,像是盒子、馬桶塞甚麼的。唯一可以看的比方是 Scott Wlaschin 的 Railway Oriented Programming[0],但是鐵路比方的是 Maybe Monad 不是 Monad。Monad 就是這麼 Meta,但是不難。
-
Optimization:Casey Muratori
- Simple Code, High Performance
- Witness 的 Ray Cast 案例:以對問題的知識限縮問題的 Domain,尋求以簡單解替代通用解(ex 往下透影取代可以任方向射線的 Ray Cast Library)
-
Twitter:最佳化之神終於做了比較入門的教學 (大部分聽得懂)。用第一原則分析硬體能做多少 ops,會發現現在很多程式都比理論速度慢三個數量級以上。不過這也大概是業界不同的關係,遊戲界效能就是真金白銀的競爭優勢,早期大家都是比誰能從機器榨出比較多的效能來畫面輾壓對方。
- "Simple Code" Follow-up Part 1: A (Very) Simplified CPU Diagram
- "Simple Code" Follow-up Part 2: Analysis with Compiler Explorer and UICA
- Where Does Bad Code Come From?
-
Twitter:SOLID 沒有被用實際的數據量測(有遵循跟沒遵循相比,使用人月的增減、產出的品質、新進人員閱讀上手所需要的時間),不像演算法 Big O 一翻兩瞪眼。變成不確定有沒有用的東西一直流傳(我自己覺得 Scrum 的爛帳也是)
務實就是數據說話,Clean Code 像是宗教儀式 - "Where Does Bad Code Come From?" - Q&A
- 沒有人能預先設計出所有實作細節,如果能就等於你已經有程式了
- 決定實作細節是探索的過程,有 35 年經驗還是不會跟你說這不用試
- 預寫設計文件因為不完整無法執行量測,只會把探索鎖死在不知好壞的位置
- 文件記錄做過的事,而非訂死要做的事
-
- The Only Unbreakable Law
- Conway's Law
- 軟體架構會長得像公司人事組織架構,加上 Leagcy Code 帶進來的過往人事架構
- "Clean" Code, Horrible Performance
- Performance Excuses Debunked
- 以 Facebook 為例
- 雖然 Facebook 持續 Rewrite 求效能,但是不是也是低效能的東西先讓他們出 Feature 活下來才有後面的求效能?
- Twenty Minutes of Reasons to Use the RemedyBG Debugger
- Video Game Programming From Scratch With Casey Muratori
Design Pattern:Bob Nystrom
- Game Programming Patterns
- Crafting Interpreters
- What Color is Your Function?
- Iteration Inside and Out
名人對談(戰)
- Is TDD Dead? - DHH vs Kent Beck - TDD or not
- "Clean" Code, Horrible Performance - Casey Muratori vs Uncle Bob - Is clean code bad
- Uncle Bob vs Casey
語言
- On rebooting: the unreasonable effectiveness of turning computers off and on again
- 當程式進入 "不預期" 的錯誤狀態,程式設計師沒有準備相應的錯誤處理程序時,唯一合理的行為就是洗掉狀態重來
- "不預期" 與 "Jazz" 的類比,Jazz 有指定要即興發揮的橋段
"Play whatever you want" from Genesis Noir: Bringing Jazz Improvisation To Gaming
- 但是即興是不合理的行為(例如 Unity 吃到 Managed Exception 還會繼續跑)
- 重啟有粒度之分,當 Function local state 爛掉重新呼叫即可、Global state 爛掉重啟程式就好、OS 狀態壞掉要重開機、傷到開機區就要重灌了,有這種粒度之分
- 控制重啟粒度的系統 Erlang supervisor
- 能自動重啟還是要蒐集鑑識資訊抓現在未知,以後該已知的錯
- C Isn't A Programming Language Anymore
- 作業系統都用 C 或是 C++ 當操作介面,使得它們定位在其他語言之上
- Composition over Inheritance
- Composition > Inheritance 範例
- A list of programming playgrounds
Lisp
Scheme
遊戲應用
- Dan Liebgold - Racket on the Playstation 3? It's Not What you Think!
- Crash Bandicoot Co-Creator Andy Gavin: Extended Interview: G.O.O.L.
Haskell
- Graham Hutton
- Free Monad
- Effect System
Objective-C
JavaScript
Python
Unicode
Category Theory
- Category Theory by Bartosz Milewski
- 27 Unhelpful Facts About Category Theory
- The Mathematician's Weapon
Optimization
Monad
- I would complement it with
- Monad transformers down to earth by Gabriele Petronella
- 層套的 Monad 無法像 Functor Generically 拆開
- 但是可以寫特製的 Monad Transformer 拆開內層,外層能繼續 Generically Compose
- 推友回覆: https://twitter.com/viktor_lin/status/1548248515838877696
Free Monad
- 如何理解 Free Monad?
- Monad for Free
- 如何评价Freer Monads, More Extensible Effects?
- What are freer monads?
- Play with free monad
Effect
測試
- Automated testing for Call of Duty
- Per-commit build 約 30 分,會平行建置,真的塞車會 skip
- 自己用 Python 撰寫,Build script 是 Python 直接在目標機器執行
- 問題做 ID 分 Bucket,有些問題 Auto-retry、有些重開測試機或是禁用,避免 Error 太多
什麼能 Auto-retry 很看情況 - 控制使用者安裝軟體:Puppet
- 主機比 PC 穩定適合截圖或比較數據
技術
- Choose Boring Technology
- 未知有分 已知的未知 跟 未知的未知,使用新技術容易在 未知的未知 上出意外
- 將採用新技術當作消費創新代幣,限制你專案的代幣用量
- 總成本 = 維護成本 - 加速的效益,一切還是求利大於弊
- 一窩蜂驅動開發
- 潮流未必可信
- 投資報酬率,還是求 Z > B
- 短時間低成本試毒
- The compiler will optimize that away
- 現在流傳的語言設計在 Memory Latency 跟 CPU Latency 差不多的年代
- 新的語言應該處理降低 Random Access 次數
- 語言等級的 Array of Structure to Structure of Array 轉換 (JAI)
-
Twitter:處理器跟記憶體的速度落差越來越大,已經是以前的 400 倍差距。當初覺得 Random Access Object 造成 Cache miss 是可接受的妥協,現在是無比的浪費。後面也拋出由語言做 AoS 變 SoA 的可能
- Legacy • Chad Fowler
演算法
- Big O myths busted! (Time complexity is complicated)
- Time complexity != time
- Slope
- Constant
- O of line count or file size are different
- Time complexity != time
- https://twitter.com/BruceDawson0xB/status/1120381406700429312
紀錄片
- React.js: The Documentary
- https://twitter.com/aaefiikmnnnr/status/1644345389204795398
React 的訪談紀錄片,算是蠻完整記錄一個新的 Library 如何在公司體系存活下來、由少量的先行者說服公司投資人力、在 Library 之外完善 Documentation 以求 Buy-in、撐過公司使用既有技術的人的阻力、開源(不太順利)、最後到慢慢改變與外界互動方式建立起社群的過程。
- https://twitter.com/aaefiikmnnnr/status/1644345389204795398
- Kubernetes: The Documentary Part 2
- 最接近使用者的 Orchestration 介面最有價值
- 成立 Cloud Native 基金會避免原來條款寫要給 Google Re-license 權利造成 Contributor 遲疑