讓自己更快融入開源專案的小技巧 - 談溝通 Pull Request

讓自己更快融入開放原始碼專案的小技巧

本文聚焦在程式碼貢獻者的部份,不過「文化」類的原則應該也適用其他角色參與者,例如「溝通風格」。

讓對方輕鬆地理解你想幹麻

「怎麼讓對方輕鬆地理解你想幹麻」,是整個融入技巧的核心概念。

所有下述的手段,都以滿足這個核心概念為目標。因此只要目標能夠被滿足,就不需要拘泥於是否實踐了每個下述的手段。

「怎麼讓對方了解你想幹麻」這件事情的門檻,可以從「會消耗對方多少資源」這個觀點著手;而資源可分成主觀與客觀。

主觀的資源,像是會消耗多少心力、耗腦力多寡與否。例如對方理解你給予的資訊時,這些資訊是不是對於對方而言很難理解、需要額外聯想或是深思,才能夠理解你想表達什麼。我這段話大概就有點令人難以一眼理解;這是我自己表達的老毛病。

客觀的資源,像是時間多寡。例如對方願意花多少時間理解你給予的資訊。主觀與客觀資源多寡則會互相影響。

單方面可以完成的事情

更動規模小

Review Please
https://www.reddit.com/r/ProgrammerHumor/comments/oat1m3/review_please/

更動規模小,例如幾個原則,如果可以的話:

簡短且具體的描述

I didn't have time to write a short letter, so I wrote a long one instead.

-- Mark Twain

撰寫簡單扼要的 pull request 與 patch 的描述,比冗長的描述往往還要不容易;就像是 Mark Twain 描寫人們撰寫信件時的心態一樣。單純地將內心想法如流水般,想到什麼就寫下什麼,往往比將文字描述重點精鍊更容易執行,只是更冗長。

只不過, 冗長的描述,往往在各種開源專案中,會堆高主觀與客觀認知門檻。許多開源專案的貢獻者又是業餘時間進行開發維護,過高的認知門檻則容易導致雙方直接放棄交流。所以簡短且具體的描述可以說是必要且值得學習的風格。

簡短的描述不是什麼:

簡短的描述是什麼:

具體的描述,就是盡可能地,使描述的方式能夠讓對方可以用他手上既有資源,就能重現場景、蒐集到相關資訊的手段。其次是至少是用對方曾經有過得體驗,例如看過、用過等等,來描述。

Pull Request 描述著重在 Why

一個幾乎已經是約定成俗的風格慣例,是說明著重在「 Why :為什麼我要做這個變動」,其次是「 What :改了什麼」。因為程式碼變動本身已經說明了「 How :如何改」。

如果可以,最好還附上自己如何驗證這個 pull request 。

整理 Commit History

提交記錄( commit history )不僅僅只是開發過程的記錄,它還可以向讀程式碼的人說故事:我是怎麼把程式碼捏成我要的形狀的。所以整理提交記錄的原則,跟說一個好故事類似;甚至可以讓閱讀者,能夠像是讀小說一樣一樣,流暢地不斷往前推薦:

提交記錄(故事)如果要盡量地呈現線性發展,另外還可以從「時常合併主要分支」一起著手。只是「時常合併主要分支」這個原則牽涉更為廣泛,像是事前的分工與程式碼架構,無可避免地會與是否容易造成 code conflict 直接相關。

[1] [llvm-dev] [Github] RFC: linear history vs merge commits
[2] [llvm-dev] [GitHub] RFC: Enforcing no merge commit policy

Commit 風格

類似上述 pull request 的風格;更多風格上的建議,像是段落、長短等等,則是可以從各大專案中找到前例,像是:

需要雙方互相配合才能夠完成的事情

溝通風格

每個專案都是自成一個組織度或強或弱的社群,可以考慮觀察與理解這個社群習慣與接受的溝通風格開始著手。幾個觀察重點像是:

這類風格往往各有利弊,就只是一種風格屬性而已,並不一定存在標準答案。也有很多社群中,底下的小社群有不一樣的風格與文化。

例如 Debian 社群既重視個人產出、同時也存在一群人願意進行師徒風格方式進行合作。如果社群懷疑貢獻不夠穩定或有品質時,當事人要參與一定強度以上的活動,則很容易受挑戰[1];但對於每個有心要協助打包 orphan package 的人,卻也提供 mentor 的角色[2]。

有一些是(我主觀上)稍微比較被公認為通常利大於弊的風格而被廣泛採納與鼓勵,則列舉如下,像是非同步、 over-communication 。

[1] 當事人在釐清貢獻之後似乎就被社群接受 https://lists.debian.org/debian-python/2021/12/msg00021.html
[2] https://lists.debian.org/debian-mentors/

非同步溝通

非同步溝通風格受歡迎,是因為在軟體開發上,對一段時間的專注力需求,能夠普遍被理解與接受。非同步溝通的手段中,本質上都是類似 email 的角色(這好像是受限於人類天生的溝通介面限制?)。所以即使在各種通訊平台流行的今日,老牌的開源社群總還是有著 mailing list (或至少類似 mailing list 的機制)在。

非同步溝通往往也透露一種價值觀:尊重其他人的時間。思維上能夠接受與理解別人不一定有責任或義務即時回覆自己的問題、提案與需求。

Over Communication

社群相對鬆散下,基本上很難互相掌握彼此對專案的了解、進而有效率地參與協調。如果能夠適當搭配成熟的非同步溝通文化,Over-communication 就可以相對容易作到;例如在不同的地方剪下貼上對同一件事情的看法與資訊。

第一次介入的貢獻類型建議

剛開始接觸該專案時,如果該專案社群存在 mentor ,直接請教對方是不是存在 "good first issue";有些專案也都會在 github issue 上面明確標示這類 issue。

如果沒有這類資源時,可考慮從文件與測試開始著手。

文件

README 的 pull request 或許是最容易被收的。因為第一相對容易 review 、對 reviewer 耗費的心力而言較為友善,第二即使 merge 了也對程式本身短期內傷害不大。

改善文件往往也對剛開始接觸專案的自己有幫助;我們大概總是需要將架設環境的過程中各種細節,筆記在某個地方。既然總是要筆記,不如筆記在更多人看得到的地方,協助比自己更晚接觸專案者,繞掉一些不必要的嘗試。

對文件做貢獻也是一種對專案的隱性承諾:以行動宣示「我願意貢獻」。是在初期建議合作信任時,很好的潤滑劑與催化劑。

測試,特別是跑在 CI 中的測試

單元測試往往夠小,並且總是暗示著某段程式的進入點。所以是一開始在茫茫程式海中,不知道從哪裡開始時的一個選擇。或許不是最好的選擇,但大概都不會太差。

如果是被放進 CI 中的測試,則又另外保證了架設測試的可靠性:至少他會動。可以說是一份活生生的文件。另外這類測試,多少還隱喻了「這些功能足夠關鍵到專案願意監控他們」,所以也可以說是暗示了專案中的核心功能與主要功能、也就是最有「價值」的部份是哪些。

最理想的情況,例如能夠有對專案熟悉者,願意告訴你有哪些功能與對應的測試單元,這往往可以使得自己很快進入狀況而貢獻。從各種 hackthon 與 sprint ,挑選那些體質良好的專案或 sprint project leader ,是一些有這類機會的場合[1]。

如果沒有 CI 或是測試的專案呢?跳坑之前或許要評估一下是不是一個正在起步的專案。

如果不是一個剛起步的專案,但又沒有 CI 和任何一丁點測試的專案呢?這或許是運用自己的智慧想一下是不是值得花時間參與的時刻了。

[1] https://github.com/RustPython/RustPython/pull/3473