编程英语基础

编程是一门语言艺术。要写出赏心悦目的代码,最重要的便是恰当的命名变量,函数,类和包等。每种编程语言都自己独特的语法和代码风格。比如 C 语言常用 snake_case 命名,而 Java 语言用 camelCase 命名。这篇文章将不去探讨具体语言的特有规范,而是去介绍通用的命名的英语语法,比如变量类型与词性的关系,词组和短语的顺序,省略的用法,近义词的辨析等。示例以 Java/TypeScript 为主。正确示例标记为✔️,错误示例标记为❌。

本文有待完善,欢迎读者意见。

命名规则

布尔值

布尔(Boolean)通常是优先用形容词命名的,动词的过去分词 -ed 和现在进行时 -ing 也可以看作形容词。形容词通常都是描述状态的,非是则否。

boolean visible = true; // ✔️ 形容词,且能判断是非
boolean hasChildren = true; // ✔️ 动词短语,且能判断是非
boolean checkSyntax = false; // ❌ 描述的是行为,无法判断是非
boolean isSyntaxCorrect = true; // ✔️ 描述的是状态,可以判断是非
boolean k = false; // ❌ 没有明确含义

名词,单个动词通常不能用来命名布尔值,要使用它们的形容词变形。

boolean close = false; // ❌ 动词
boolean closed = true; // ✔️ 形容词
boolean enable = false; // ❌ 动词
boolean enabled = true; // ✔️ 形容词
boolean edit = false; // ❌ 动词
boolean edited = true; // ✔️ 形容词
boolean editable = true; // ✔️ 形容词
boolean success = false; // ❌ 名词
boolean succeed = false; // ❌ 名词
boolean successful = true; // ✔️ 形容词
boolean succeeded = true; // ✔️ 形容词
boolean edit = false; // ❌ edit 是动词
boolean edited = true; // ✔️ edited 是形容词
boolean editable = true; // ✔️ editable 是形容词

注意有些英文单词既是形容词,也是动词,在同一个范围内方法和字段名冲突时可以有两种思路:

// 字段前缀 is
class Dialog {
  boolean isOpen = false;
  void open() {}
  void close() {}
}
// 方法后缀对象
class Dialog {
  boolean open = false;
  void openDialog() {}
  void closeDialog() {}
}
// 方法前缀 set
class Dialog {
  boolean open = false;
  void setOpen(boolean open) {}
}

如果是复合词,则主体形容词放在最后。

boolean disabledLeftButton = false; // ❌ 主体是 button
boolean buttonDisabledLeft = false; // ❌ 主体是 left
boolean leftButtonDisabled = true; // ✔️ 主体是 disabled

复杂的情况也会用动词短语,但要确保命名一定要是描述一种状态(而不是行为),能够判断是非的,意义明确的。

boolean checkSyntax = false; // ❌ 描述的是行为,无法判断是非
boolean isSyntaxCorrect = true; // ✔️ 描述的是状态,可以判断是非

枚举值

枚举(Enumerate)通常是用名词-名词或者名词-形容词命名的。

enum Direction {
  Left,
  Right,
  Up,
  Down
}

enum Status {
  Loading,
  Succeeded,
  Failed
}

数字

数字(Number)通常是用量词命名的。比较常见的错误是使用名词复数。

int rows = 100; // ❌ 名词复数常用做数组列表,容易引起混淆
int rowCount = 100; // ✔️ 量词

字符串

字符串(String)通常是用名词命名的。原则上是通过变量名能猜到是字符串类型。

String author = "Tom"; // ❌ author 也可能是对象,容易引起混淆
String authorName = "Tom"; // ✔️ authorName 明显是字符串

类和对象

类和对象通常是名词。

类的对象的名词通常有很多定语修饰,定语顺序是一个大问题。英语老师传授了一个容易记的口诀:美小圆旧黄,法国木书房。意思是定语顺序为:美丑-大小-形状-新旧-颜色-国家-材质-用途-主体。比如 headerFancyVideo 是错的, fancyHeaderVideo 是对的。又比如 iconMapSvgLarge 是错的,largeMapSvgIcon 是对的。如果有后置定语,则应该放到最后,比如 usersWithPosts

函数/方法

函数(Function)和方法(Method)通常是用动词命名的,不能用形容词或名词。比如 active() 是错的,activate() 是对的。

对于 setter 和 getter,由于 set 和 get 已经充当了动词,则方法名可以用名词和形容词。比如 set size()

像是 xml2json() 这种函数命名用法很常见,但是推荐使用 convertXmlToJson()。一味追求命名的简短并没有什么好处。

React 中的函数组件是一个例外,需要用名词。

函数的调用形式没有主语,而方法则有对象或类作为主语。这带来了一些命名上的区别。方法名可以用介词短语,比如 book.toJson() ,但是函数名则不能这样。

另外一个晦涩的问题是:有的时候我们会用 has,is,contains,includes 这样的第三人称单数,但是 get,set,add,remove 这种却总是用动词原形。这是为什么呢?这与主语的判断有关。以 JavaScript 的 Array 为例,我们可以从自然语言表达来推断方法的动词形式:

  1. the array includes element → Array.includes()
  2. find an element in array → Array.find()
  3. map an array into another array → Array.map()

而对于函数,则要根据函数中的名词或第一个参数在自然语言中的位置来判断:

  1. input string is ISBN → isISBN(input)
  2. compare date A and date B → compareDate(dateA, dateB)
  3. element contains iframe → containsIframe(element)

有一些方法使用了名词的形式,比如 JavaScript 的 Array.keys() 省略了 get。这有其历史原因,我们自己命名方法的时候还是应该用动词,不要盲目效仿。

React

React 组件(Component)可以用函数或类来实现,用名词命名。

可视化的组件,应用可视化名词后缀。比如 <Product/> 就太泛泛,不能描述它的视觉呈现效果,可以根据视觉样式命名为 <ProductCard/>

列表组件通常用 <ProductsList/> 这种错误的英语语法。在 React 的圈子,这已经变成了事实标准。但我们推荐用 <ProductList/> 这种放之四海皆准的命名。

组件名比较复杂的,名词次序应为:视觉外观-实现方式。比如 <LinkButton/> 应该是一个看起来像链接的 <button/> ,而 <ButtonLink/> 应该是一个看起来像按钮的 <a/>

属性 Interface 应该用组件名加上 Props 后缀。比如 ButtonProps。不要直接使用 Props,因为这样的命名太宽泛,导出后会产生冲突。状态 Interface 应该用组件名加上 State 后缀,比如 DropdownState

组件属性中,回调函数一般用 on 前缀加动词,比如 onMouseEnteronMenuCollapse

React 的 Context 一定是以 Context 结尾的,比如 ThemeContext。封装 Context.Provider 的组件一定以 Provider 结尾的,比如 ThemeProvider。Context.Consumer 可以封装成 HOC 或 Hooks。

React 的 HOC 本质是函数,应该使用动词或介词短语,常用 with 前缀,比如 withRoute(MyView)

React 的钩子(Hooks)函数,则普遍使用 use 前缀命名。比如 useTheme()

词汇辨析

get

get 函数是直接从数据结构中获取数据的,没有大计算量或IO延迟。get 经常被用得太滥,项目里通篇 get,函数意义不明。

如果有大量数据计算,则应该用 calculate 或 compute 之类的词。

如果有数据结构转换,则应该用 transform 或 convert 之类的词。

如果有数据解码过程,则应该用 parse 或 decode 之类的词。

如果有 IO 延迟,则应该用 read (存储)或 fetch (网络)之类的词。(虽然 HTTP 就是有 GET 这个 Action,但是为了避免与其他方法混淆,还是应该用 fetch)

总之,当有更明确具体的动词替代,则不应该使用 get。

code

名称含 code 的变量通常是固定长度的字符串,有一个标准的编码表可查,是可以穷举的,因而不会特别长。比如 countryCode,currencyCode,languageCode,postalCode。

id

名称含 id 的变量可能是数字,也可能是字符串。SQL 应用通常用连续整数做 id,但 NoSQL 应用则通常是随机字符串。浏览器 DOM 的 id 是字符串。现实中的身份证号是字符串,设备 ID 也是字符串。id 的范围会随时间不断产生增多,没有上限或者上限很大。

index

index 做名词通常指列表中的连续编号,基本上都是整数。

实用建议

避免使用无意义的变量名

button1numstr 这种除了表明类型而没有明确含义的变量命名应该避免。变量名应该有其实际含义,比如 editButtonrowCountsourceText

谨慎使用缩写

广泛使用且没有歧义的缩写是可以使用的。比如 urlbtnsyncimg

不太常见的缩写,不建议使用。比如 tlbbkmnbevt

有歧义的缩写,也不建议使用。比如 dir 既可能是 direction 也可能是 directory

避免中文注释

很多常见词汇的中文和英文并不是一一对应的。比如在英文中 State 和 Status 是两个词,在编程中是不同的概念,但在中文里都是“状态”。而 Attribute 和 Property 在中文里都是“属性”,而在编程中是两种不同的东西。

另外像 Asset,Context,Portability 这种单词,中文翻译没有统一标准,反而不如英文容易懂。

最后,中文注释限制了代码的受众。如果想做开源或者国外市场,外国程序员读不懂这些注释,使用和参与的热情就会大打折扣。

避免拼音命名

在实际项目中使用的编程语言,几乎都不支持中文变量名。但是有很多使用拼音命名。

在 GitHub 上使用英文交流

GitHub 是一个国际化的开源社区平台。提 Issue 和 Pull Request 之前,要看看开发者是不是外国开发者。如果是的话,请使用英文。即使一些中文开发者维护的项目,如果是中外用户都涵盖(比如 Vue),一般也建议使用英文交流。

《“编程英语基础”》 有 1 条评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据