从0开始搭建编程框架——思考
? ? ? ? 需求來源于問題。(轉載請指明出于breaksoftware的csdn博客)
? ? ? ? 之前有個人做前端開發的同學在群里問“C語言能做什么?能寫網頁么?”,然后大家就開始基于這個問題展開爭辯。有的認為是“不能,從來沒聽說過C語言能寫網頁”;有的說“能,連瀏覽器都是C寫的”。我想這是基于不同層面做出的回答。如果僅僅從語言層面來說,C的確寫不出網頁。但是從底層來說,C語言是可以做到的——大不了它自己設計一套描述語言來描述網頁。
? ? ? ? 但是又有幾個人會嘗試使用C語言去定制一個瀏覽器內核并繪制“網頁”呢?
? ? ? ? 所以我們不可能找到一項可以勝任所有場景的技術,于是“在一定的場景下,PHP是最好的語言”可能并不是一個笑話。
? ? ? ? 我們工作也摻雜著很多的場景,這些場景包括:同事技術棧和基礎知識功底,業務特征和資源消耗類型及難點等。
? ? ? ? 舉個例子。記得之前看過一篇Go語言之父Rob Pike講述的關于golang誕生歷程的文章(原文:https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html),其中他極盡嘲諷了一下C++的編譯速度,以及他認為很奇怪的一些特性。于是在他的預想的場景下,產生了設計新語言的需求。最終我們在golang中的確看到了“簡單”這個特點。但是比較諷刺的是,他希望借此吸引C++程序員的愿望并沒有達成,但是吸引力很多PHP或者Java語言棧的同學。
? ? ? ? 可以見得,有的時候我們發現的問題可能比較明確,解決的方案可能也非常恰當,但是最終可能在另外一個領域或者場景下取得不錯的成果。這樣的例子還包括最近在人工智能領域大火的Python。
? ? ? ? 當一個東西火起來之后,人們就開始思考它是否“放之四海而皆準”。我們在網上看到很多關于golang好不好的爭論,個人覺得“只有適不適合”,而不存在“好不好”的問題。
? ? ? ? 回到框架設計上面來說。我們需要先定義當前的場景、問題,然后找到一個恰當的方案。
? ? ? ? 為了讓此系列文章有繼續寫下去的意義,我假設當前的場景是:
- 團隊成員只有PHP語言基礎和經驗
- 團隊成員對C/C++了解僅限于大學教程,其他語言不會
- 團隊成員對多線程編程不了解,對操作系統了解很少
- 項目需要在半個月內完成
- 項目是CPU密集型網絡服務,經調研,在當前資源下PHP不足以支撐
- 項目的主要特征是網絡數據獲取并統籌計算,數據量不是很大
- 不能使用Go語言
? ? ? ? 除了最后一點,很多團隊可能都會遇到。但是如果沒有最后一條,可能這個系列也不存在寫下去的意義。
? ? ? ? 很顯然,希望突擊培訓成員的C/C++、多線程編程和操作系統基礎是不太可能的。即使這么短的時間內可以讓大家寫出代碼,但是代碼質量和維護性需要打上大大的問號,這對一個項目管理來說是非常不可控的。
? ? ? ? 那怎么辦?這個時候可能就需要我們設計一套易于使用的編程框架。它應該
- 把各種復雜的問題封裝起來,讓使用者對其無感。
- 可以將復雜的問題化簡為團隊成員經常面對的問題。
? ? ? ? 其中第二點是非常重要的一種抽象,因為當我們人類面臨未知問題時,最本能的思路是把它和已解決的問題進行對比。然后對已知方案進行修改和組合,以解決未知問題。
? ? ? ? 確定好基本目標后,我們就會面臨基礎方案的選擇問題。以我的經驗,這是整個框架設計和開發過程中最最煩躁的過程。因為我們面臨著很多種選擇,比如
- 查找各種基礎的框架
- 平行基礎框架的性能對比,
- 平行基礎框架的易用性、穩定性和可維護性
- 我們選擇約束什么,約束到什么程度
- 我們決定放開什么,放開到什么程度
? ? ? ? 很多似是而非的問題,很可能沒法做到定量分析和對比。于是框架的設計者的經驗、偏好和哲學就會發揮作用。
? ? ? ? 略掉中間過程,假設我們最終選定brpc作為網絡框架(使用見《brpc介紹、編譯與使用》)。現在就需要基于它來解決一些設計問題了,我們只以“多線程”這個問題為例。
? ? ? ? 讓我們的成員熟悉多線程編程?不現實,很多寫了很多年的老手也經常在線程同步上栽跟頭。
? ? ? ? 編寫一個線程池?不太好,雖然避開了線程管理的問題,但是還是保留了線程的概念。而且目前場景下,有足夠的時間來寫一個超越brpc中使用的bthread的庫么?
? ? ? ? 直接使用brpc中的bthread?不太好。因為可以參見文檔(https://github.com/brpc/brpc/blob/master/docs/cn/bthread.md),其中提到一句“你不應該直接調用bthread函數,把這些留給brpc做更好”。
? ? ? ? 那怎么解決?回顧之前提到的哲學:將未知問題轉化成已知問題。我們是不是可以把每個異步過程看成一次請求呢?
? ? ? ? 具體的做法是,服務開啟一個內部端口,原來需要獨立線程執行的過程變成該端口下的一個服務策略提供服務。
? ? ? ? 這樣我們就將多線程問題抽象成一個請求,將團隊成員未知的問題變成了已知。
? ? ? ? 當然,會有很多人提出異議。比如這么做是否最好?參數序列化的代價?不可否認這些都是問題,但是在之前介紹的場景下,這個方案不算差的。
總結
以上是生活随笔為你收集整理的从0开始搭建编程框架——思考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据竞争(data race)问题分析的
- 下一篇: 从0开始搭建编程框架——主框架和源码