Deno 風格指南

2020-06-24 17:06 更新

目錄

版權標題

存儲庫中的大多數(shù)模塊都應具有以下版權標題: // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. 如果代碼來源于其他地方,請確保文件擁有適當?shù)陌鏅鄵碛姓摺?我們只允許 MIT、BSD 和 Apache 許可代碼。

在文件名中使用下劃線,而不是破折號

例如: 將文件命名為 file_server.ts 而不是 file-server.ts。

為新特性添加測試

每個模塊都應該包含或伴隨著對其公共功能的測試。

TODO 注釋

TODO 注釋通常應該將一個 issue 或者作者的 github 用戶名放在括號中。例如: // TODO(ry): Add tests. // TODO(#123): Support Windows. // FIXME(#349): Sometimes panics.

不建議使用元編程(Meta-programming),包括代理(Proxy)的使用

即使要寫更多的代碼,也要力求明確。 在某些情況下,使用這些技術可能是有意義的,但是在絕大多數(shù)情況下,它們是沒有意義的。

包含代碼(Inclusive code)

請遵循有關包含代碼的準則,網(wǎng)址為: https://chromium.googlesource.com/chromium/src/+/master/styleguide/inclusive_code.md

Rust

遵循 Rust 約定,并與現(xiàn)有代碼保持一致。

Typescript

代碼庫的 TypeScript 部分包括內(nèi)置的 cli/js 和標準庫 std。

使用 TypeScript 而不是 JavaScript

使用術語“模塊(module)”,而不是“庫(library)”或“包(package)”

為了保證明確性和一致性,避免使用術語 “l(fā)ibrary” 和 “package” ,而是使用 “module” 來引用一個 JS 或 TS 文件,或者一個 TS/JS 代碼目錄。

不要使用 index.ts 或 index.js 作為文件名

Deno 不會以特殊的方式處理 “index.js” 或 “index.ts” 文件。如果使用了這些名稱,就意味著當它們需要模塊說明符時,可能被排除在外。這會造成誤解。 如果一個代碼目錄需要一個默認的入口點,使用文件名 mod.ts。 文件名 mod.ts 遵循 Rust 的約定,比 index.ts 短,并且沒有任何關于它如何工作的先入為主的概念。

導出函數(shù)(Exported functions): 最多 2 個參數(shù),其余的放入一個選項對象(options object)

  1. 在設計函數(shù)接口時,請嚴格遵循以下規(guī)則: 若某函數(shù)是公共 API 的一部分,則其可以接受 0~2 個參數(shù),如果必要的話,可以外加一個選項對象,因此最大總數(shù)為 3 個。
  2. 可選參數(shù)通常應放到選項對象中。 如果只有一個可選參數(shù),并且將來一般不會添加更多可選參數(shù),那么該可選參數(shù)可以不放在選項對象中。
  3. 選項參數(shù)是唯一一個常規(guī)對象參數(shù) 其他參數(shù)可以是對象,但它們在運行時必須能區(qū)別于其他一般的對象("plain" Object)。有以下兩種方法進行區(qū)別:
    • 一個獨特的原型(例如:Array,Map,Date,class MyThing)
    • 一個眾所周知的符號屬性(例如 Symbol.iterator) 這允許 API 以向后兼容的方式發(fā)展,即使選項對象的位置發(fā)生了變化。

  1. // 錯誤示例:可選參數(shù)不是選項對象的一部分 (#2)
  2. export function resolve(
  3. hostname: string,
  4. family?: "ipv4" | "ipv6",
  5. timeout?: number
  6. ): IPAddress[] {}
  7. // 正確示例:
  8. export interface ResolveOptions {
  9. family?: "ipv4" | "ipv6";
  10. timeout?: number;
  11. }
  12. export function resolve(
  13. hostname: string,
  14. options: ResolveOptions = {}
  15. ): IPAddress[] {}
  1. export interface Environment {
  2. [key: string]: string;
  3. }
  4. // 錯誤示例:`env`可以是一個常規(guī)對象,因此無法與選項對象區(qū)分 (#3)
  5. export function runShellWithEnv(cmdline: string, env: Environment): string {}
  6. // 正確示例
  7. export interface RunShellOptions {
  8. env: Environment;
  9. }
  10. export function runShellWithEnv(
  11. cmdline: string,
  12. options: RunShellOptions
  13. ): string {}

  1. // 錯誤示例:多于3個參數(shù) (#1),多個可選參數(shù) (#2)。
  2. export function renameSync(
  3. oldname: string,
  4. newname: string,
  5. replaceExisting?: boolean,
  6. followLinks?: boolean
  7. ) {}
  8. // 正確示例
  9. interface RenameOptions {
  10. replaceExisting?: boolean;
  11. followLinks?: boolean;
  12. }
  13. export function renameSync(
  14. oldname: string,
  15. newname: string,
  16. options: RenameOptions = {}
  17. ) {}

  1. // 錯誤示例:參數(shù)過多 (#1)
  2. export function pwrite(
  3. fd: number,
  4. buffer: TypedArray,
  5. offset: number,
  6. length: number,
  7. position: number
  8. ) {}
  9. // 正確示例:
  10. export interface PWrite {
  11. fd: number;
  12. buffer: TypedArray;
  13. offset: number;
  14. length: number;
  15. position: number;
  16. }
  17. export function pwrite(options: PWrite) {}

  1. // 錯誤示例:參數(shù)過多 (#1)
  2. export function pwrite(
  3. fd: number,
  4. buffer: TypedArray,
  5. offset: number,
  6. length: number,
  7. position: number
  8. ) {}
  9. // 正確示例:
  10. export interface PWrite {
  11. fd: number;
  12. buffer: TypedArray;
  13. offset: number;
  14. length: number;
  15. position: number;
  16. }
  17. export function pwrite(options: PWrite) {}

盡量降低依賴性;不要進行循環(huán)導入

盡管 cli/js 和 std 沒有外部依賴關系,但仍然必須注意保持內(nèi)部依賴關系的簡單性和可管理性。請尤為注意,不要引入循環(huán)導入。

不要連接到文件名以下劃線開頭的文件,如:_foo.ts

有時候可能需要一個內(nèi)部模塊,但是它的 API 并不穩(wěn)定或者不被連接。這種情況下,在文件名前面加一個下劃線。按照慣例,只有它自己目錄中的文件才能導入它。

對導出的符號使用 JSDoc

我們力求文檔的完整性。理想情況下,每個導出的文檔符號都應該有一個文檔行。 如果可能的話,最好寫單行 JSDoc。例如:

  1. /** foo does bar. */
  2. export function foo() {
  3. // ...
  4. }

文檔易于閱讀是很重要的,但是還需要提供額外的樣式信息,以確保生成的文檔有更豐富的含義。因此,JSDoc 通常應該遵循 markdown 標記來豐富文本。 雖然 markdown 支持 HTML 標記,但是在 JSDoc 塊中是禁止的。 代碼字符串文字應使用反引號(`)括起來,而不是用引號。例如:

  1. /** Import something from the `deno` module. */

不要記錄函數(shù)參數(shù),除非它們的意圖不明顯(當然,如果它們沒有明顯的意圖,應該重新考慮 API 的設計)。因此,通常不應使用 @param。如果使用了 @param,則不應該包含 type ,因為 TypeScript 已經(jīng)是強類型化的了。

  1. /**
  2. * Function with non obvious param.
  3. * @param foo Description of non obvious parameter.
  4. */

應盡可能減小垂直間距。因此單行注釋應寫為:

  1. /** 這樣寫單行 JSDoc 注釋。 */

不要寫為:

  1. /**
  2. * 不要這樣寫單行 JSDoc 注釋。
  3. */

代碼示例不應使用三個反引號(```)標記。它們應該用縮進標記,要求在示例代碼塊前加入一個空行,并且示例代碼的每一行需要有 6 個額外空格。比注釋的第一列多 4 個空格。例如:

  1. /** A straight forward comment and an example:
  2. *
  3. * import { foo } from "deno";
  4. * foo("bar");
  5. */

既然代碼示例已經(jīng)是一個注釋了,它就不應再包含其他注釋。如果它需要進一步的注釋,那意味著它不是一個很好的示例。

每個模塊都應該附帶一個測試模塊 每個帶有公共功能 foo.ts 的模塊都應該附帶一個測試模塊 foo_test.ts。由于 cli/js 模塊的上下文不同,它的測試應該放在 cli/js/tests 中,或者它應只是測試模塊的同級模塊。

單元測試應是明確的

為了更好地理解測試,函數(shù)應該在測試命令中按照提示正確命名,如:

  1. test myTestFunction ... ok

測試示例:

  1. import { assertEquals } from "https://deno.land/std@v0.11/testing/asserts.ts";
  2. import { foo } from "./mod.ts";
  3. Deno.test("myTestFunction" function() {
  4. assertEquals(foo(), { bar: "bar" });
  5. });

頂級函數(shù)不應使用箭頭語法

頂級函數(shù)應使用 function 關鍵字。箭頭語法應限于閉包。 錯誤示例:

  1. export const foo = (): string => {
  2. return "bar";
  3. };

正確示例:

  1. export function foo(): string {
  2. return "bar";
  3. }

std

不要依賴外部代碼 https://deno.land/std/ 旨在成為所有 Deno 程序可以依賴的基礎功能。我們希望向用戶保證,此代碼不包含任何可能未經(jīng)審核的第三方代碼。 文檔以及維護瀏覽器兼容性 如果一個模塊兼容瀏覽器,在模塊頂部的 JSDoc 中包含以下聲明:

/* This module is browser compatible. / 為該模塊維護瀏覽器兼容性,在代碼和測試中都不要使用 Deno 命名空間,確保任何新的依賴都兼容瀏覽器。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號