Deno 風(fēng)格指南

2020-06-24 17:06 更新

目錄

版權(quán)標(biāo)題

存儲(chǔ)庫(kù)中的大多數(shù)模塊都應(yīng)具有以下版權(quán)標(biāo)題: // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. 如果代碼來(lái)源于其他地方,請(qǐng)確保文件擁有適當(dāng)?shù)陌鏅?quán)擁有者。 我們只允許 MIT、BSD 和 Apache 許可代碼。

在文件名中使用下劃線,而不是破折號(hào)

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

為新特性添加測(cè)試

每個(gè)模塊都應(yīng)該包含或伴隨著對(duì)其公共功能的測(cè)試。

TODO 注釋

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

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

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

包含代碼(Inclusive code)

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

Rust

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

Typescript

代碼庫(kù)的 TypeScript 部分包括內(nèi)置的 cli/js 和標(biāo)準(zhǔn)庫(kù) std。

使用 TypeScript 而不是 JavaScript

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

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

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

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

導(dǎo)出函數(shù)(Exported functions): 最多 2 個(gè)參數(shù),其余的放入一個(gè)選項(xiàng)對(duì)象(options object)

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

// 錯(cuò)誤示例:可選參數(shù)不是選項(xiàng)對(duì)象的一部分 (#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;
}


// 錯(cuò)誤示例:`env`可以是一個(gè)常規(guī)對(duì)象,因此無(wú)法與選項(xiàng)對(duì)象區(qū)分 (#3)
export function runShellWithEnv(cmdline: string, env: Environment): string {}


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

// 錯(cuò)誤示例:多于3個(gè)參數(shù) (#1),多個(gè)可選參數(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 = {}
) {}

// 錯(cuò)誤示例:參數(shù)過(guò)多 (#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) {}

// 錯(cuò)誤示例:參數(shù)過(guò)多 (#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) {}

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

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

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

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

對(duì)導(dǎo)出的符號(hào)使用 JSDoc

我們力求文檔的完整性。理想情況下,每個(gè)導(dǎo)出的文檔符號(hào)都應(yīng)該有一個(gè)文檔行。 如果可能的話,最好寫(xiě)單行 JSDoc。例如:

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

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

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

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

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

應(yīng)盡可能減小垂直間距。因此單行注釋?xiě)?yīng)寫(xiě)為:

/** 這樣寫(xiě)單行 JSDoc 注釋。 */

不要寫(xiě)為:

/**
 * 不要這樣寫(xiě)單行 JSDoc 注釋。
 */

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

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

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

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

單元測(cè)試應(yīng)是明確的

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

test myTestFunction ... ok

測(cè)試示例:

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" });
});

頂級(jí)函數(shù)不應(yīng)使用箭頭語(yǔ)法

頂級(jí)函數(shù)應(yīng)使用 function 關(guān)鍵字。箭頭語(yǔ)法應(yīng)限于閉包。 錯(cuò)誤示例:

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

正確示例:

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

std

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

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

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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)