建設繁榮的開源生態,純粹只靠研發是遠不夠的,尤其對於追求分佈式技術與協同開發的 Web3 領域項目來說更加重要,因此便需要一套系統性流程以此讓項目更具 “親和力” 以及持續迭代能力,其中就包括開源協同、文檔撰寫、翻譯、技術文章傳播... 本文將從「技術寫作」角度為項目構建者提供一系列觀點與方法論。

— 導讀(Web3Caff 編輯部注)

原文:开源软件的技术写作(夜天之书)

作者:tison 丨 Web3Caff 經授權發布

封面: Photo by Shahadat Rahman on Unsplash

開源社群雖然是圍繞開源軟件建立起來的,但是建設繁榮的開源生態,依靠只讀的源代碼是不夠的。建設繁榮的開源生態需要開源協同,而協同的基礎是溝通。溝通不僅有論壇和聊天室的交互式形式,還有主動的內容生產和發布,包括不同受眾的文檔的撰寫和翻譯,以及技術文章的傳播等等。這些內容創造都可以歸類為技術寫作,也就是說,圍繞開源軟件的技術寫作,是建設繁榮的開源生態的重要一環。

本文嘗試討論這些不同類型的技術寫作在現實當中被採納和運用的情況,以及它們相應的價值。

開發過程

雖然大一統的低語總是想讓我說 “代碼也是技術寫作的一部分”,但是我還是克制了這個衝動。不過,軟件開發的過程當中,為了提高軟件的可理解性和可維護性而刻意寫好的代碼註釋和提交信息,確實可算作是技術寫作的一部分。畢竟,很有一些開源軟件即使增長到一定的複雜度,也沒有半行註釋,提交信息裡全是 updatesave  或 fix  這樣不明所以的單詞信息。

代碼註釋

代碼註釋的重要性在許多軟件開發的最佳實踐當中都有提及,總結下來我認為不外乎三點。

  1. 關鍵設計要有模塊註釋,接口和數據結構要有基本的說明註釋。
  2. 實現上的 trick 要有行內註釋。
  3. 清晰明白的代碼不需要囉嗦的註釋。

第一點可以分成兩個部分,第一個部分是通過模塊註釋提綱挈領地說明模塊的設計動機和思路。一個軟件往往由多個模塊構成,每個模塊又由多個小模塊構成,這樣層層拆分下去,每一層都有模塊設計的註釋,對於有志於投入到代碼開發或使用的參與者來說,就是一個循序漸進且每次都能處理適量信息的過程。

這一方面做得尤為出色的是 Rust 的標準庫註釋。雖說是註釋,但是在 rustdoc 渲染工具的加持下,這份註釋其實直接就可以作為實現文檔呈現出來。Rust 的標準庫註釋從最上層介紹了標準庫的構成和各個模塊的職能,到每個模塊細分之後同樣復刻最上層的介紹模式,直到每一個具體的數據結構和方法的接口定義。可以說,開發 Rust 標準庫的程序員和使用 Rust 標準庫的程序員,都反復多次閱讀過這些註釋文檔。

Rust 的標準庫註釋

廣泛使用的編程語言的標準庫註釋似乎總能做得十分完善,Java 的標準庫註釋也類似。尤其是我時常翻閱的 Java 並發模塊的註釋,由於並發的複雜性和設計上依賴約定的特性,詳實的註釋文檔顯得尤為重要。

Java 標準庫並發模塊的註釋

由於標準庫做出了好的示範,並且提供了好的註釋文檔化支持,Rust 生態的軟件和 Java 生態的軟件,大多能夠考慮寫好模塊註釋。語言對註釋的支持是很重要的。

例如 Rust 按照模塊拆分,支持了簡單的模塊註釋手段和 Markdown 語法,程序員就很容易順著這條預設路徑寫出好的註釋。反觀 Java 是以類來組織代碼的,優秀的項目往往會在類註釋內寫好詳實的註釋,但是 package-info.java  的用例並不流行,甚至很多程序員都不知道有這麼個東西,JavaDoc 生成出來的內容比起 rustdoc 更加難以閱讀,尤其是因為缺乏模塊的概要註釋,以至於根本不知道應該看哪部分代碼。所以 Java 程序員往往是直接閱讀源碼上的註釋,而不是到對應的 JavaDoc 網站上閱讀。

狀態機經常需要註釋定義

回過頭看 Rust 的文檔,雖然生成的頁面非常精緻,對模塊文檔的高度支持讓 rustdoc 生成的內容幾乎就是一份形式上優質的實現文檔,但是在代碼內鏈接的部分,如果直接讀源碼註釋則很難像 Java 註釋一樣方便的跳轉。當然這有可能是編輯器和集成開發套件對這類跳轉支持還不足的原因,但是確實會影響註釋產生的實際價值。

缺少工具支持,直接閱讀註釋不方便

第一點的第二部分是對第一部分的補充。除了大段的模塊註釋,組成軟件對外契約的接口和公共數據結構,需要有基本的說明註釋。也就是說,這個數據結構的用途和各個字段的定義,接口方法的用途和輸入輸出的約束等等。這些接口和數據結構往往被下游所引用和依賴,軟件分層、抽象和封裝的目的就在於使用者只需要閱讀接口契約就夠。

典型的接口文檔

第二點比較好理解。如同前幾天我發出的討論技術債問題的推特,很多時候實現上為了速度或者確實有客觀複雜度難以理解,需要對實現做具體註釋,例如經典地告訴別人不要亂動某幾行代碼。這樣的註釋是不可避免的。

THIS IS A HACK

第三點某種意義上是對前兩點的總結,也就是說除了公開定義的數據結構和接口和模塊的註釋,以及實現上必須澄清的細節,其他的註釋能少則少。這也是 《重構》當中頗為反直覺的一個論斷,書中給出的解釋如下

當你感覺需要撰寫註釋時,請先嘗試重構,試著讓所有註釋都變得多餘。

我同意這個觀點。技術寫作不必卷帙浩繁,內容不是越多越好,簡練準確地傳達出完整的信息,是註釋要達到的效果。

提交信息

代碼註釋之外,與開發活動密切相關的另一個技術寫作的實例,就是撰寫提交信息了。

現代開源軟件大多有源碼控制系統版本化的管理,每次變更都會經過提交補丁和代碼評審,通過後方可合併到代碼倉庫中。提交上來的補丁會包含提交信息,如果用 Git 管理,那就是所謂的 Git Commit Message  的內容。

關於如何寫好提交信息,相關討論和材料不少。總結下來,我認為有以下幾個關鍵點。

第一點,參考 Conventional Commits  的分類,根據項目特點突出每個提交的目的。同時,Conventional Commits 標準還給出了提交信息的基本格式指南。

第二點,為了突出提交的目的,標題採用祈使句而非陳述句,也就是說提交信息標題讀起來形如 “(應用這個補丁,將會)實現某個功能/修復某個缺陷”。

第三點,提交信息內容主要關注為什麼要做變更和做了什麼變更,而不是變更的細節或實現方式。如果項目使用 issue tracker 等工具記錄需求和缺陷報告,通常可以簡化為提供一個到 issue 的引用。如果實現細節 trick 是軟件知識的一部分,也應該記錄在案。這跟註釋的分類方式是類似的,具體如何取捨詳略,只能在實踐當中根據直覺和同行評議交流積累經驗了。

第四點,可能比較容易引起爭議,我個人傾向於合入主分支的提交信息省略開發中間過程,保持主分支的線性提交歷史,每個補丁提交的信息都是經過開發、評審、修改後的結論。Linus 設計 Git 的時候,其 git-merge 功能實際上會把開發分支的所有 commits 都合併到上游分支裡,這就導致開發的中間過程被保留。往往多個分支互相反复 merge 以後,提交歷史就變成一個複雜的有向無環圖,難以閱讀。當然,我認為開發的中間過程有其自身的價值所在,不過在 GitHub 式的平台接管開發流程的今天,這種在 pull request / merge request 交互過程中產生的中間狀態,可以由代碼託管平台記錄下來,作為提交歷史的外掛擴展信息存在。通常,只需要在提交歷史裡提及對應的 request 鏈接,即可關聯上相關信息。

代碼註釋和提交信息,是在一線開發環境裡產生的一手技術寫作內容。實際上,如果這部分相對上游的內容生產被主動管理起來,生產出高質量的內容原材料,下游無論是文檔還是宣傳內容,都將受益匪淺。

文檔

前文提到註釋的時候,我經常會下意識地寫成註釋文檔或者文檔,這是因為註釋可以理解成與代碼共同演進的文檔。其實,《活文檔》一書中就曾經提及,以開發過程中誕生的知識為源頭活水,隨軟件開發不斷進化的文檔,或者叫 “活文檔”,才是可靠、高效、協同且有見地的文檔。

雖然如此,為了編寫描述實現細節、模塊設計、開發流程和使用方式的文檔,所需的技能集與代碼開發還是有很多不同。儘管有不少開源項目的文檔是由開發者順便完成的,但是無論是在企業當中,還是組織複雜度達到一定程度的開源團隊當中,都會形成專注文檔內容輸出的子團隊。

如前所述,根據受眾用途的差異,文檔可以粗略地分成用戶文檔和開發文檔;根據受眾地域的差異和全球化的需求,文檔團隊又需要考慮國際化和本地化的問題。

討論文檔問題,可以從一個項目的 README 文件說起。這是開源運動伊始時就在開源項目的創作者中間傳播開來的最佳實踐。簡單來說,無論你是一個開發者,獲取到了開源軟件的源碼壓縮包,還是一個用戶,獲取到了可供編譯的源碼壓縮包或預編譯的二進製文件發布包,解壓縮以後的文件集合裡,通常都會有一個 README 文件簡要介紹該軟件的名稱、定位用途、使用方式、作者和著作權,以及其他聯繫方式或相關材料的信息。可以說,開源軟件最初的專門文檔,就是從 README 開始的。即使在今天,瀏覽託管在 GitHub 上的軟件代碼倉庫,首頁上最引人注目篇幅最大的,還是渲染 README 文件展示出來的頁面。

Python 解釋器的 README 文件

對於國際化和本地化的問題,往往首先被考慮的也是 README 文件。例如 Perl  就完成了中日韓等語言的 README 文檔翻譯和本地化。

用戶文檔

用戶文檔,顧名思義就是寫給用戶看的文檔。

這看似是一句廢話,卻是不少開源項目用戶文檔質量不佳的癥結所在。因為如果完全從開發者的角度出發,很容易因為過於了解實現細節,深度參與了設計討論考慮了太多極端情況,而在用戶文檔的行為上不能換位到目標用戶的知識儲備和熱點路徑,經常出現專有名詞或內部知識堆砌,或者熱點路徑和極端情況篇幅詳略不當的情況。

對於這些情況,本文不做過多展開。還是把重點講回到好的用戶文檔實踐當中。

文檔的發布有多種形式。如今互聯網發達,成本低廉,大部分用戶閱讀文檔的手段是在線文檔,這些文檔不僅包含文字和圖片,還可以連接到音頻,甚至嵌入在線互動模塊。當然,還有以 EPUB 或 PDF 格式發布的文檔,常見於羅列所有命令、接口或規格的參考手冊當中,典型的包括 Intel 各個類型芯片架構的指令集文檔,硬件驅動的接口文檔等等。

關注到開源軟件主要採用的前一種形式,好的文檔網站還是有許多的。

我最喜歡舉例的是 Spring 框架生態的文檔矩陣。官網就是它的入口,頂端導航欄 Projects 按鈕列出生態內 Spring Boot 和 Spring Framework 等一系列子項目的入口,Learn 按鈕列出了半小時內快速搭建任何一項功能的樣例項目的教程。

這裡值得特別提出的就是 Spring 豐富的教程。從文檔遞進關係上 Learn 按鈕下的 Quickstart  展示的是 Spring 生態當前強推的 Spring Boot 一攬子框架。Spring Boot 項目的意義就在於快速啟動一個包含多個 Spring 生態模塊的項目,首先展示這項內容,抓住了絕大部分用戶最熱點的問題,可以說不只是二八定律,而是用 1% 的投入換取了 90% 問題的解決。

我曾經和不少開發人員或技術寫作人員討論過,一個共識是專業人士往往由於掌握了高級知識,對問題有全面的了解,在寫作文檔的時候,總希望把內容全面的介紹出去,或者有些賣弄的動機在裡面;同時,容易對難題產生極大的興趣,以攻破難題為首要目標。實際上,文檔寫作經年沈淀的經驗當中,能夠總結出 TL;DR 和 FAQ 這樣的縮寫詞,就是因為這是大部分的天性。也就是說,太長的內容不會看,少數幾個最常問的問題組成了所有問題人次中的絕大部分。

其實,從知識成長的曲線也不難看出,自然演進的結果下,入門材料永遠是最多的,點擊頻率也是最高的。內容文檔團隊想要生存下來,做好入門材料是一個百試不厭的護身符。

Spring 文檔矩陣在 Quickstart 之下,是針對大量細分用戶場景的 Getting Started Guides  文檔。我在學習和使用 Spring 生態的過程中,大量參考了這些指南文檔。無論是你想要連接數據庫,提供 RESTful 接口,對接各種系統,部署上雲,使用 Gradle 管理 Spring 項目構建,都可以在這裡找到一個合適的入門點。

前面提到,入門材料是內容文檔團隊生存的護身符。不僅如此,做好入門材料也是挑戰難點的前提條件。真正能夠憑藉一己之力或說動力,跨過入門階段探索進階用法的人少之又少,絕大部分潛在用戶一試不成,也就放棄了。其實我也是如此,每次我遇到一個需求,想要尋求開源解決方案的時候,如果三兩下試不出來解決好我的基本問題,那也就放棄了。如果基本問題被解決了,那麼如何解好,發現軟件的高級功能並從中受益,才會更加順理成章。

高新科技派的代表是 Kubernetes 的交互式教程。其實這種形式的 “文檔”,我在大學期間通過 Codecademy 學習 Ruby on Rails 的時候就接觸過了。隨著 Katacoda  等構建交互式教程的工具的推出,相信以後這類 “寓教於樂” 的教程還會更多。

很多年前,有人提起前端的受眾遠多於後端的原因,就在於前端的教學反饋更加及時,所見即所得,用戶可以直接視覺化的看到自己的 “努力” 的收穫。反觀後端的上手過程,大多是和終端打交道,越是深入進去,成功的喜悅就越是建立在一個正常的退出碼,一段正確打印的內容,一個沒有崩潰的程序,想要從這種體驗中得到激勵,本身就有一定的選擇性。用戶文檔的受眾是一般用戶,順應人性而非考驗人性是一個基本要求。讓用戶快速地用起來,解決實際應用場景的問題,比軟件本身的正常運行和底層接口返回了正確的結果,更能切中要害。

用戶文檔不僅僅是用來入門和指導搭建原型的,還有排查問題的作用。TiDB 的文檔在設計的時候就考慮到了這一點,在每個容易出問題的地方附上對應的 Note 或 Troubleshooting 段落。不過,文檔終究不是用戶排查問題的第一順位。一般來說,在故障發生的地方就地打印提示信息幫助排查,是最有效的。除此以外,用戶通常會在 Stack Overflow 及其他典型問答網站或搜索引擎上尋找問題的解法,面對這個場景的內容運營我會在最後 “寫作之外” 一段當中再次提及。儘管如此,文檔還是一個記錄常見問題官方認可的解法的好地方。例如,Flink 用戶經常會碰到 Class Loading 的問題,這在官方文檔中就有一個專門的頁面介紹 Flink 解決 Class Loading 的整體思路和典型問題的可能解法。

開發文檔

好的用戶文檔案例還有很多,數據庫領域的臥龍鳳雛 PostgreSQL  和 MySQL  的文檔就是經典之一。不過,這兩份文檔不僅僅是給用戶看的,其中涉及了不少模塊設計、數據結構和接口設計,以及設計哲學,不僅試圖兼容這兩大數據庫軟件的團隊成員必須了解,所有數據庫從業人員都能從中獲益。

如果你去搜索 TiDB 代碼當中以上面 MySQL 文檔網站為引用的註釋,能夠從執行模塊找到許多個匹配結果。可以說,要想兼容 MySQL 的語義,從文檔和實現中復刻一套數據類型和表達式是不可避免的。同樣還有試圖對接或者復刻 PostgreSQL 的軟件,例如現在想要支持讓 psql 直接訪問自研的數據庫服務,那麼了解 psql 的通信協議,實現對應的服務端編解碼模塊就是必須的。

開發文檔主要受眾是軟件開發者。當然,前面用戶文檔一段裡,Spring 的用戶也是業務軟件的開發者。開發文檔的開發者,詳細說來分成生態開發者和內核開發者,與直接生產業務軟件乃至只是通過鼠標鍵盤和軟件交互,不以編程方式交互的終端用戶是有差別的。

生態開發者與終端用戶有一定的相似之處。他們都不會關心軟件的內部實現,主要關心對外暴露的接口。不同的是,終端用戶直接生產不可複用的業務軟件,或者不以編程的方式與軟件打交道,而生態開發者往往圍繞著軟件暴露出來的接口或插件框架,實現自己的插件或者將這個開源軟件與另一個生態連接起來。

插件開發,也就是對開源軟件完成某項工作的功能模塊做出抽象,允許加載第三方提供的實現。例如 Flink 讀取數據源的模塊,官方定義了接口,並提供了 Kafka 和 HBase 等一系列常見系統的對接。第三方開發者為了與企業內部系統對接,或者對接一個官方沒有支持的開源軟件,就可以根據開發文檔實現 Flink 定義的接口,並根據文檔裝載和啟動。

軟件開發往往開始於解決一個特定問題。如果這個問題過於特殊或者簡單,可能軟件的開發週期就到此為止了。如果這個問題可以泛化,或者軟件本身就定義了一種新的方法論,那麼軟件的複雜度就會隨著時間日益增加。例如 Apache Flink 提出了一個有狀態流處理的計算框架,那麼與整個大數據生態的對接,就是其演進的必經之路。一個人或一個相同背景的團隊,很難完成對世界上形形色色場景的覆蓋,通過開源協同來豐富生態,是開源軟件能夠吞噬軟件世界的一個基本前提。因此,強盛的開源軟件往往會有豐富的擴展點,繁榮的開源社群會有大量的生態開發者將軟件及其方法論傳播到每一個有用戶需求的地方。

例如,Flink 不僅通過 Connector 抽象了與其他數據源的對接,還通過 State Backend 的抽象和 High Availability Service 的抽象允許生態開發者對接其他能夠提供相應能力的存儲系統。例如,被某公司高管認為難以擴展生態的數據庫領域,PostgreSQL 通過 Foreign Data Wrapper 和 Extension 等一系列插件化模塊,激發了生態開發者極大的開發熱情。又例如,Spring 這樣一個提供了基礎的控制反轉和麵向切面編程的方法論的軟件,通過對接不同數據源,不同鑑權服務,不同部署環境,形成了龐大的 Java 開發生態。

Apache Flink 的開源生態

開發文檔要為生態開發者解決的問題,就是明確這些框架接口的定義和約定,讓他們能夠放心地依賴並創造出新的價值,構建出生態護城河。此外,開發文檔網站可以羅列已有的生態開發項目,一方面能夠激勵生態開發者 “名留青史”,另一方面對於新人來說,有一個天然的不用刻意編寫的參考教程,即使是經驗豐富的生態開發者,也有可能從其他人的作品當中汲取靈感。

Apache SkyWalking 的開源生態

內核開發者指的是開發文檔所屬的開源軟件的人。如果軟件範疇小,那麼它可能代指的是所謂的核心團隊;如果軟件足夠複雜,那麼內核開發者可能分成好幾個團隊。例如 Rust 的內核開發團隊就分成編譯器團隊和標準庫團隊,而包管理器、資源網站開發和開發工具開發的團隊,則介於內核開發者和生態開發者之間。

對於內核開發者來說,僅僅了解軟件架構和公開的接口契約,就不太足夠了。生態項目的開發者,只要了解開源軟件的接口,開發的方式和風格很大程度上可以按照自己的喜好來決定,本質上是一個全新的開源項目。對於內核開發者來說,他們要開發的是一個已經存在的開源項目,因此項目的目標、設計哲學和風格,首先要入鄉隨俗,在經過深度的參與之後,才有可能提出合理的修改意見。

內核開發者核心的開發文檔是介紹如何參與的 CONTRIBUTING.md 文件,或者進一步展開的 Dev Guide 文檔。許多著名的開源項目都有類似的材料。

其中 TiDB 的開發文檔是我在參與 TiDB 社群運行的時候提出了推動撰寫的。此前 TiDB 有的是一系列源碼閱讀文章和博客分享。這些材料固然是有價值的,也是 TiDB 社群在當時相對早期的國內開源環境當中脫穎而出的依仗,但是開源運動發展到今天,當社群不再局限於一地,而是參與全球化競爭的時候,將發布後即不可變的零散材料,按照主題整理成可操作性的文檔,就顯得更加迫切了。

開發文檔需要覆蓋的內容,以 TiDB Development Guide 為例,分成了以下四個章節。

  1. Get Started 搭建開發環境,介紹完成基本開發流程的必需知識。
  2. Contribute to TiDB 開源社群歡迎哪些參與,這些參與方式分別如何進行。
  3. Understand TiDB 深入了解軟件架構設計、模塊設計和關鍵實現細節。
  4. Project Management 開源軟件的項目管理和軟件工程最佳實踐。

其他的開發文檔大同小異。例如 Rustc 的開發文檔主要討論了前三個問題,把項目管理的部分放到整體討論 Rust 社群運作方式的 Rust Forge  文檔裡。例如 Python 的開發文檔的順序是 Getting Started 隨後是各類參與形式的細節,最後以模塊設計和開發 Tips 收尾。

構建並運行一個內核開發者社群,通常的知識流通方向就是從公開的官方交流渠道上積累,匯聚沉澱到開發文檔上,再反哺到每日的溝通討論當中,逐漸形成豐富的知識庫財產,這是開源協同創造知識,並依托群體智慧製造高水平軟件的秘密所在。

國際化和本地化

很長一段時間裡,美國代表了軟件開發的前沿方向,開源運動盛行於歐美,並以英文為通用語言。這一狀況至今沒有太大的變化,但是中國和日本等國家的強勢加入,法國、德國和意大利等國家的內容本地化需求成長,使得開源軟件的內容創作必須要考慮國際化和本地化的問題。

一方面,技術寫作者以本地語言創作,往往能夠最為準確的表意,並且滿足直接受眾需求。但是為了擴大內容的影響力,融入全球化前沿的開源共同體當中,也為了在內容創作上堅持國際化和本地化兩手都要硬的需求,需要將內容翻譯成英語或關鍵受眾所在地區的本地語言。另一方面,對於第一手材料是外語的情況,開源社群的技術佈道師為了將內容國際化和本地化,也需要進行相應的翻譯工作。

內容翻譯是個複雜的話題,本文不會深究如何翻譯的問題,僅從現有的案例出發,介紹開源軟件內容國際化和本地化的成熟做法。

首先要考慮的是展示問題。如同上面討論文檔交付和展示方式時提到的,當今開源軟件的文檔,往往是以網站形式展示的。為了順應國際化和本地化需求的潮流,新興的文檔網站框架往往內置支持了多語言切換和發布的功能。

例如 Facebook 某團隊基於 React 框架提出的 Docusaurus 網站框架,就支持切換多語言的功能。Apache InLong (Incubating) 和 Apache APISIX 等採用這一框架來開發自己文檔網站的開源項目,也就因此能夠順利的支持國際化和本地化的需求。

Docusaurus 的多語言功能

除去展示階段的趨勢,另一個問題是內容翻譯的專家如何參與進來。上面提到的 Docusaurus 框架,或者許多手工完成國際化的文檔頁面,往往採用一個頁面寫兩次的手段,依靠人來維持不同版本之間的同步。這樣很容易導致文檔之間及時性不足不說,對於內容翻譯者來說,他們更想關注的是內容的翻譯,而非頁面方式用於描述如何渲染和其他網站相關的元素。

GNU gettext  項目提供了一種方案,能夠提取出文件中的片段,翻譯者只需要翻譯相關片段的內容,通過成熟的套件支持,能夠把原來文件當中的內容部分替換成翻譯後的內容。

Python 的用戶文檔多語言支持做得是公認的好,其背後就是這樣一套體系在支撐。具體的內容可以參考 PyCon Taiwan 2016 的演講 《多語系 Sphinx 與 Python 官方文件中文化》,這也是我最初接觸文檔國際化和本地化的重要材料之一。

Python 官方文件中文化

工具之外,開源共同體當中自發組成的內容翻譯團隊的力量也不容小覷。上面提到的 Python 官方文檔的翻譯,就是一個自發運行的小組。另一個頗有名氣的翻譯組,是 Linux 中國的翻譯組。他們翻譯了大量 Linux 社群的高質量文章,並且推進了許多實用工具文檔的中文化,是一個很有行動力的組織。

書籍文章

按照距離開源軟件生產中心的距離,文字內容創作依次分類成代碼註釋、提交信息和文檔,再往下走就是本節要介紹的文章和書籍了。

例如,這篇文章就可以視作開源共同體當中討論技術寫作的重要性和必要性的內容輸出。

我在 “夜天之書” 公眾號上發布的系列文章,大部分都關注在如何認識開源社群的人和事,如何參與開源社群,以及如何建設開源社群上。這些文章與 “開源之道”的系列文章,莊表偉的 Blog 上討論開源的文章,OpenTEKr 公眾號的系列內容,以及廣泛的關注開源、投入開源的參與者的文章一樣,構成了開源共同體當中的每一個個體對開源的解讀。

例如,前面提到的 TiDB 社群發布的每週速遞、功能解讀、源碼閱讀和路線展望等內容,就是具體到某個開源項目對自己的開發過程及結果的介紹和宣傳。

這其中,自然也包括 TiDB 首席架構師 @siddontang  在簡書上發布的博客,核心開發者 @tiancaiamao  的個人博客等等。

技術博客文章的價值在哪?回答這個問題之前,我想先拋出一個論點。

文章須言之有物。

這個觀點來自於胡適《文學改良芻議》的第一條。為什麼講這句話?因為技術博客及文章,其價值體現首先依賴於內容言之有物。

例如,上述個人博客的內容與社群的每週速遞類似,大多抓住的當前開發過程當中遇到的問題,並針對問題提出務實且有建設性的議論。作者寫下這些文字的時候,首先考慮的是對自己的思路整理有幫助,首先內容需要對自己有價值,進而才有可能讓讀者從中獲益。只有言之有物的內容,才有可能引來同行的評論和碰撞。

例如,前不久登上 Hacker News 首頁的 Retool 團隊升級 4TB PostgreSQL 的經驗一貼,就引來了數十條評論。@tiancaiamao 在自己博客當中討論到具體問題的時候,我自己和其他讀者都曾經回复討論過這些問題的解法和自己的經驗。

技術博客文章的價值在哪?我認為第一點是自己想寫,想記錄,滿足自己整理思路和外掛記憶的需求,再有第二點是內容言之有物,與同行切磋碰撞。

開源精神的重要內涵是分享的精神,寫作文章就是向開源共同體分享自己的所見與所思。開源協同的本質是共同創造價值,通過文章輸出自己的觀點,把別人不知道的事情講給人聽,把別人隱隱約約知道的事情講清楚,挑明問題,提出解法,為開源共同體創造價值,最後,自己和文章所依託的開源社群收穫真知灼見與技術影響力,這是開源社群的內容創作的閉環。

為什麼要強調言之有物呢?這是因為內容渠道一旦建立,推送內容的壓力立刻就會來到運營者身上。如果運營者本身不是內容的創作者,為了保證內容推送的密度,很容易飢不擇食降低標準推送一些無關的內容或者低質量的內容。

例如,我曾經多次和 Databend 團隊的成員提過,他們在公眾號上直接複製發布英文寫成的 Weekly 是不能達到正向運營的效果的。因為微信公眾號的受眾天然是中文受眾,由於人力緊張或者其他原因,直接將英文寫成的 Weekly 原封不動地推送出來,除了製造垃圾以外,很難想像有什麼價值。最近,Databend 公眾號在推送此類消息時,就做了基本的翻譯工作,以及除了無情報幕以外,增添了部分 Tips 內容。

不過,其實 Weekly 並不需要將所有內容都重複一遍,我在 TiDB 社群和 Flink 社群寫 Weekly 的時候,主要參考的是 Perl 6 當時的 Weekly 和 Flink 的英文 Weekly 的選材方式,以一個開發者的角度看我自己會關心會感興趣的內容,挑選出來以後略加評論並說明這個改動或者新功能、模塊的發布,可以怎麼用,還能怎麼改進。否則,只是簡單的說 “主分支進了 X 個提交”,分別是什麼提交號、標題是啥,真成了報幕的,信息價值就很低了。

要想改善內容輸出的頻率和質量,培訓和引導是必要的。例如,PingCAP 為了提高員工的技術寫作水平,優化 TiDB 社群內容的質量,在公司內舉行了多個技術寫作培訓計劃。例如,Google 發布了自家關於技術寫作的材料,這份材料本身就是其內容影響力矩陣的一部分。

一個好的例子是 Bytebase 團隊,他們圍繞開源軟件 Bytebase 關注的數據庫運維領域,輸出了一系列相關技術文章,同時也包括團隊的文化和運行管理方式。這很大程度上是由於創始人重視內容創作,並且以身作則示範好的內容應該如何生產的緣故。

博客文章畢竟是一種比較口語化的內容輸出形式,並且受限於文章篇幅,往往不能夠完整地討論一個問題。通常,博客文章的作用局限於對知識思路進行整理時的階段性輸出,或者即時地議論時事。如果相關內容在你的腦海中有比較完整的脈絡,或者有具體的結論,首先可以寫一篇文章再做一輪輸出,然後就是把相關文章作為原材料,二次創作形成文檔、論文或者書籍了。

前面提到,內核開發者社群的內容飛輪,是溝通渠道和開發文檔共同支撐的。溝通渠道產生原始知識,總結沉澱形成開發文檔,文檔再作為可引用的對象參與溝通,相互促進。其實把博客文章認為是一種作者對讀者有輸出優勢的溝通渠道,這個論斷仍然是成立的。例如,TiDB Development Guide 的內核技術部分,很大程度上來源於此前發布的源碼閱讀系列。例如,我正在撰寫的 《開源指南》文檔,內容也會參考此前寫作的與開源相關的博客。

論文的形式相對博客文章更加正式,並且經過同行評審後才會在相關期刊會議上發出。分佈式系統的明星博主 Martin Kleppmann  就實踐過這種做法。

書籍相對於博客文章來說,容量更加寬裕。開源軟件到達一定的流行程度以後,大多會發行相關的書籍來系統性的介紹自己的設計和使用場景,大幅度的提升自己的技術影響力。《Redis 使用手冊》、《HBase 原理與實踐》以及各種 “權威指南”,均屬於此類。

寫作之外

寫作之外的內容不是本文的重點,因此只做簡單的介紹。

隨著時代的發展,多媒體內容逐漸佔據了內容市場的重要比例。除去撰寫文章、書籍和文檔,以及開發過程當中涉及的技術寫作內容以外,在內容創作這個大門類下面,還有其他的重要形式。

例如,演講是近年來線上線下社群活動的重要組成部分。通過 KOL 圍繞主題並提供示例的演講,往往能夠在聽眾當中形成一個強有力的印象。KOL 本身很多時候也需要通過演講來建立起自己的影響力。可以說,演講能力是一個內容創作者必須掌握的關鍵能力。

例如,越來越多的開源社群在 Bilibili 和 Youtube 等視頻網站上開設自己的賬號並上傳視頻和短視頻內容。這可以理解成線上演講的一部分,也包括線上課程和功能展示等等。目前視覺化地學習 Flink 和 Pulsar 最好的資源,就是它們在 Bilibili 上發布的視頻內容。

例如,播客作為視頻和文字之間的折衷,也越來越得到開源社群的青睞。ALC Beijing  和 CHAOSS China  這樣的社群,會通過播客的方式邀請專業嘉賓訪談來輸出自己的內容觀點。

可以看到,開源軟件的技術寫作,到開源軟件的內容創作,是一個內涵極其豐富的領域。即使最貼近軟件開發的註釋和提交信息的部分可以結合到軟件工程實踐當中由開發人員完成,但是針對受眾群體特徵的文檔的寫作,內容的國際化與本地化,文章與書籍的技術寫作技巧,內容生產之後運營和推廣的能力,與開發一個軟件所需掌握的技術能力是有很大區別的。

當然,我不會說一個人只能同時掌握這些能力當中的一個,我也見過許多開發人員有動力、有能力並最終通過努力成為高水平的內容創作者。但是,作為關注開源項目發展的決策者,作為需要認識到開源社群如何建設的每一個人,將這一過程類比為一個新興的創業項目,要好過想像成一個開發者團隊能夠覆蓋方方面面的工程項目。

實際上,我們尚未看到有任何一個創業公司,能夠達到 Linux 這樣的成就。同時,Linux 的協同方式與傳統的公司運作方式有著許多不同。清醒客觀地認識到開源社群建設與發展的複雜性和創新性,評估和應對其中包括軟件開發、項目管理、內容創作、市場營銷乃至資金支持的風險和相應的收益,才是應有的審慎的態度。

免責聲明:作為區塊鏈信息平台,本站所發布文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。本文內容僅用於信息分享,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。