Glean 拾遗
Daily /2026-09-23 / Long Names Are Long

Long Names Are Long

Source journal.stuffwithstuff.com Glean’d 2026-09-23 06:00 Read 9 min
AI summary

Working on Dart at Google, Bob Nystrom sits on the second layer of code review: the "readability" pass that checks style, idioms and documentation rather than behavior. What he sees there is identifiers that are far too long. Names can be too short, but the pendulum has swung — names over 60 characters dwarf the operations performed on them, force line breaks, and push authors toward nested expressions instead of locals. His four guidelines: drop words the type already implies (nameString → name, holidayDateList → holidays); drop words that don't disambiguate, tested by asking whether the name still means the same thing without them; drop words the surrounding class or method already supplies (AnnualHolidaySale.promote, not promoteHolidaySale); and drop filler like manager, data, state or engine. A deliberately awful waffle example is trimmed step by step from DeliciousBelgianWaffleObject down to Waffle.garnish.

Original · 9 min
journal.stuffwithstuff.com ↗
§ 1

One smart thing Google does is rigorous code reviews. Every change, before you can land it, gets reviewed in at least two ways. First, someone on the team does a normal review to make sure the code does what it’s supposed to.

But, then, there’s a second layer of review called readability. It makes sure the code is, well, readable: Is it easy to understand and maintain? Does it follow the style and idioms of the language? Is it well-documented?

谷歌做的一件聪明事是严格的代码评审。每次改动在合入之前,至少会经过两种评审。首先,团队里的某个人会做常规评审,确保代码确实实现了预期的功能。

但之后还有第二层评审,叫作 readability(可读性)。它要确保代码——嗯——可读:容易理解和维护吗?遵循语言的风格和惯用法吗?文档写得好吗?

§ 2

Dart usage inside Google is cranking up, so I’ve been doing a ton of these kind of code reviews. As a language designer, it’s fascinating. I get a firsthand view into how people use Dart, which is really useful for evolving the language. I have a clearer picture of which mistakes are common and which features are heavily used. I feel like an ethnographer journaling the lives of natives.

Google 内部 Dart 的使用量正在快速上升,所以这类代码评审我做了很多。作为语言设计者,这非常有意思。我能直接看到人们如何使用 Dart,这对语言演进很有用。我更清楚哪些错误常见、哪些特性被大量使用。我感觉自己像一位记录原住民生活的民族志学者。

§ 3

But, anyway, that’s not what this is about. Heck, it’s not even about Dart. What I want to talk about is something I see in a lot of code that drives me up the wall: identifiers that are too damn long.

不过,这不是本文要谈的内容。见鬼,甚至连 Dart 都不是。我想谈的是我在很多代码里看到、让我抓狂的一件事:标识符长得要命。

§ 4

Yes, names can be too short. Back when C only required external identifiers to be unique up to the first six characters; auto-complete hadn’t been invented; and every keypress had to be made uphill, in the snow, both ways; it was a problem. I’m glad we now live in a futuristic utopia where keyboard farts like p, idxcrpm, and x3 are rare.

But the pendulum has swung too far in the other direction. We shouldn’t be Hemingway, but we don’t need to be Tennessee Williams either. Very long names also hurt the clarity of the code where they are used. Giant identifiers dwarf the operations you’re performing on them, are hard to visually scan, and force extra line breaks which interrupt the flow of the code.

Long class names discourage users from declaring variables of that type, leading to massive, gnarly nested expressions instead of hoisting things out to locals. Long method names obscure their equally important argument lists. Long variables are annoying to use repeatedly, leading to sprawling method chains or cascades.

没错,名字可以太短。当年 C 只要求外部标识符在前六个字符内唯一;自动补全还没发明;每次按键都得在雪地里、上坡、来回走两趟——那时确实是个问题。我很高兴我们如今生活在一个未来主义乌托邦里,像 p、idxcrpm、x3 这种键盘随手糊出来的名字已经很少见了。

但钟摆已经朝另一个方向荡得太远了。我们不该做海明威,但也不必做田纳西·威廉斯。非常长的名字同样会损害使用它们的代码的清晰度。巨大的标识符会让针对它执行的操作相形见绌,难以用眼睛扫描,还会迫使代码换行,打断阅读流。

很长的类名会让使用者不愿意声明该类型的变量,结果写出庞大、扭曲的嵌套表达式,而不是把东西提升到局部变量。很长的方法名会掩盖同样重要的参数列表。很长的变量反复使用起来很烦,于是导致漫无边际的方法链或级联调用。

§ 5

I’ve seen identifiers over 60 characters long. You could fit a haiku or a koan in there (and likely enlighten the reader more than the actual chosen name did). Fear not, I am here to help.

Choosing a good name#choosing-a-good-name

A name has two goals:

It needs to be clear: you need to know what the name refers to.

It needs to be precise: you need to know what it does not refer to.

After a name has accomplished those goals, any additional characters are dead weight. Here’s some guidelines I use when I names things in my code:

我见过超过 60 个字符的标识符。这里面能塞下一首俳句或一则公案(而且很可能比真正选的那个名字更能启发读者)。别怕,我来帮你。

选个好名字#choosing-a-good-name

一个名字有两个目标:

它必须清晰:你得知道这个名字指代什么。

它必须精确:你得知道它不指代什么。

一旦名字达成这两个目标,再多出来的字符就是累赘。以下是我在代码里命名时用的一些准则:

§ 6
  1. Omit words that are obvious given a variable’s or parameter’s type#1-omit-words-that-are-obvious-given-a-variables-or-parameters-type

If your language has a static type system, users usually know the type of a variable. Methods tend to be short, so even when looking at local variable whose type was inferred, or in a code review or some place where static analysis isn’t available, it rarely takes more than scanning a few lines to tell what type a variable has.

Given that, it’s redundant to put the type in the variable’s name. We have rightfully abandoned Hungarian notation. Let it go.

// Bad: String nameString; DockableModelessWindow dockableModelessWindow;

// Better: String name; DockableModelessWindow window;

In particular, for collections, it’s almost always better to just use a plural noun describing the contents instead of a singular noun describing the collection. If the reader cares more about what’s in the collection, the name should reflect that.

// Bad: List<DateTime> holidayDateList; Map<Employee, Role> employeeRoleHashMap;

// Better: List<DateTime> holidays; Map<Employee, Role> employeeRoles;

This also applies to method names. The method name doesn’t need to describe its parameters or their types—the parameter list does that for you.

// Bad: mergeTableCells(List<TableCell> cells) sortEventsUsingComparator(List<Event> events, Comparator<Event> comparator)

// Better: merge(List<TableCell> cells) sort(List<Event> events, Comparator<Event> comparator)

This tends to make callsites read better:

mergeTableCells(tableCells); sortEventsUsingComparator(events, comparator);

Is it just me, or is there an echo echo in here here?

  1. 省略类型已经说明的词语#1-omit-words-that-are-obvious-given-a-variables-or-parameters-type

如果你的语言有静态类型系统,使用者通常知道变量的类型。方法往往很短,所以即使在看一个类型被推断出来的局部变量,或者在做代码评审、没有静态分析可用时,通常也只需扫几行就能看出变量是什么类型。

既然如此,把类型放进变量名就是多余的。我们已经正当地抛弃了匈牙利命名法。让它去吧。

// Bad: String nameString; DockableModelessWindow dockableModelessWindow;

// Better: String name; DockableModelessWindow window;

特别是对集合来说,几乎总是更好的做法是用描述内容的复数名词,而不是描述集合的单数名词。如果读者更关心集合里装的是什么,名字就应该反映这一点。

// Bad: List<DateTime> holidayDateList; Map<Employee, Role> employeeRoleHashMap;

// Better: List<DateTime> holidays; Map<Employee, Role> employeeRoles;

这条也适用于方法名。方法名不需要描述它的参数或参数类型——参数列表已经替你做这件事了。

// Bad: mergeTableCells(List<TableCell> cells) sortEventsUsingComparator(List<Event> events, Comparator<Event> comparator)

// Better: merge(List<TableCell> cells) sort(List<Event> events, Comparator<Event> comparator)

这往往让调用点读起来更好:

mergeTableCells(tableCells); sortEventsUsingComparator(events, comparator);

只有我觉得这里回声 echo echo 吗?

§ 7
  1. Omit words that don’t disambiguate the name#2-omit-words-that-dont-disambiguate-the-name

Some people tend to cram everything they know about something into its name. Remember, the name is an identifier: it points you to where it’s defined. It’s not an exhaustive catalog of everything the reader could want to know about the object. The definition does that. The name just gets them there.

When I see an identifier like recentlyUpdatedAnnualSalesBid, I ask:

Are there updated annual sales bids that aren’t recent?

Are there recent annual sales bids that were not updated?

Are there recently updated sales bids that aren’t annual?

Are there recently updated annual bids not related to sales?

Are there recently updated annual sales things that are not bids?

A “no” for any of these usually points to an extraneous word.

// Bad: finalBattleMostDangerousBossMonster; weaklingFirstEncounterMonster;

// Better: boss; firstMonster;

Of course, you can go too far. Shortening that first example to bid might be a little too vague. But, when in doubt, leave it out. You can always add qualifiers later if the name proves to cause a collision or be imprecise but it’s unlikely you’ll come back later to trim the fat.

  1. 省略不能让名字更明确的词语#2-omit-words-that-dont-disambiguate-the-name

有些人喜欢把自己知道的关于某事物的一切都塞进名字里。记住,名字是标识符:它把你指向定义所在的地方。它不是一份详尽目录,列出读者可能想知道的关于对象的一切。定义才负责那个。名字只负责把读者带到定义那里。

当我看到像 recentlyUpdatedAnnualSalesBid 这样的标识符时,我会问:

有更新的年度销售出价,但不算最近的吗?

有最近的年度销售出价,但没有更新吗?

有最近更新的销售出价,但不是年度的吗?

有最近更新的年度出价,但与销售无关吗?

有最近更新的年度销售事物,但不是出价吗?

其中任何一个回答“否”,通常就指向一个多余的词。

// Bad: finalBattleMostDangerousBossMonster; weaklingFirstEncounterMonster;

// Better: boss; firstMonster;

当然,你也可能做过头。把第一个例子缩短成 bid 也许有点太含糊。但是,拿不准时,就删掉它。如果这个名字后来被证明会冲突或不精确,你随时可以再加限定词;但你不太可能日后回来给名字瘦身。

§ 8
  1. Omit words that are known from the surrounding context#3-omit-words-that-are-known-from-the-surrounding-context

I can use “I” in this paragraph because you can see this post is by Bob Nystrom. My dumb face is right up there. I don’t need to keep saying “Bob Nystrom” everywhere here (despite Bob Nystrom’s temptation to aggrandize Bob Nystrom by doing so). Code works the same way. A method or field occurs in the context of a class. A variable occurs in the context of a method. Take that context for granted and don’t repeat it.

// Bad: class AnnualHolidaySale { int _annualSaleRebate; void promoteHolidaySale() { ... } }

// Better: class AnnualHolidaySale { int _rebate; void promote() { ... } }

In practice, this means that the more deeply nested a name is, the more surrounding context it has. That in turn means it usually has a shorter name. The effect is that identifiers with shorter scopes have shorter names.

  1. 省略从周围语境就能知道的词语#3-omit-words-that-are-known-from-the-surrounding-context

我可以在这段里用“我”,因为你能看到这篇文章的作者是 Bob Nystrom。我那张蠢脸就在上面。我不需要在这里到处反复说“Bob Nystrom”(尽管 Bob Nystrom 很想这么做来抬高 Bob Nystrom)。代码同理。方法或字段出现在类的语境里。变量出现在方法的语境里。把这种语境视为理所当然,别重复它。

// Bad: class AnnualHolidaySale { int _annualSaleRebate; void promoteHolidaySale() { ... } }

// Better: class AnnualHolidaySale { int _rebate; void promote() { ... } }

在实践中,这意味着名字嵌套得越深,它拥有的周围语境就越多。这反过来意味着它通常名字更短。结果是:作用域越短的标识符,名字越短。

§ 9
  1. Omit words that don’t mean much of anything#4-omit-words-that-dont-mean-much-of-anything

I used to see this a lot in the game industry. Some people succumb to the temptation to inflate their identifiers by adding Serious Business sounding words. I guess it makes their code feel more important and, by extension, makes them feel more important.

In many cases, the words carry no meaningful information. They’re just fluff or jargon. Usual suspects include: data, state, amount, value, manager, engine, object, entity, and instance.

A good name paints a picture in the mind of the reader. Calling something a “manager” doesn’t convey any image to the reader about what the thing does. Does it do performance evaluations? Lean over your cubicle and ask for TPS reports?

Ask yourself “Would this identifier mean the same thing if I removed the word?” If so, the word doesn’t carry its weight. Vote if off the island.

  1. 省略没什么含义的词语#4-omit-words-that-dont-mean-much-of-anything

我以前在游戏行业经常看到这种情况。有些人抵挡不住诱惑,给标识符加上听起来很“正经业务”的词,把它吹大。我猜这能让他们的代码显得更重要,进而让他们自己显得更重要。

很多情况下,这些词不携带任何有意义的信息。它们只是废话或行话。常见的嫌疑词包括:data、state、amount、value、manager、engine、object、entity 和 instance。

好名字会在读者脑海中画出一幅画。把某个东西叫作“manager”,并不能让读者对它的作用产生任何画面。它负责绩效考核吗?还是探过隔间来要 TPS 报告?

问自己:“如果我把这个词去掉,这个标识符的意思还一样吗?”如果一样,那这个词就没有承担自己的重量。投票把它赶下岛。

§ 10

Applying the guidelines… to waffles#applying-the-guidelines-to-waffles

To give you a feel for how these rules work in practice, here’s an example that breaks all of these rules. This contrived example is tragically close to real code I’ve seen in reviews:

class DeliciousBelgianWaffleObject { void garnishDeliciousBelgianWaffleWithStrawberryList( List<Strawberry> strawberryList) { ... } }

We know from the type that it takes a list of strawberries (#1), so let’s cut that out:

class DeliciousBelgianWaffleObject { void garnishDeliciousBelgianWaffle( List<Strawberry> strawberries) { ... } }

Unless our program has foul-tasting Belgian waffles, or waffles of other nationalities, we can drop those adjectives (#2):

class WaffleObject { void garnishWaffle(List<Strawberry> strawberries) { ... } }

The method is inside a WaffleObject, so we know what it’s going to garnish (#3):

class WaffleObject { void garnish(List<Strawberry> strawberries) { ... } }

Obviously it’s an object. Everything is an object. That’s kind of what “object-oriented” means (#4):

class Waffle { void garnish(List<Strawberry> strawberries) { ... } }

There, much better.

把准则用到……华夫饼上#applying-the-guidelines-to-waffles

为了让你感受这些规则在实践中如何运作,这里有一个违反所有规则的例子。这个刻意构造的例子,悲剧性地接近我在评审中见过的真实代码:

class DeliciousBelgianWaffleObject { void garnishDeliciousBelgianWaffleWithStrawberryList( List<Strawberry> strawberryList) { ... } }

我们从类型知道它接收一串草莓(#1),所以把它删掉:

class DeliciousBelgianWaffleObject { void garnishDeliciousBelgianWaffle( List<Strawberry> strawberries) { ... } }

除非我们的程序里有难吃的比利时华夫饼,或者其他国家的华夫饼,否则可以去掉那些形容词(#2):

class WaffleObject { void garnishWaffle(List<Strawberry> strawberries) { ... } }

这个方法在 WaffleObject 里面,所以我们知道它要装饰的是什么(#3):

class WaffleObject { void garnish(List<Strawberry> strawberries) { ... } }

显然它是个对象。一切都是对象。这差不多就是“面向对象”的意思(#4):

class Waffle { void garnish(List<Strawberry> strawberries) { ... } }

好了,好多了。

§ 11

I think these are pretty simple guidelines. You may think it’s pointless to worry about this stuff, but I believe that naming things is one of the most fundamental tasks we do when programming. Names are the structure we impose on the formless sea of bits that is computing.

我觉得这些准则相当简单。你可能觉得担心这些东西没意义,但我相信命名是编程时我们做的最基础的任务之一。名字是我们强加给计算这片无定形比特之海的结构。

Open source ↗