Naming Variables

10th May 2021 at 3:47pm
Programming: General Technique

对于变量命名的建议,Dart 这个 文档 写得非常好。下面大部分内容摘录自此。

保持一致

好的命名:

pageCount         // A field.
updatePageCount() // Consistent with pageCount.
toSomething()     // Consistent with Iterable's toList().
asSomething()     // Consistent with List's asMap().
Point             // A familiar concept.

差的命名:

renumberPages()      // Confusingly different from pageCount.
convertToSomething() // Inconsistent with toX() precedent.
wrappedAsSomething() // Inconsistent with asX() precedent.
Cartesian            // Unfamiliar to most users.

最重要的描述性名词放最后面

好的命名:

pageCount             // A count (of pages).
ConversionSink        // A sink for doing conversions.
ChunkedConversionSink // A ConversionSink that's chunked.
CssFontFaceRule       // A rule for font faces in CSS.

差的命名:

numPages                  // Not a collection of pages.
CanvasRenderingContext2D  // Not a "2D".
RuleFontFaceCss           // Not a CSS.

最重要的描述性名词放最后面

好的命名:

pageCount             // A count (of pages).
ConversionSink        // A sink for doing conversions.
ChunkedConversionSink // A ConversionSink that's chunked.
CssFontFaceRule       // A rule for font faces in CSS.

差的命名:

numPages                  // Not a collection of pages.
CanvasRenderingContext2D  // Not a "2D".
RuleFontFaceCss           // Not a CSS.

非布尔型的属性或变量,用名词短语来命名

好的命名:

list.length
context.lineWidth
quest.rampagingSwampBeast

差的命名:

list.deleteItems

boolean 属性或变量,用非命令式动词短语

boolean 变量经常被用在控制流的条件中,所以用动词短语可读性好于形容词。比较下这两者:

if (window.closeable) ...  // Adjective.
if (window.canClose) ...   // Verb.

非命令式动词短语(non-imperative verb phrase)有几种:

  • "to be" 形式:isEnabled, wasShown, willFire
  • 助动词hasElements, canClose, shouldConsume, mustSave

非命令式动词短语,它从语义上不改变任何东西,因此适合作为属性的命名,因为访问一个 boolean 变量也不改变任何东西。

好的命名:

isEmpty
hasElements
canClose
closesWindow
canShowPopup
hasShownPopup

差的命名:

empty         // Adjective or verb?
withElements  // Sounds like it might hold elements.
closeable     // Sounds like an interface.
              // "canClose" reads better as a sentence.
closingWindow // Returns a bool or a window?
showPopup     // Sounds like it shows the popup.

当函数参数为 boolean 时,省略掉动词

这个修订了上一条建议。boolean 作为参数时,往往是比较直观的,省略掉动词会简练一些:

Isolate.spawn(entryPoint, message, paused: false);
var copy = List.from(elements, growable: true);
var regExp = RegExp(pattern, caseSensitive: false);

用「正向」形式来表达 boolean 属性或变量

好的例子:

if (socket.isConnected && database.hasData) {
  socket.write(database.read());
}

差的例子:

if (!socket.isDisconnected && !database.isEmpty) {
  socket.write(database.read());
}

例外:有些场景下,反向形式是最常被使用的(比如有时候关注反向多于正向),此时用反向更佳。

用于返回数值的函数命名

使用名词短语:

var element = list.elementAt(3);
var first = list.firstWhere(test);
var char = string.codeUnitAt(4);

避免函数命名为 getXXX

如果函数不带参数,它的作用类似于访问一个属性,可以设置一个 getter。比如 getBreakfastOrder() 变为 breakfastOrder 属性。

如果函数需要带参数、或者有副作用等导致它不能被定义成一个 getter,可以选择:

  • 去掉 get,使用名词短语,比如 breakfastOrder()
  • 使用更精确的动词,如 create, download, fetch, calculate, request, aggregate

生成格式字符串

比如你想动态生成一个 Redis key:

def get_session_key(session_id):
    return f"session_{session_id}"

这个函数命名中的 get 会使其含意混淆不清,直觉会认为是从远程接口获取的。好的命名应该叫 make_session_key。这个命名参考了 django-redis 项目的某段 代码