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 部分包括內置的 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ā)生了變化。

// 錯誤示例:可選參數(shù)不是選項對象的一部分 (#2)
export function resolve(
  hostname: string,
  family?: "ipv4" | "ipv6",
  timeout?: number
): IPAddress[] {}


// 正確示例:
export interface ResolveOptions {
  family?: "ipv4" | "ipv6";
  timeout?: number;
}
export function resolve(
  hostname: string,
  options: ResolveOptions = {}
): IPAddress[] {}
export interface Environment {
  [key: string]: string;
}


// 錯誤示例:`env`可以是一個常規(guī)對象,因此無法與選項對象區(qū)分 (#3)
export function runShellWithEnv(cmdline: string, env: Environment): string {}


// 正確示例
export interface RunShellOptions {
  env: Environment;
}
export function runShellWithEnv(
  cmdline: string,
  options: RunShellOptions
): string {}

// 錯誤示例:多于3個參數(shù) (#1),多個可選參數(shù) (#2)。
export function renameSync(
  oldname: string,
  newname: string,
  replaceExisting?: boolean,
  followLinks?: boolean
) {}


// 正確示例
interface RenameOptions {
  replaceExisting?: boolean;
  followLinks?: boolean;
}
export function renameSync(
  oldname: string,
  newname: string,
  options: RenameOptions = {}
) {}

// 錯誤示例:參數(shù)過多 (#1)
export function pwrite(
  fd: number,
  buffer: TypedArray,
  offset: number,
  length: number,
  position: number
) {}


// 正確示例:
export interface PWrite {
  fd: number;
  buffer: TypedArray;
  offset: number;
  length: number;
  position: number;
}
export function pwrite(options: PWrite) {}

// 錯誤示例:參數(shù)過多 (#1)
export function pwrite(
  fd: number,
  buffer: TypedArray,
  offset: number,
  length: number,
  position: number
) {}


// 正確示例:
export interface PWrite {
  fd: number;
  buffer: TypedArray;
  offset: number;
  length: number;
  position: number;
}
export function pwrite(options: PWrite) {}

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

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

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

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

對導出的符號使用 JSDoc

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

/** foo does bar. */
export function foo() {
  // ...
}

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

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

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

/**
 * Function with non obvious param.
 * @param foo Description of non obvious parameter.
 */

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

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

不要寫為:

/**
 * 不要這樣寫單行 JSDoc 注釋。
 */

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

/** A straight forward comment and an example:
 *
 *       import { foo } from "deno";
 *       foo("bar");
 */

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

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

單元測試應是明確的

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

test myTestFunction ... ok

測試示例:

import { assertEquals } from "https://deno.land/std@v0.11/testing/asserts.ts";
import { foo } from "./mod.ts";


Deno.test("myTestFunction" function() {
  assertEquals(foo(), { bar: "bar" });
});

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

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

export const foo = (): string => {
  return "bar";
};

正確示例:

export function foo(): string {
  return "bar";
}

std

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

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

以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號