README 寫法

基本的 README 組成

  • 一句話解釋模組的目的
  • 簡潔可運行的範例
  • 詳細的API文件
  • 安裝說明
  • 注意事項和限制
  • 授權條款
  • 必要的背景資料或連結
  • 專業術語的資訊

簡介

README 的目的顯而易見:這是進行下一步之前的重要資訊

README 是寫給模組建立者的。一個沒有文件的模組,往往時隔 6 個月後,就連作者自己都會覺得陌生。

README 也是寫給模組使用者的。每個模組的作者同時也是該模組的使用者。Node 有一個非常健康的依賴關聯度:沒人會處在依賴樹的底部。

了解作品的入口

README 是使用者首先(或唯一)審視你作品的入口。
編寫優秀的文件可以讓使用者不用閱讀原始碼就能理解你模組的精妙之處。
沒有 README 意味著開發者需要閱讀原始碼才能理解你的模組。
使用者希望模組能滿足他們的需要,所以你要清楚的說明你的模組的主要作用和優勢。

只要你的文件是完備的,使用者就可以直接使用你的模組而無需去閱讀原始碼。這是非常重要的。透過文件可以在很大程度上將你的模組的外部介面和內部實現進行分離。這樣就可以在保持介面不變的情況下,靈活的修改內部實現。
記住: 對模組進行定義的是文件而不是程式碼。
——Ken Williams

目標

讓讀者了解

  1. 這是什麼
  2. 使用情境
  3. 如何使用
  4. 實作及相關細節

原則

簡潔

理想的 README 應該儘可能的短。詳細的文件可以在單獨的頁面裡描述

快速理解

  • 這些關鍵要素的排序應該讓人儘快放棄你的模組
  • 當你用利他主義思想來做的時候,不是為了銷售給別人,而是為了讓人們儘可能客觀公正的評估你的作品,並判斷是否滿足他們的需要。而不是讓你的下載量和使用者數最大化

方法

common-readme

common-readme用的文件格式,一個README寫作指南和方便的command-line生成器。
你也可以在標準Readme中領略下更具結構化的通用Readme格式。

以史為鑑

古人云:以史為鑑,可以知興替。
開發者編寫文件已經有多年的歷史了。值得我們花時間去看看在 Node 之前人們是怎麼正確寫文件的。

順序:以使用者的角度

當我想要一個 2D 碰撞檢測模組時我找到了collide-2d-aabb-aabb
我開始從頭開始檢查這個模組:

  1. 取名:名字要能做到“其義自見”。collide-2d-aabb-aabb 聽起來是個不錯的匹配,儘管它假設我知道”aabb”是什麼意思。如果名字含義非常模糊或與我要找的沒什麼關係,我就會繼續查詢其它的模組了。
  2. 簡介:透過一句話簡明扼要的說明了這個模組是做什麼的。
    collide-2d-aabb-aabb 的描述是:

    Determines whether a moving axis-aligned bounding box (AABB) collides with
    other AABBs.
    太棒了——描述了 AABB 的定義是什麼,並且說明了這個模組是做什麼的。現在開始評測它是否適合我的程式碼:

  3. 用法:在開始探究 API 文件之前,最好看看這個模組在實際應用中是什麼樣子。我可以快速決定用JS寫的示例程式是否符合我的程式碼樣式和我要解決的問題。人們會在很多問題上意見相左,比如 promises/callbacks 和 ES6。如果符合我的要求,我會進一步去研究細節。
  4. API:模組的名字,描述和使用方法都符合我的胃口。在這一點上我很樂意使用這個模組。我需要瀏覽API來確定這就是我需要的,並且很容易整合到我的程式碼中。API 部分應該詳述模組的物件和函式,以及它們的簽名,返回值,回撥和事件。當型別不是特別明顯的時候,也無需進行描述。注意事項要描述清楚。
  5. 安裝:當我讀到這兒的時候我就要開始試用這個模組了。 如果不是通用的安裝說明,就需要在這兒進行描述。即使是一句簡單的npm install也好。 對於使用Node的新使用者來說,放一個指向npmjs.org的連結和安裝命令,可以讓使用者快速上手使用模組。
  6. 授權:大多數模組把這個放在最末尾,但是最好還是往前放一些;非常有可能在把這個模組整合完後才發現授權協議不合適。我通常使用 MIT/BSD/X11/ISC。如果你的協議不是很寬容,最好是放到最前面。

順序:認知漏斗

可以想象成是一個直立的漏斗,最寬的部分相關細節最寬泛,越往下移動細節越具體,只有對你的作品足夠感興趣的人才會關注這部分內容。最後,底部可以放一些作品背景的細節 (background,credits,biblio,…)

Perl模組的文件對於細節的描述是從少到多的。
你的簡介部分應該包含一個小的例子程式
(或許只有一行程式碼,省略掉不常用的用例或大多數使用者用不到的功能)
描述部分應該從總體上描述你的模組,
通常只需要幾個段落;在隨後的章節中再詳細描述模組的例程或方法,長的程式碼示例,或其它的資料。
理想情況下,在點“下一頁”之前就能讓人大體上了解你的模組。
隨著使用者繼續閱讀文件,他們能夠漸進的獲得更多的知識。
—— perlmodstyle

實作

API改的越多,越要努力的去更新文件

動機

考慮包涵一個 背景 部分 (background),如果你的模組依賴於重要但是不為人所熟知的抽象或生態系統。bisecting-between的函式從它的名字上看不是特別明顯,所以在 背景 部分會描述定義,並且給出具體概念和抽象的連結,以便需要的人去使用和獲取。如果已經有相似的模組在npm上存在了,這兒也是一個非常適合描述建立模組的動機的地方

連結

如果你談及其它的模組,想法,或者其他人的時候,在相關的引用內容上加上連結,這樣訪客就可以很容易的得到你的模組背後的想法。極少有模組是憑空誕生的:所有的作品來源於其它作品,因此很有必要讓使用者追溯你的模組的歷史和靈感

範例檔案

用法 部分包含的示例程式碼,要在repo中以檔案的形式體現 – 例如example.js。這樣當用戶clone專案後,就可以直接執行README中提及的程式碼

徽章

使用徽章要慎重。經常會被濫用。它們會容易引起爭論。它們在你的README中加入了視覺噪聲,並且只有當用戶在聯網的瀏覽器裡閱讀你的markdown時才能看到徽章,因為圖片是存放在網際網路上的其它地方。對於每一個徽章,需要考慮:README中的徽章提供給典型讀者的真實含義是什麼?用一個CI徽章來顯示build/test狀態?這個訊號更應該發郵件給維護者,或者自動建立一個issue – 永遠要考慮你的README中的資料的受眾並且自問一下是否有一個流程能夠讓資料更好的送達到目標受眾。

API

API 文件格式沒有侷限。使用任何你認為是清晰的格式,但是要包含重要的細節:
a. 引數是否可選,以及預設值
b. 包含型別資訊,如果型別不能清楚的根據約定進行體現
c. 對於 opts 物件引數,描述它所接受的所有的 keys 和 values
d. 為每個API提供一個小的呼叫示例,如果它們的用法不明顯或是在 用法 部分沒有體現。
不過,也有可能是函式太複雜了,需要進行重構,劃分成更細粒度的函式,或者整體刪除。
e. 為特殊術語建立連結! 在markdown中你可以把腳註 放在文件的末尾,可以很方便的多次引用它們。這兒有一些我的API文件格式的個人偏好。

  • 放一些呼叫和返回值的示例可能比執行一個示例檔案更清晰
    • 如果你的模組提供了 CLI (command line interface)而不是 API,用命令呼叫的方式展示呼叫示例和輸出。如果你建立了或更改了一個檔案,cat 它來展示更改前後的變化。

關鍵字

github 和 npm 皆有提供手動填寫關鍵字

內嵌圖片

最後,請記住你的程式碼倉庫和其中的README存在的時間要比你的程式碼倉庫託管主機和你連結到的其它任何東西–特別是圖片–的時間都要長久。所以內嵌任何對將來要獲取你的作品的使用者來說是重要的東西。

範例

  • https://github.com/noffle/ice-box
  • https://github.com/substack/quote-stream
  • https://github.com/feross/bittorrent-dht
  • https://github.com/mikolalysenko/box-intersect
  • https://github.com/freeman-lab/pixel-grid
  • https://github.com/mafintosh/torrent-stream
  • https://github.com/pull-stream/pull-stream
  • https://github.com/substack/tape
  • https://github.com/yoshuawuyts/vmd

參考資料

  • art-of-readme

歡迎關注我的其它發布渠道