如何在 Github 上做一個規範的開源項目?

很多人 Github 當成一個代碼倉庫,需要代碼就到上面去搜索,但是很多項目都是扔上去就再也不管了,也沒有文檔,很不利於別人使用。

而我理解的開源項目應該是要對他人有用的,且易於使用的。

那麼一個優秀的開源項目應該有哪些特性?

如何規範開源項目?

開源者應該如何維護開源項目?

還望各位不吝賜教,謝謝!


輪子哥也回答了這個問題,讓我倍感壓力。但還是硬著頭皮把我自己維護了一兩年(放到Github上才兩三個月,以前是在自己的Git伺服器上)的自用爬蟲框架拿出來,並說說自己對開源項目的理解。PS:最近有了其他contributors。

爬蟲框架的Github地址:xianhu/PSpider,最近剛剛補充了英文文檔說明(寫起來那個痛苦呀)。

寫這個框架的初衷有這麼幾個:

1. 學習Python基礎,學習Python進階用法,比如裝飾器、元類、非同步IO、多線程數據同步等。

2. 不喜歡用輪子,更喜歡造輪子,因為可以自己很方便的擴展、修改框架。

3. 寫爬蟲框架的過程,能更好的理解爬蟲框架的內部原理、數據流程等,而不是僅僅會用。

下面回答下題主提問的幾個問題:

一個優秀的開源項目應該有哪些特性?

很明顯我的開源項目不優秀,但我看過一些其他的優秀的開源項目,比如aiohttp,tushare等。個人認為一個優秀的爬蟲框架應該包含如下特性:

(1)開源項目完成的功能很明確,且有完整的說明文檔。小的、簡單的開源項目,最好還能講解一下項目架構,代碼結構等。

(2)開源項目的代碼結構清晰,代碼抽象合理,文件名、變數名等命名合理易讀。某一語言的項目最好遵循該語言的代碼規範,比如Python的PEP 8或者GooglePythonStyleGuide,或者利用pylint等第三方檢查庫進行項目檢查。

(3)開源項目的功能要具有通用性,比如各平台通用、各語言版本通用、各業務情形通用。這點要求就比較高,可能需要大量的測試人員去不斷debug。

(4)有持續的貢獻者,有持續的更新,有人對其負責。在Github上找開源項目時,如果最後更新日期在一兩年前,我一般不會使用。

很明顯,我的開源項目只符合30%到50%左右,哎,道路漫長。

如何規範開源項目?

開源項目的重點在於開源兩字,如何規範確實比較頭疼。據我了解,Hadoop的每次分支合併,都會有上千人進行評估,且評估者涉及各行各業各個職位(不知道是真是假)。當然Hadoop那種級別的開源項目另當別論,當開源項目不是那麼龐大時,可能相對來說簡單一點。

規範開源項目有兩個方面需要考慮:

(1)對於開源者本身來說,需要規範代碼結構,規範文件名、變數名、函數名、類名等等,不能隨隨便便更改介面,要做到向下兼容,特別是當你的項目被別人使用時。(說起來容易,做起來還是挺難的)

(2)當你的開源項目被別人fork且提交了合併請求時,作為開源者,應該去檢查這次commit的合理性、規範性、通用性等,因為你最了解你的項目。比如檢查文件、變數命名是否合理,考慮的情況是否全面,合併後是否對於其他模塊產生影響等等。由於提交合併的開發者水平不一、風格不一、考慮問題的角度也不一樣,如果隨隨便便就去合併每一個人的提交,很容易造成開源項目混亂。當然,當你拒絕一個提交時,最好給出一個合理的解釋,以免對提交者產生壞的影響。

開源者應該如何維護開源項目?

(1)規範、規範、規範。這點很重要,對開源者和貢獻者都要求很高。

(2)如果條件允許,最好和所有貢獻者建立討論小組,每周或每月組織討論,共同維護。

(3)要宣傳自己的項目,不要怕被鄙視,要讓更多的人使用。只有這樣才能發現項目的問題,以及項目所需要進一步開發的功能等。


規範的Web前端開源項目需要

  1. 版本管理:每個版本的發布必須有 releases 且遵循 語義化版本 2.0.0
  2. 發布:將構建後的代碼發布到 npm 或者 dist/ 文件夾下存放UMD規範代碼
  3. 使用示例:示例可以放在 /example 目錄下
  4. 文檔: 盡量放在 /doc 目錄下,文檔應給出組件/庫的最佳實踐
  5. 單元測試: 可以放在 /test 目錄下

https://travis-ci.org/ 是個好幫手


絕大多數有生命力的開源項目,都是因為開發人員有工資。少數靠個人威望撐起來。更少的才是因為個人的興趣還沒有熄滅。

所以最容易的方法就是發錢。


有文檔和簡單用例 (這也是功能的展示)。
寫清楚在這個項目要解決的問題,特點,和其他同類項目的比較 (如果可以比較)。

連到CI,加上編譯通過的badge,寫測試然後加一個測試全綠的badge。

如果是庫,也發布到包管理器一份。如果是獨立程序可以把新版本發到github release。


1可以掛上一些持續集成。聊天室等等此類標誌

2寫好markdown。文檔。

3有一些語言有發布的一些規範。發布時也按照他的要求發布


從13年開始使用github,14年陸續在上面開源了一些項目,同時也瀏覽了非常多項目的源碼及構建方案。以下是我覺得一個規範的開源項目必須所具備的:

1、項目結構與代碼規範(如php的psr規範等)

2、使用主流的包管理器,讓你的項目可以非常容易的與其他項目合併

3、嚴格的單元測試及持續集成;是否有單元測試是一個項目是否靠譜的重要評估標準,單元測試的覆蓋度,也能夠說明項目是否嚴謹;持續集成功能能夠讓用戶直觀的看到項目質量。醬紫用戶才會放心使用

4、要有大致的ROADMAP,開源項目是給別人用的,嚴格線路規劃能夠避免項目的變化,對用戶更友好

5、版本控制,語義化版本 2.0.0

6、完善的examples,讓用戶快速學習項目的使用方法

7、完善的文檔(英文),如果有精力可以同時維護英文、中文兩份文檔

8、README.MD中需要添加travis-ci等tag圖標

9、如有精力可以搭建項目官網

我的項目:huyanping/simple-fork-php,這個項目是我覺得我做的最好的一個項目,雖然star不多,但文檔、demo完善,相對比較規範,容易上少


- 使用英文書寫 README.md 和 documentation 。

- 不把 .idea .swap 等文件加入到 Git 。

- 如果不是 markdown 或 awesome 工程師,標配 unit test 和 CI,選配其餘各種 badges 。

- 提供 Demo/example 。

- 提供 unix 系統下載和安裝的方法,但是不要提供 windows 的。

關於維護,幾乎沒有下載量的玩具庫自己有心就反覆改改好了,畢竟 issue 和 pull request 偶爾跳出來一個都能讓你高興半天,而 star 更是去各種論壇上刷那麼幾次或者認識的人點出來的,他們是支持者,不是用戶。

如果真的是好東西,需求量很大,那麼就會出現很多人會追問和鞭策你去更新它的,或者看你的 repo 扶不起來,就直接 fork 甚至重開一個去維護了。


這篇關於項目規範的文章,在我正在寫回復的時候已經有接近9000的star了,對一個規範的項目有非常好的指導意義。指導大家仔細閱讀。

wearehive/project-guidelines

項目規範 ·

a

javascript工程項目的一系列最佳實踐策略

每當開發一個新項目,就像在田裡打滾,對其他人來說維護這樣一個項目簡直就是一個潛在的噩夢。以下內容是我們在hive的大多數JavaScript項目中發現,撰寫和收集的最佳實踐列表(至少我們是這樣認為的)。如果您想分享其他最佳實踐,或者認為其中一些內容應該刪除。歡迎隨時與我們分享。.

  • Git
    • 一些git規則
    • Git workflow
    • 編寫良好的提交備註信息
  • 文檔
  • 環境
    • 一致的開發環境
    • 一致性的依賴配置
  • 依賴
  • 測試
  • 結構與命名規則
  • 代碼風格
  • 日誌
  • API
    • API 設計
    • API 安全
    • API 文檔
  • 許可

1. Git

a

1.1 一些Git規則

有一套規則要牢記:

  • 在需求分支中執行開發工作。

為什麼:

因為這樣,所有的工作都是在專用的分支而不是在主分支上隔離完成的。它允許您提交多個pull請求而不會導致代碼衝突。您可以持續迭代提交,而不會污染那些很可能還不穩定而且還未完成代碼的主分支。更多請閱讀...

  • 從develop拉出分支。

為什麼:

這樣,您可以保持master中的代碼穩定性,這樣就不會導致構建問題,並且可以直接用於發版(當然,這可能對某些項目來說要求會比較高).

  • 在確保Pull請求之前,千萬不要push到 develop 或者 master 分支。

為什麼:

開發成員如果完成功能,需要馬上通知團隊。這樣開發夥伴就開源更容易對代碼進行評審,同時還可以互相討論所開發的需求功能

  • 在更新您本地的develop分支時,並在push和pull之前,先進行rebase操作。

為什麼:

Rebasing將合併到你正在操作的分支(master或develop)中,並將您本地進行的提交應用於所有歷史提交的最頂端,而不會去創建額外的merge提交(假設沒有衝突的話)。這樣可以保持一個漂亮而乾淨的歷史提交記錄。 更多請閱讀 ...

  • 請確保在pull rebase的時候解決完潛在的衝突。
  • merge後刪除本地和遠程需求分支。

為什麼:

如果不刪除需求分支,會導致大量殭屍分支存在,會很混亂。請確保一次性合併到 (master or develop)。只有當這個feature需求分支還處於開發中時才應該存在。

  • 在進行Pull請求之前,請確保您的需求分支已經建立,並已經通過了所有的測試(包括代碼規則檢查)。

為什麼:

您即將將代碼提交到這個穩定的分支。而如果您的需求分支功能測試都失敗了,那您的目標分支構建很可能也會失敗。此外,確保在進行pull請求之前應用代碼規則檢查。因為它有助於我們代碼的可讀性,並減少格式化的代碼與實際業務代碼更改混合在一起導致的混亂問題。

  • 使用 .gitignore 文件.

為什麼:

此文件包含一個文件列表描述,描述那些文件和代碼不會被發送到遠程git倉庫中。這個文件裡面應該添加那些為大多數IDE自己產生的文件和文件夾以及大多數常見的依賴文件夾和文件(比npm的node_modules),這些文件我們都不會上傳到遠程代碼庫,這些文件不是我們需要的。

  • 保護 develop 和 master 分支.

為什麼:

它保護您的生產分支免受意外情況和不可回退的變更. 更多請閱讀... Github and Bitbucket

1.2 Git workflow

因為以上原因, 我們使用 需求功能分支-workflow 並配合 Rebasing的使用方法 和 一些關於 Gitflow (命名和使用一個develop branch). 主要步驟如下:

  • 針對一個新項目, 在你的項目目錄初始化你的項目. 針對下級目錄 features/changes 這一步請忽略.

cd &<項目目錄&>

git init

  • Checkout 一個新的 feature/bug-fix 分支。

git checkout -b &<分支名稱&>

  • 新增一下代碼變更。

git add

git commit -a

為什麼:

git commit -a 這會啟動一個編輯器,編輯你的說明信息,這樣的好處是可以專註於寫這些注釋說明. 更多請閱讀 section 1.3.

  • 保持與遠程的同步,以便拿到最新變更。

git checkout develop

git pull

為什麼:

這其實是在rebasing的時候創造了一個解決衝突的時機,而不是創建通過包含衝突的Pull請求。

  • 通過使用rebase從develop拉取最新的代碼提交

git checkout &

git rebase -i --autosquash develop

為什麼:

您可以使用--autosquash將所有相同類型提交壓縮到單個提交。一般沒有人想在開發分支中提交一大堆相同功能的提交吧? 更多請閱讀...

  • 如果沒有衝突請跳過此步驟,如果你有衝突, 解決方式 就可以通過--continue參數繼續rebase

git add & & ...

git rebase --continue

  • Push你的分支. Rebase將會改變提交歷史, 所以你可以使用 -f 強制push到遠程分支. 如果其他人正在您的這個分支上面進行開發,請使用不那麼破壞性的 --force-with-lease.

git push -f

為什麼:

當你rebase時,你會改變需求功能分支的提交歷史。結果呢?Git卻拒絕了正常的「git push」。那麼,您只能使用-f或--force參數了。更多請閱讀...

  • 提交一個Pull Request.
  • Pull Request 會被負責代碼審查的同事接受,合併和關閉.
  • 如果你完成了開發,請記得刪除你的本地分支.

git branch -d &<分支&>

刪除所有已經不在遠程倉庫維護的分支

git fetch -p for branch in `git branch -vv | grep ": gone]" | awk "{print $1}"`; do git branch -D $branch; done

1.3 如何寫好提交說明

堅持遵循關於提交的標準指南,會讓在與他人合作使用Git時更容易。這裡有一些經驗法則 (source):

  • 將標題和文體用換行後的兩條空行分開

為什麼:

Git非常聰明,它可將您提交消息的第一行識別為摘要。實際上,如果你嘗試使用git shortlog,而不是git log,你會看到一個很長的提交消息列表,其中包含提交的id和摘要。

  • 將標題行限制為50個字元,並將文體控制在72個字元。

為什麼_

提交應儘可能簡潔明了,而不是寫一堆冗餘的描述。 更多請閱讀...

  • 大寫的標題線
  • 不要用句號結束標題句
  • 使用 imperative mood 在標題線

為什麼:

不是簡單的寫提交者這次做了什麼。最好寫明提交者將要進一步做什麼事情。更多請閱讀...

  • 使用文體去解釋 是什麼為什麼 而不是 怎麼做

2. 文檔

a

  • 使用這個 模板 給 README.md, 歡迎添加裡面沒有的內容。
  • 對於具有多個存儲庫的項目,請在各自的README.md文件中提供它們的鏈接。
  • 隨項目持續的更新 README.md.
  • 給你的代碼添加詳細的注釋,這樣就可以清楚每個主要部分的含義。
  • 如果您正在使用的某些代碼和方法,在github或stackoverflow上已經有公開討論,請在您的評論中包含這些鏈接,
  • 不要把注釋作為壞代碼的借口。保持你的代碼乾淨整潔。
  • 也不要把那些清晰的代碼作為不寫注釋的借口。
  • 當代碼更新,也請確保注釋的同步更新。

3. 環境

a

  • 如果需要,請分別定義 development, test 和 production 三個環境.

為什麼:

不同的環境可能需要不同的數據,token,API,埠等。您可能需要一個隔離的development環境,它調用mock的API,mock會返回我們需要的數據,使自動和手動測試變得更加容易。或者您可能只想在production 環境中才啟用Google Analytics(分析)。 更多請閱讀...

  • 從環境變數載入部署的相關配置,不要將這些配置作為常量添加到代碼庫中, 看這個例子.

為什麼:

你會有令牌,密碼和其他有價值的信息。這些配置應正確地從應用程序內部分離開來,這樣代碼庫就可以隨時獨立發布,不會包含這些敏感配置信息。

怎麼做:

使用.env文件來存儲環境變數,並將不提交到git倉庫的文件添加到.gitignore中。另外,再提交一個.env.example作為開發人員的參考配置。對於生產環境,您應該以標準化的方式設置環境變數。 更多請閱讀

  • 建議您在應用程序啟動之前校驗一下環境變數。 看這個例子 使用 joi 去校驗提供的值.

為什麼:

在排查問題的痛苦經歷中你一定需要他。

3.1 一致的開發環境:

  • 在package.json里的engines中設置你的node版本

為什麼:

讓其他人可以清晰的知道這個項目中用的什麼node版本 更多請閱讀...

  • 另外,使用nvm並在你的項目根目錄下創建一個.nvmrc文件。不要忘了在文檔中標註。

為什麼:

任何使用nvm的人都可以使用nvm use來切換到自己想要的node版本。 更多請閱讀...

  • 最好設置一個檢查node和npm版本的「preinstall」腳本

為什麼:

某些依賴項可能會在新版本的npm中安裝失敗。

  • 如果可以的話最好使用Docker image

為什麼:

它可以在整個工作流程中為您提供一致的環境。不用花太多的時間來解決依賴或配置。 更多請閱讀...

  • 使用本地模塊,而不是使用全局安裝的模塊

為什麼:

你不能指望你的同事在自己的全局環境都安裝了相應的模塊,本地模塊可以方便你分享你的工具。

3.2 依賴一致性:

  • 確保您的團隊成員獲得與您完全相同的依賴關係

為什麼:

因為您希望代碼在任何開發環境中運行都能像預期的一樣 更多請閱讀...

怎麼做:

在npm@5或者更高版本中使用 package-lock.json

我們沒有npm@5:

或者,您可以使用「yarn」,並確保在「README.md」中標註。您的鎖文件和package.json在每次依賴關係更新後應該具有相同的版本。更多請閱讀...

我不太喜歡 Yarn:

居然不喜歡Yarn,太糟糕了。對於舊版本的「npm,在安裝新的依賴關係時使用-save --save-exact,並在發布之前創建npm-shrinkwrap.json。 更多請閱讀...

4. 依賴

a

  • 持續跟蹤你當前的可用依賴包: e.g., npm ls --depth=0. 更多請閱讀...
  • 查看這些軟體包是否已經變得不可用或者已經廢棄: depcheck. 更多請閱讀...

為什麼:

您可能會在代碼中包含未使用的庫,這會增大生產包的大小。請搜索出這些未使用的依賴關係並擺脫它們吧。

  • 在使用依賴之前,請檢查他的下載統計信息,看看它是否被社區大量使用: npm-stat. 更多請閱讀...

為什麼:

更多的使用將意味著更多的貢獻者,這通常意味著擁有更好的維護,這些才能確保快速發現錯誤和快速修復錯誤。

  • 在使用依賴關係之前,請檢查它是否具有良好而成熟的版本發布頻率與大量的維護者:例如, npm view async. 更多請閱讀...

為什麼:

如果維護者沒有足夠快地merge修補程序,那麼這些貢獻者也將會變得不積極不高效。

  • 如果需要使用那些不太熟悉的依賴包,請在使用之前與團隊進行充分討論。始終確保您的應用程序在最新版本的依賴包上面能正常運行,而不是無法使用:npm outdated. 更多請閱讀...

為什麼:

依賴關係更新有時包含破壞性更改。當顯示需要更新時,請始終先查看其發行說明。並逐一的更新您的依賴項,如果出現任何問題,可以使故障排除更容易。這裡有一個很酷的工具,如 npm-check-updates.

  • 檢查包是否有已知的安全漏洞,例如: Snyk.

5. 測試

a

  • 如果需要,構建一個 test 環境.

為什麼:

雖然有時在production模式下端到端測試可能看起來已經足夠了,但有一些例外:比如您可能不想在生產環境下啟用數據分析功能,只能用測試數據來填充(污染)某人的儀錶板。另一個例子是,您的API可能在production中才具有速率限制,並在請求達到一定量級後會阻止您的測試請求。

  • 將測試文件放在使用* .test.js或* .spec.js命名約定的測試模塊,比如moduleName.spec.js

為什麼:

你肯定不想進入一個層次很深的文件夾結構來查找裡面的單元測試。更多請閱讀...

  • 將其他測試文件放入獨立的測試文件夾中以避免混淆。

為什麼:

一些測試文件與任何特定的文件實現沒有特別的關係。你只需將它放在最有可能被其他開發人員找到的文件夾中:__test__文件夾。這個名字:__test__也是現在的標準,被大多數JavaScript測試框架所接受。

  • 編寫可測試代碼,避免不良代碼,提取並寫成純函數 //UFO

為什麼:

您想要將業務邏輯拆分為為單獨的測試單元。您必須「盡量減少不可預測性和非確定性過程對代碼可靠性的影響」。 更多請閱讀...

純函數是一個函數,它總是為相同的輸入返回相同的輸出。相反,不純的函數是可能具有不可預測性或取決於來自外部的條件來決定產生對應的輸出值。這使得它不那麼可預測更多請閱讀...

  • 使用靜態類型檢查器

為什麼:

有時您可能需要一個靜態類型檢查器。它為您的代碼帶來一定程度的可靠性。更多請閱讀...

  • 先在本地develop分支運行測試,待測試通過後,再進行pull請求。

為什麼:

你不想成為一個導致生產分支構建失敗的人吧。在您的rebase之後運行測試,然後再將您的需求功能分支改動推送到遠程倉庫。

  • 記錄您的測試,包括在README.md文件中的相關部分說明。

為什麼:

這個記錄的筆記非常的方便,便於留給其他開發人員或DevOps專家及QA和任何幸運的人,讓他們更方便的來處理您的代碼。

6. 結構布局與命名

a

  • 圍繞產品功能/頁面/組件來組織您的文件,而不是圍繞角色來組織文件。此外,請將測試文件放在他們對應實現的旁邊。

不規範

.

├── controllers

| ├── product.js

| └── user.js

├── models

| ├── product.js

| └── user.js

規範

.

├── product

| ├── index.js

| ├── product.js

| └── product.test.js

├── user

| ├── index.js

| ├── user.js

| └── user.test.js

為什麼:

比起一個冗長的列表文件,創建一個單一責權封裝的小模塊,並在其中包括測試文件。將會更容易瀏覽,更一目了然。

  • 將其他測試文件放在單獨的測試文件夾中以避免混淆。

為什麼:

這樣可以節約您的團隊中的其他開發人員或DevOps專家的時間。

  • 使用./config文件夾,不要為不同的環境製作不同的配置文件。

為什麼:

當您為不同的目的(資料庫,API等)分解不同的配置文件;將它們放在具有容易識別名稱(如「config」)的文件夾中才是有意義的。只要記住不要為不同的環境製作不同的配置文件。這樣並不是具有擴展性的做法,如果這樣,就會導致隨著更多應用程序部署被創建出來,新的環境名稱也會不斷被創建,非常混亂。 配置文件中使用的值應通過環境變數提供。 更多請閱讀...

  • 將腳本文件放在./scripts文件夾中。包括bash腳本和node腳本。 為什麼:

很可能最終會出現很多腳本文件,比如生產構建,開發構建,資料庫feeders,資料庫同步等。

  • 將構建輸出結果放在./build文件夾中。將build/添加到.gitignore中以便忽略此文件夾。

為什麼:

命名為你最喜歡的就行,dist看起來蠻酷的。但請確保與您的團隊保持一致性。哪些東西最有應該放這個文件夾呢?比如(bundle,編譯結果,轉換結果)。您產生什麼編譯結果,您的隊友也可以生成同樣的結果,所以沒有必要將這些結果提交到遠程倉庫中。除非你故意希望提交上去。

  • 文件名和目錄名請使用PascalCase``camelCase風格。組件請使用PascalCase風格。
  • CheckBox/index.js應該代表CheckBox組件,也可以寫成CheckBox.js,但是不能寫成冗長的CheckBox/CheckBox.js或checkbox/CheckBox.js。
  • 理想情況下,目錄名稱應該和index.js的默認導出名稱相匹配。

為什麼:

這樣您就可以通過簡單地導入其父文件夾直接使用你預期的組件或模塊。

7. 代碼風格

a

  • 對新項目請使用Stage2和更高版本的JavaScript(現代化)語法。對於老項目,保持與老的語法一致,除非您打算把老的項目也更新為現代化風格。

為什麼:

這完全取決於你的選擇。我們使用轉換器來使用新的語法糖。Stage2更有可能最終成為規範的一部分,而且僅僅只需經過小版本的迭代就會成為規範。

  • 在構建過程中包含代碼風格檢查。

為什麼:

在構建時中斷下一步操作是一種強制執行代碼風格檢查的方法。強制你認真對待代碼。請確保在客戶端和伺服器端代碼都執行代碼檢查。 更多請閱讀...

  • 使用 ESLint - Pluggable JavaScript linter 去強制執行代碼檢查

為什麼:

我們個人很喜歡eslint,不強制你也喜歡。它支持更多的規則,配置規則的能力和添加自定義規則的能力。

  • 針對JavaScript我們使用Airbnb JavaScript Style Guide , 更多請閱讀. 在你的團隊和項目中推廣此代碼風格是必須的。
  • 我們使用 ESLint的流式樣式檢查規則。 如果使用FlowType.

為什麼:

Flow引入了很少的語法,需要遵循這些代碼風格並進行檢查。

  • 使用.eslintignore將某些文件或文件夾從代碼風格檢查中排除。

為什麼:

當您需要從風格檢查中排除幾個文件時,就再也不需要通過eslint-disable注釋來污染您的代碼了。

  • 在Pull Request之前,請刪除任何eslint的禁用注釋。

為什麼:

在處理代碼塊時禁用風格檢查是正常現象,這樣就可以關注在業務邏輯。只要記住把那些eslint-disable注釋刪除並遵循這些風格規則。

  • 根據任務的大小使用//TODO:注釋或做一個標籤。

為什麼:

這樣你就可以提醒自己和他人有這樣一個小的任務需要處理(如重構一個函數或更新一個注釋)。對於較大的任務,使用由lint規則執行的//TODO(#3456),其中的#3456號碼是一個標籤,方便查找。

  • 隨著代碼的變化,始終保持注釋的相關性。刪除那些注釋掉的代碼塊。

為什麼:

代碼應該儘可能的可讀,你應該擺脫任何分心的事情。如果你在重構一個函數,就不要注釋那些舊代碼,直接把要注釋的代碼刪除吧。

  • 避免不相關的和搞笑的的注釋,日誌或命名。

為什麼:

雖然您的構建過程中可能(應該)移除它們,但有可能您的源代碼會被移交給另一個公司/客戶,你的這些笑話應該無法逗樂你的客戶。

  • 請使用有意義容易搜索的命名,避免縮寫名稱。對於函數使用長描述性命名。功能命名應該是一個動詞或動詞短語,需要能清楚傳達意圖的命名。

為什麼:

它使讀取源代碼變得更加自然。

  • Organize your functions in a file according to the step-down rule. Higher level functions should be on top and lower levels below.(譯者註:這一段我翻譯不好,大家看看原文吧,大體意思是為了說明函數的組織方式,根據逐級下降的規則,把底層函數和上層函數按照具有具有條理性的規則拆分開。也有朋友說這個是高階函數的封裝。此中文翻譯已經被官方採納,我們等hive的同事給出進一步解釋吧。也請讀者給出您的寶貴建議。)

為什麼:

它使源代碼的可讀性更好。

8. 日誌

a

  • 避免在生產環境中使用客戶端的日誌

為什麼:

您在構建過程可以把(應該)它們去掉,但是請確保您在代碼風格檢查中提供了有關控制台日誌的警告信息。

  • 用於生產環境的可讀生產日誌記錄。一般使用在生產模式下所使用的日誌記錄庫 (比如 winston or node-bunyan).

為什麼:

它通過添加著色、時間戳、log到控制台或者文件中,來減少故障排除中那些令人不愉快的事情,這些文件會每天滾動迭代。更多請閱讀...

9. API

a

9.1 API 設計

為什麼:

因為我們試圖實施開發出結構穩健的Restful介面,讓團隊成員和客戶可以簡單而一致地使用它們。

為什麼:

缺乏一致性和簡單性會大大增加集成和維護的成本。這就是為什麼API設計這部分會包含在這個文檔中的原因

  • 我們主要遵循資源導向的設計方式。它有三個主要要素:資源,集合和URLs。
    • 資源具有數據,嵌套,和一些操作方法。
    • 一組資源稱為一個集合。
    • URL標識資源或集合的在線位置。

為什麼:

這是針對開發人員(您的主API使用者)非常著名的設計方式。除了可讀性和易用性之外,它還允許我們在無需了解API細節的情況下編寫通用庫和一些連接器。

  • 使用kebab模式的URL。
  • 在查詢字元串或資源欄位中使用camelCase模式。
  • 在URL中使用多個kebab-case作為資源名稱。
  • 總是使用複數名詞來命名指向一個集合的url:/users.

為什麼:

基本上,它可讀性會更好,並可以保持URL的一致性。 更多請閱讀...

  • 在源代碼中,將複數轉換為具有列表後綴名描述的變數和屬性。

為什麼_:

複數形式的URL非常好,但在源代碼中使用它卻很微妙而且容易出錯,所以要小心謹慎。

  • 堅持這樣一個概念:始終以集合名起始並以標識符結束。

/students/245743

/airports/kjfk

  • 避免這樣的網址:

GET /blogs/:blogId/posts/:postId/summary

為什麼:

這不是在指向資源,而是在指向屬性。您完全可以將屬性作為參數傳遞,以減少響應。

  • URLs裡面請盡量少用動詞

為什麼:

因為如果你為每個資源操作使用一個動詞,你很快就會維護一個很大的URL列表,而且沒有一致的使用模式,這會使開發人員難以學習。此外,我們還要使用動詞做別的事情。

  • 為非資源型請求使用動詞。在這種情況下,您的API並不需要返回任何資源。而是去執行一個操作並返回執行結果。這些不是 CRUD(創建,查詢,更新和刪除)操作:

/translate?text=Hallo

為什麼:

因為對於CRUD,我們在資源或集合URL上使用HTTP自己帶的方法。我們所說的動詞實際上是指Controllers。你通常不會開發這些東西。更多請閱讀...

  • 請求體或響應類型如果是JSON,那麼請遵循camelCase規範為JSON屬性命名來保持一致性。

為什麼:

這是一個JavaScript項目指南,其中用於生成JSON的編程語言以及用於解析JSON的編程語言被假定為JavaScript。

  • 即使資源類似於對象實例或資料庫記錄這樣的單一概念,您也不應該將table_name用作資源名稱或將column_name作為資源屬性。

為什麼:

因為您的目的是分析資源,而不是分析資料庫模式。

  • 再次,只有在您的URL上面命名資源時才使用名詞,不要嘗試解釋其功能。

為什麼:

只能在資源URL中使用名詞,避免像/addNewUser或/updateUser這樣的結束點。也避免使用參數作為發送資源的操作。

  • 如何使用HTTP方法來操作CRUD功能

怎麼做:

GET: 查詢資源的表示法

POST: 創建一些新的資源或者子資源

PUT: 更新一個存在的資源

PATCH: 更新現有資源。它只更新所提供的欄位,不管其他欄位

DELETE: 刪除一個存在的資源

  • 對於嵌套資源,請在URL中把他們的關係表現出來。例如,使用id將員工與公司聯繫起來。

為什麼:

這是一種自然的方式,方便資源的認知。

怎麼做:

GET /schools/2/students , 應該從學校2得到所有學生的名單

GET /schools/2/students/31 , 應該得到學生31的詳細信息,且此學生屬於學校2

DELETE /schools/2/students/31 , 應刪除屬於學校2的學生31

PUT /schools/2/students/31 , 應該更新學生31的信息,僅在資源URL上使用PUT方式,而不要用收集

POST /schools , 應該創建一所新學校,並返回創建的新學校的細節。在集合URL上使用POST

  • 對於具有v前綴(v1,v2)的版本,使用簡單的序數。並將其移到URL的左側,使其具有最高的範圍表述:

http://api.domain.com/v1/schools/3/students

為什麼:

當您的API為第三方公開時,升級API會導致發生一些意料之外的影響,也可能導致使用您API的人無法使用你的服務和產品。而這時使用URL中版本化可以防止這種情況的發生。 更多請閱讀...

  • 響應消息必須是自我描述的。一個很好的錯誤消息響應可能如下所示:

{

"code": 1234,

"message" : "Something bad happened",

"description" : "More details"

}

或驗證錯誤:

{

"code" : 2314,

"message" : "Validation Failed",

"errors" : [

{

"code" : 1233,

"field" : "email",

"message" : "Invalid email"

},

{

"code" : 1234,

"field" : "password",

"message" : "No password provided"

}

]

}

為什麼:

開發人員在使用這些由API構建的應用程序時,難免會需要在故障排除和解決問題的關鍵時刻使用到這些精心設計的錯誤消息。好的錯誤消息設計能節約大量的問題排查時間。

_注意:儘可能保持安全異常消息的通用性。例如,別說不正確的密碼,您可以換成無效的用戶名或密碼,以免我們不知不覺地通知用戶他的用戶名確實是正確的,只有密碼不正確。這會讓用戶很懵逼。

  • 只使用這8個狀態代碼,並配合您自定義的響應描述來表述程序工作一切是否正常客戶端應用程序發生了什麼錯誤API發生錯誤

選誰呢?:

200 OK GET, PUT 或 POST 請求響應成功.

201 Created 標識一個新實例創建成功。當創建一個新的實例,請使用POST方法並返回201狀態碼。

304 Not Modified 發現資源已經緩存在本地,瀏覽器會自動減少請求次數。

400 Bad Request 請求未被處理,因為伺服器不能理解客戶端是要什麼。

401 Unauthorized 因為請求缺少有效的憑據,應該使用所需的憑據重新發起請求。

403 Forbidden 意味著伺服器理解本次請求,但拒絕授權。

404 Not Found 表示未找到請求的資源。

500 Internal Server Error 表示請求本身是有效,但由於某些意外情況,伺服器無法實現,伺服器發生了故障。

為什麼:

大多數API提供程序僅僅只使用一小部分HTTP狀態代碼而已。例如,Google GData API僅使用了10個狀態代碼,Netflix使用了9個,而Digg只使用了8個。當然,這些響應作為響應主體的附加信息。一共有超過70個HTTP狀態代碼。然而,大多數開發者不可能全部記住這70個狀態碼。因此,如果您選擇不常用的狀態代碼,您將使應用程序開發人員厭煩構建應用程序,然後你還要跑到維基百科上面找出您要告訴他們的內容,多累啊。 更多請閱讀...

  • 在您的響應中提供資源的總數
  • 接受limit和offset參數
  • 還應考慮資源暴露的數據量。 API消費者並不總是需要資源的完整表述。可以使用一個欄位查詢參數,該參數用逗號分隔的欄位列表來包括:

GET /student?fields=id,name,age,class

  • 分頁,過濾和排序功能並不需要從所有資源一開始就要得到支持。記錄下那些提供過濾和排序的資源。

9.2 API 安全

這些是一些基本的安全最佳實踐:

  • 不要只使用基本認證。不要在URL中傳輸驗證令牌:GET /users/123?token=asdf....

為什麼:

因為令牌、用戶ID和密碼通過網路是明文傳遞的(它是base64編碼,而base64是可逆編碼),所以基本認證方案是不安全的。 更多請閱讀...

  • 必須使用授權請求頭在每個請求上發送令牌:Authorization: Bearer xxxxxx, Extra yyyyy
  • 授權代碼應該是簡短的。
  • 通過不響應任何HTTP請求來拒絕任何非TLS請求,以避免任何不安全的數據交換。響應403 Forbidden的HTTP請求。
  • 考慮使用速率限制

為什麼:

保護您的API免受每小時數千次的機器人掃描威脅。您應該考慮在早期就實施流控。

  • 適當地設置HTTP請求頭可以幫助鎖定和保護您的Web應用程序。更多請閱讀...
  • 您的API應將收到的數據轉換為規範形式,或直接拒絕響應,並返回400錯誤,並在其中包含有關錯誤或丟失數據的詳細信息。
  • 所有通過Rest API交換的數據必須由API來校驗。
  • 序列號JSON

為什麼:

JSON編碼器的一個關鍵問題是阻止瀏覽器中輸入的任意JavaScript代碼在遠程被執行,或者如果您在伺服器上使用node.js。您必須使用適當的JSON序列化程序對用戶輸入的數據進行正確編碼,以防止在瀏覽器上執行用戶提供的輸入,這些輸入可能會包含惡意代碼,而不是正常的用戶數據。

  • 驗證內容類型,主要使用application/*.json(Content-Type 頭欄位).

為什麼:

例如,接受application/x-www-form-urlencodedMIME類型可以允許攻擊者創建一個表單並觸發一個簡單的POST請求。伺服器不應該假定Content-Type。缺少Content-Type請求頭或異常的Content-Type請求頭應該讓伺服器直接以4XX響應內容去拒絕請求。

9.3 API 文檔

  • 在[README.md模板](./README.sample.md)為API填寫 API參考段落。
  • 盡量使用示例代碼來描述API授權方法
  • 解釋URL的結構(僅path,不包括根URL),包括請求類型(方法)

對於每個端點(endpoint)說明:

  • 如果存在URL參數就使用URL參數,請根據URL中使用到的名稱來指定它們:

Required: id=[integer]

Optional: photo_id=[alphanumeric]

  • 如果請求類型為POST,請提供如何使用的示例。URL Params也是這樣。Params分為可選和必需。
  • 響應成功,應該對應什麼樣的狀態代碼,返回了哪些數據?當人們需要知道他們的回調應該是期望的樣子,這很有用:

Code: 200

Content: { id : 12 }

  • 錯誤響應,大多數端點都存在許多失敗的可能。比如錯誤參數導致的未經授權的訪問等。所有的都應該列在這裡。雖然有可能會重複,但它卻有助於防止發生損害。例如

{

"code": 403,

"message" : "Authentication failed",

"description" : "Invalid username or password"

}

  • 使用API設計工具,有很多開源工具可用於提供良好的文檔,例如 API Blueprint and Swagger.

10. 證書

a

確保您有權使用的這些資源。如果您使用其中的軟體庫,請記住先查詢MIT,Apache或BSD,但如果您打算修改它們,請查看許可證詳細信息。圖像和視頻的版權可能會導致法律問題。

資源: RisingStack Engineering, Mozilla Developer Network, Heroku Dev Center, Airbnb/javascript, Atlassian Git tutorials, Apigee, Wishtack


求企鵝


推薦閱讀:

假如沒有載入畫面遮掩,在進入遊戲或者關卡時玩家會看到什麼樣的場景?
python2.7.9卸載和安裝提示there is a problem....該怎麼解決?
一名計算機大專學生的困惑?
為何有些程序的文件操作對話框不能輸入地址?
作為一個普通211大學的非王牌專業的學生,學習地理信息科學,是否能夠重點轉向為編程?

TAG:前端開發 | 程序員 | 編程 | 開源 | GitHub |