资讯动态

命名规范深度解析:驼峰、帕斯卡、匈牙利、下划线一次讲透

发布时间:2026/10/19 9:32:27 来源:尧图企业网站定制
我自己在这块吃过不少亏所以今天这篇想把驼峰命名法、帕斯卡命名法、匈牙利命名法、下划线命名法这四种最常见的规则一次讲透。不光讲它们长什么样更想聊聊它们各自解决什么问题、在什么场景下选型、以及混用时会踩到哪些坑。适合刚入门的新手系统建立起命名认知也适合写了两三年代码但从来没认真梳理过命名规范的开发者。1. 命名这件事为什么值得专门花时间去学先说我自己的经历。有段时间我在维护一个老系统里面同一个业务字段在数据库里叫create_time在后端 Java 代码里叫createTime传到前端 JavaScript 又变成了creationTimestamp。三套名字描述的是同一个东西。后来要做一个数据对账功能我需要在三个端之间来回核对字段肉眼比对到怀疑人生最后还因为一个字段名映射错位导致线上报表数据差了整整一天。那次之后我就意识到命名规范不是一个审美问题而是一个实打实的工程问题。1.1 命名本质上是分词策略和语义标注如果你把四种命名法放在一起看会发现它们核心都在做两件事。第一件事是分词。一段连续的字符比如userlogininfo如果没有空格人脑很难快速识别出user、login、info这三个单词。四种命名法本质上是四种不同的分词策略用小写字母和大写字母的交替来分词就是驼峰和帕斯卡用下划线来分词就是下划线命名法用一组特定的前缀字符来分词就是匈牙利命名法。第二件事是语义标注。名字不仅要让人知道有哪些词还要让人知道这个词是什么角色。比如isActive里的is告诉你这是个布尔值maxSize里的max告诉你这是个上限值_count前面的下划线告诉你这是一个内部私有状态。这些前缀、后缀、特殊符号都是在给阅读者传递额外的语义信息。理解了这个底层逻辑你就不会再去纠结到底哪种命名法是最好的而是会想当前这个语言、这个场景更适合哪一种分词和标注策略。1.2 为什么我建议把命名规范当成团队沟通协议来看待一个团队动辄几十人代码一写就是好几年。今天你写的变量明天可能由另一个完全不认识的人来维护。如果每个人的命名风格都随心情变化那整个代码库就相当于一本没有统一排版的书——每一章的格式都不一样读者每翻一章都要重新适应。反过来如果大家都遵循同一套命名协议那代码就成了一本排版一致的文档看到PascalCase就知道是类或组件看到camelCase就知道是变量或函数看到snake_case就知道是数据字段或配置项。这种看到形式就知道含义的预期一致性才是命名规范真正的价值。2. 四种命名法的核心写法、适用范围与典型误区介绍之前先声明一下我对各种命名法的态度它们没有绝对的高下之分只有适合的场景和不适合的场景之分。下面逐个拆解。2.1 驼峰命名法camelCase驼峰命名法的规则是第一个单词首字母小写后续每个单词首字母大写单词之间没有空格也没有下划线。示例userName、getOrderList、isVisible。这是我最常用的命名法主要出现在 JavaScript、Java、TypeScript 这类语言的变量名、函数名、方法名上。为什么变量和函数偏爱它因为小写开头传达了一个信息这是个具体的事物或动作而不是一个类型或模板。举个对比userProfile是一个具体的用户资料对象而UserProfile是一个用户资料类前者是个体、后者是模板一眼就能分开。驼峰命名法有两条实践约定值得特别注意函数名一般用动词或动词短语开头getData()、setValue()、handleClick()、runTask()。这个习惯能让你在阅读代码时第一时间知道这行代码是在做什么动作而不是在描述什么东西。布尔变量名用is、has、can、should这类词开头isLoading、hasPermission、canSubmit、shouldRetry。这样if (isLoading)读起来就像一句自然语言你不需要去查这个变量的类型定义就能猜出它的值是 true 还是 false。误区方面我见过不少人把驼峰命名的首字母大写写成UserName这样的形式。严格来说这就不是驼峰而是帕斯卡了。在 Java 里如果你把局部变量命名为UserName语法上没错但团队规范上通常会被 code review 打回因为读者会下意识把它当成一个类名。2.2 帕斯卡命名法PascalCase帕斯卡命名法和驼峰几乎一样唯一区别是第一个单词的首字母也大写。示例UserProfile、OrderService、PaymentController。它在 Java、C#、C 里通常用于类名、接口名、枚举名、组件名。为什么类型要跟变量在形式上做出区分核心原因是面向对象语言里类是模板、对象是实例。如果类和对象都长一个样那user new user()这种代码到底谁是类谁是实例就很容易混淆。帕斯卡命名法用全大写开头来标记模板驼峰命名法用小写开头来标记实例两者配合使用阅读效率是最高的。在 TypeScript 和 React 里组件名也沿用帕斯卡命名法比如UserCard、OrderTable。这不是偶然而是 JSX 语法的一个硬性约定React 规定小写开头的标签会被当成原生 HTML 元素大写开头的标签才会被当成自定义组件。如果你把组件命名为userCard写userCard /的时候 React 会去找一个叫userCard的 HTML 标签然后就找不到了。帕斯卡命名法一个比较常见的争论点是缩略词的处理。比如ID这个词有人写成UserId有人写成UserID还有人写成UserId中间带奇怪的大小写混排。我的建议是把它当普通单词处理写成UserId、OrderId而不是UserID。因为全大写的ID夹在单词中间会破坏分词的可读性而且很多语言规范比如微软的 .NET 命名指南也明确建议这样处理。2.3 下划线命名法snake_case下划线命名法的规则是所有字母小写单词之间用下划线分隔。示例user_name、get_order_list、is_visible。它在 Python、Ruby 这类语言中是官方推荐的变量和函数命名方式也是数据库字段、配置文件、环境变量里的主流风格。为什么数据库和配置文件偏爱下划线原因有两个一是数据库系统很多是对大小写不敏感的如果字段叫userName在不同的数据库迁移工具、不同的操作系统下可能解析结果不一致而全小写下划线方案稳定得多二是下划线天然就是分词符比大小写交替在视觉上更直接尤其适合字段名比较长的场景比如customer_shipping_address_line_1展开成一串也能很清楚地看出层次。Python 里下划线命名法还有一个变体双下划线前缀比如__private_var。这是 Python 里表示类内部私有成员的约定解释器会做名字修饰。这个机制很多人写过我不再展开只需要记住一点单下划线前缀_var表示我建议你别动它双下划线前缀__var表示类不想让你轻易动它。这在 Java 和 TypeScript 里也有类似约定通常用_前缀表示私有属性。下划线命名法最容易被诟病的地方是丑、不够简洁。确实get_user_order_detail比getUserOrderDetail更占空间。但对 Python 社区来说可读性优先于简洁性他们认为user_name的阅读速度高于userName——因为下划线把单词边界画得清清楚楚不需要人眼去识别大小写切换。这个争议没有标准答案跟随你所在语言的主流约定就好。2.4 三种主流命名法之间的关系我做了张对照表命名法示例分词方式常见语言/场景典型用途优点缺点驼峰命名法userProfile、getOrder大小写交替Java、JS、TS 的变量和函数变量、函数、方法名简洁、不占额外字符单词边界靠大小写识别长名字时易眼花帕斯卡命名法UserProfile、OrderService大小写交替首个大写Java、C#、TS 的类、React 组件类名、接口名、组件名与实例命名形成清晰区分和驼峰容易记混下划线命名法user_profile、get_order下划线分隔Python、Ruby、数据库、配置文件变量、函数、字段名、环境变量单词边界最清晰、跨系统稳定名字偏长、打字多按几次下划线这个表建议你收藏。但有一点我必须强调语言规范不是死的。比如 JavaScript 和 Java 也有允许常量用全大写下划线的约定MAX_RETRY_COUNT、DEFAULT_PAGE_SIZE这其实是把下划线命名法的一个变体用在了常量场景。又比如 Rust 里的函数推荐用小写加下划线但结构体struct推荐用帕斯卡。所以最靠谱的方式是学一门语言时先去看它的官方风格指南而不是套用你上一门语言的习惯。3. 匈牙利命名法被误解的那些事今天还有没有必要学匈牙利命名法大概是被误解得最深的一种命名法了。现在很多新手接触到的版本是给变量加类型前缀比如strName表示字符串、iCount表示整数、bFlag表示布尔值。然后网上就会有很多文章告诉你这是老古董现代语言有类型系统根本不需要这种前缀。这个说法对了一半但它忽略了一个关键事实匈牙利命名法的原始版本根本不是用来标注类型的。3.1 原始版本用前缀表达用途语义而不是数据类型匈牙利命名法源自一位匈牙利裔工程师的设计最早用在某种系统编程语言的环境里。它的核心思想不是加个类型缩写而是用前缀告诉阅读者这个变量的用途或属性是什么。举个例子m_前缀表示成员变量member看到它就知道这不是局部变量而是对象内部的状态。cch表示字符计数cb表示字节计数。这两个都是计数但语义不同cch统计的是字符个数cb统计的是字节个数。在多字节编码时代这两个值差很多如果搞混了就会出现缓冲区长度错误。p前缀表示指针h前缀表示句柄sz表示以空字符结尾的字符串。看出区别了吗cch不是说这个变量是 int 类型——它描述的是这个数字代表什么含义。这类信息是编译器不知道的类型系统也没法替你检查只有靠命名来传递。这就是应用型匈牙利命名法的价值所在它补充的是编译器看不到的语义信息而不是重复编译器已经知道的类型信息。3.2 为什么后来变成了类型前缀的怪胎事情坏在它的推广过程。后来的 Windows 开发团队在整理内部编码规范时把一部分前缀理解成了标志类型的写法然后这套被简化和误读的版本随着大量 Windows 代码、教材流传开来。于是我们就看到int iCount、string strName这种命名——前缀告诉你这是 int、这是 string而这些信息在强类型语言里根本不需要占一个位置。这就是备受诟病的系统型匈牙利命名法。为什么会变成这样我猜和当时的编辑器有关。那个年代没有现代 IDE没有类型推断悬停提示看代码时确实需要一种捷径来快速判断变量的类型。但这个方案放到今天在 Java、C#、TypeScript 这类静态类型语言里等于是把已经在类型定义里写明的东西又重复了一遍白白增加阅读负担。而且重复是最容易出错的——类型改了前缀没改代码就变成了写着str的数字反而误导后人。3.3 今天还能从匈牙利命名法里学什么我的观点是别整套照搬类型前缀但要继承用前缀表达语义的思路。有几个现代编程里仍然非常有用的做法其实就是匈牙利命名法的嫡系后代私有成员用_前缀TypeScript、Python、Java 的私有属性都习惯这么干看到下划线就知道内部实现细节外部不要碰。常量用业务前缀比如所有接口路径常量放在一个API_前缀的命名空间里所有错误码常量用ERR_前缀这样在用的时候API_和ERR_本身就是一种快速分类。区分同类型但不同语义的变量比如offset和limit都是数字但一个是偏移量、一个是每页大小。如果你愿意可以命名为nOffset和nLimit至少在参数列表里能一眼分辨。当然更现代的做法可能是直接把它们放入一个结构体或配置对象里这就不需要靠前缀了。所以对匈牙利命名法的正确态度是它提出了一种很好的思路——命名要携带语义信息但具体携带什么、用什么前缀要跟着时代走。现代语言把类型已经管好了你就别再让命名去重复类型把精力放在业务含义生命周期可见性这些类型系统管不到的地方才是真正把命名做好的方向。4. 跨语言、跨团队协作时的命名冲突怎么统一单看一门语言的规范其实问题不大。麻烦的是一个业务系统通常由多个端的代码组成——数据库一套命名、后端一套、前端一套、数据同步脚本又一套。你单独看哪一段都挺规范拼到一起就变成了四套标准描述同一个业务实体。这一节我要讲的就是这个场景。4.1 三个最容易出问题的协作场景第一个场景是Python 后端 TypeScript 前端。后端按 PEP8 用snake_case返回user_name前端组件里按 JS 习惯用userName然后你不得不在每个接口的 mapper 层来回转换。这不是谁对谁错而是两种语言的社区规范冲突。处理不好整个项目就充满了user_name和userName并存的割裂感。第二个场景是数据库字段与 ORM 模型。数据库里是created_at、updated_at但很多 ORM 默认会把created_at映射成对象的created_at如果保持下划线或者映射成createdAt如果开启驼峰转换。如果团队没约定清楚就会发生数据库是下划线、ORM 实体是驼峰、手写 SQL 又回到下划线的三层混乱。一旦代码里出现用createdAt拼接 SQL 的情况线上直接报字段不存在。第三个场景是微服务之间的消息契约。上游服务发消息时字段叫orderId下游服务接收后解析成order_id中间没有任何自动转换机制。结果就是每个消费方都要写一段手动对应字段的胶水代码要是有 20 个字段这就是妥妥的 20 行隐患。4.2 我把这类冲突总结成了三条设计原则第一条在契约边界上定死一套规范内部允许各自语言习惯。比如服务间传 JSON 时统一规定用snake_case因为大部分语言解析snake_case不受影响而且 JSON 本身就是数据格式靠近数据层语法。到 JS 内部再转成camelCase这个转换集中在唯一的 mapper 层。定下这个约定之后任何人看到跨服务传过来的字段第一反应就是哦这个是数据契约用下划线内部变量再随便用驼峰互不干扰。第二条分界处转换不做半吊子混合。最怕出现的是函数内部一会儿用userName一会儿为了对接 ORM 又写user_name。这种混合不是灵活而是没有分层。正确做法是在接口层拿到数据的那一刻就完成命名规则转换之后内部业务代码只使用一种规则。把转换收敛到边界是控制命名混乱最有效的手段。第三条数据库字段长期稳定优先放弃看起来好看。数据库字段一旦上线迁移成本很高索引、视图、存储过程、历史数据全绑定在上面。所以数据库字段名应该选择跨语言兼容性最好的snake_case而不要在数据库里追求驼峰。你可以在 ORM 层做映射但是底层字段名保持稳定、保守、无歧义。4.3 我平时会用的字段命名检查清单如果你跟我一样经常在多个端之间设计接口可以参考这份清单在写接口文档之前就逐项过一遍所有跨服务字段是否都统一为同一种命名风格是否存在同一字段在两处不同顺序的写法orderId与order_id混用布尔字段是否统一用is_、has_、can_这类前缀比如is_paid和is_published一眼可读。时间字段是否统一通用了时区信息created_at和created_at_tz要区分清楚否则跨时区解析完数据对不上。ID 类字段是否有歧义比如order_id是业务单号order_row_id是明细行号两者必须有明显区隔。缩略词是否存在多种写法比如用户 ID 究竟是user_id、userid还是userId缩略词必须写进团队字典里统一。这清单看起来琐碎但真出了线上对齐错误你排查的半小时可能就是因为某个字段名少了一个下划线。5. 让命名规范真正落地的三个手段光靠自觉是不够的我们约定好了大家以后都按这个规范写代码——这句话几乎每个团队都说过但三个月后看代码库大家又各写各的了。原因很简单人的注意力有限写完一行代码急着赶下一个功能谁还记得刚才那个布尔变量有没有加is前缀。所以让命名规范落地不能靠自觉要靠工具、文档和评审三板斧。5.1 第一板斧用 .editorconfig 与 Linter 把命名规则自动化现在主流语言都有 lint 工具自动检查命名风格。比如 ESLint 里有camelcase规则Python 的 ruff 和 flake8 会检查 PEP8 命名约定C# 有自己的.editorconfig命名规则配置Java 这边通过 Checkstyle 或 IDE 的 Inspection 也能做。我建议团队在项目根目录放一份统一的代码风格配置并接到 CI 里命名风格不对直接 CI 失败。配置时有几个容易忽略的点文件编码和换行符.editorconfig里统一utf-8、LF这是命名规范之外的卫生问题但会影响后续自动化工具的一致性。异常豁免比如对接第三方旧系统时某些字段名无法调整可以用 lint 的局部豁免注释但必须在注释里说明原因避免豁免滥用。文件的命名也要纳入检查项目文件、组件文件、模块文件通常也有命名约定比如 React 组件文件用帕斯卡UserCard.tsx配置文件用小写下划线build_config.ts或kebab-case风格这些都建议一并写入 CI。我见过一个很实用的操作把命名检查直接写进 Git 提交钩子或 CI 流水线里。这样代码根本到不了 code review 阶段就能把低级命名错误先拦下一大半。5.2 第二板斧维护一份团队命名约定文档越具体越好不要写那种成员变量用驼峰命名的废话要写一份能查字典的手册。具体来说应该包含三张表第一张是通用词表把业务里最容易混的词汇固定下来。比如订单统一用order明细统一用line_item总额统一用total_amount而不是一会儿amount一会儿sum一会儿total。用词不稳定是最隐蔽的命名混乱。第二张是缩写表凡是出现缩略语的地方必须有唯一解释。比如msg代表 messagereq代表 requestcb代表 callback。没有这个表后来的人看到resp_data只能靠猜猜错了就是 bug。第三张是前后缀约定表事件处理器统一用handle前缀工具函数统一用format、parse、convert这类动词前缀服务类统一Service仓储类统一Repository。这是把之前讲的命名约定固化成团队自己的 API。5.3 第三板斧把命名当成 Code Review 里的一等议题代码评审时很多团队重点看逻辑正确性但命名审查往往流于这也行吧。我建议在评审清单里单列一条命名是否传递了准确语义具体看三个问题这个名字读起来像一句自然语言吗比如if (isUserLoggedIn hasOrderPermission)就明显比if (a b)好读。这个名字会不会让人误解数据形态比如变量叫userList但实际是个对象或者叫user但实际是个数组这类名不副实最危险。这个名字和相邻代码的命名风格是否一致如果周围都是userName你新写的user_name无论在拼写还是语义上都很可能误导后人。评审这件事我体会最深的是提出命名问题时要给一个替代方案。只说这个名字不好对方大概率不知道怎么改但你说要不要改成retryCount因为这里表达的是次数而不是开关对方立刻就能明白你的思路。最后说一点个人体会。命名规范这件事新人总觉得是老油条吹毛求疵但经历过几年几十万行代码的维护之后你会越来越确信代码是写给人看的顺便给机器执行。一个清晰的名字省掉的不仅是查找替换的时间更是两次沟通之间的不确定性。我也是踩过好几个雷之后才慢慢琢磨出这套方法的。如果你现在正为到底该用哪种命名法纠结我的建议很简单先跟主流、定约定、上工具剩下的——等你把代码写多了自然就会形成自己的手感。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑