代码之丑
郑晔
开源项目 Moco 作者
19833 人已学习
新⼈⾸单¥59
登录后,你可以任选2讲全文学习
课程目录
已完结/共 24 讲
代码之丑
15
15
1.0x
00:00/00:00
登录|注册

01 | 缺乏业务含义的命名:如何精准命名?

你好,我是郑晔。
讲写代码的书通常都会从命名开始讲,《程序设计实践》如此,《代码整洁之道》亦然。所以,我们这个讲代码坏味道的专栏,也遵循传统,从命名开始讲。
不过,也许你会说:“我知道,命名不就是不能用 abcxyz 命名,名字要有意义嘛,这有什么好讲的。”然而,即便懂得了名字要有意义这个道理,很多程序员依然无法从命名的泥潭中挣脱出来。

不精准的命名

我们先来看一段代码:
public void processChapter(long chapterId) {
Chapter chapter = this.repository.findByChapterId(chapterId);
if (chapter == null) {
throw new IllegalArgumentException("Unknown chapter [" + chapterId + "]");
}
chapter.setTranslationState(TranslationState.TRANSLATING);
this.repository.save(chapter);
}
这是一段看上去还挺正常的代码,甚至以很多团队的标准来看,这段代码写得还不错。但如果我问你,这段代码是做什么的。你就需要调动全部注意力,去认真阅读这段代码,找出其中的逻辑。经过阅读我们发现,这段代码做的就是把一个章节的翻译状态改成翻译中。
问题来了,为什么你需要阅读这段代码的细节,才能知道这段代码是做什么的?
问题就出在函数名上。这个函数的名字叫 processChapter(处理章节),这个函数确实是在处理章节,但是,这个名字太过宽泛。如果说“将章节的翻译状态改成翻译中”叫做处理章节,那么“将章节的翻译状态改成翻译完”是不是也叫处理章节呢?“修改章节内容”是不是也叫处理章节呢?换句话说,如果各种场景都能够叫处理章节,那么处理章节就是一个过于宽泛的名字,没有错,但不精准。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

文章总结:通过深入探讨命名在编程中的重要性,本文强调了良好命名对代码质量和可维护性的关键作用。首先,指出了命名过于宽泛和使用技术术语命名的问题,阐述了不精准的命名会导致代码理解困难的根源所在,提出了命名应该描述意图而非细节的观点。其次,强调了使用业务语言编写代码的重要性,以提高代码的可读性和可维护性。通过具体的代码示例,深入浅出地阐述了命名问题对代码质量的影响,为读者提供了实用的命名指导原则。整体而言,本文通过深入的技术讨论,为读者提供了对命名问题更深入的认识,强调了好的命名是体现业务含义的命名,对读者在编程实践中具有重要的指导意义。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《代码之丑》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(45)

  • 最新
  • 精选
  • Jxin
    1.实际工作时,去抓别人的命名规范其实挺不舒服的,显得自己爱计较,而且在缺少共同认知,一般人家也觉得你爱计较。 2.命名其实就是对抽象的定义。不能描述业务含义的命名往往是由于抽象的角度不正确或不明确引起的。设计建模时我们会说,业务驱动,认知先行。这里的认知先行就是要先建立与业务侧达成共识的模型(可以认为就是文中让产品看看能不能理解)。然后基于这个认知模型直接翻译成代码,不要扯什么实现和设计允许不一致,好的设计和实现应该就是一模一样的。这样翻译出来的代码,其行为和能力的定义(命名)自然是对应在业务特征上的。遗憾的是,大多数时候,在一个叫现实的东西面前,我不得不低下头,毕竟时间有限,测试支撑无力,在对项目没有足够认知之前,我们只能用最小的改动、最大的复用和差不多的命名去实现功能,设计和对齐认知的事情放到后面可能存在的重构上。(实现先行,设计随后)

    作者回复: 坚持做正确的事情有难度,不坚持却难以提升。

    2020-12-29
    3
    25
  • 刘大明
    老师提的命名不规范,在项目中全中。 还有项目总监写的这种代码 aaaaaa.updateFlight(airOrder, airOrderOld); 各种不规范命名。难受

    作者回复: aaaaa还是突破底线了。

    2020-12-28
    5
    25
  • Demon.Lee
    老师,xxxMap这种命名表示映射关系,比如:书id与书的映射关系,不能命名为bookIdMap么?一时没想到好的命名,老师能给点建议么

    作者回复: 按照我习惯的约定,Map 表示的是一个数据结构,而映射关系我会写成 Mapping。

    2020-12-30
    3
    16
  • 捞鱼的搬砖奇
    老师好,我又又又来了。 18年末,我看了你的10X 工作法专栏,里面有提到过“代码的坏味道”碰巧那时候我刚读完重构第一版,对你专栏的的观点非常认同,几个月之后重构出了第二版,一半是好奇,一半是自己对优秀代码的向往把书买回来读完了。几个月前我看完了软件设计之美。这样一想三年过去了,自己在代码量有了更多的积累,每次回过去看那些重构的原则,都会有新的体会,写的时候依旧会犯迷糊,一个查询方法,是用 listXX,getXX还是queryXX呢,光是思考这些我都会想好一会,还有就是有时候写的时候觉得合适的,之后等整个功能完成回去检查时又觉得这样不好了。动手之前想的更多了。 期待后面课程。

    作者回复: 欢迎回来! 进步都一点一点来的,没有谁一开始就很牛。

    2020-12-29
    5
    9
  • 布凡
    今日总结: 1、命名要能描述功能(或方法)所做的事情,要用具体的(动词+名称)比如AddChapter 2、一个好的名字应该描述意图,而非细节,比如, StartTranslation 3、不能用技术术语命名,因为接口时稳定的,而实现时易变的,比如不能用 bookList 这样的命名就不够好,而应该用books 4、实际代码中,技术名称的出现,比如redis 代表的就是具体的技术实现,而应该用cache这样更广泛的词,和第一点正好相反 5、保持团队代码的统一,建立团队的词汇表,并进行代码评审,保证项目命名的统一,也能更好的让业务知识在项目成员中传递

    作者回复: 很好的总结

    2021-02-09
    8
  • Gojustforfun
    唉,啥也白说了,都是眼泪啊..... 刚写代码时,老鸟通常会对菜鸟说教:你不要期望一次将代码写好,得注重健壮性(鲁棒性)、可读性、可维护性、可扩展性,多思考、常重构....多看书去看看《重构》《代码整洁之道》等等。然而你看他的提交记录除了改bug就没重构过!再看看他写的代码(后面举例),你会发现他推荐你看的书他其实没读完或者根本没读过!(类比于学算法让你看算法导论)当你再追问为什么不按书中/大厂规范做,他两手一滩说到不能教条要变通,脱离场景谈优化都是耍流氓——得按咱们团队规范写(其实没规范),我写的就符合规范!(我C,直接说照着你的代码风格写不就好了,非得套在一堆大道理凸显自己,事后分析起来仍旧是个笑话!其实,在大多数情况下,个体是无法对抗群体习惯的!) 1) 包名明明已经限定语义,赋值运算符右侧User后的后缀其实是可以省略。 左侧的变量名,在一般场景可以用dao/srv/repo表示,在聚合场景可能还得用userDao/chapterDao来区分。 UserDao userDao = dao.UserDao(); UserService userSrv = services.UserService(); UserRepository userRepo = repositories.UserRespository(); 这就完了?怎么可能!包名dao/model用单数而services和repositories用复数!对就是这么坑,这么任性! 2)对于缩略词的命名:userId还是userID?Isbn还是ISBN 3)我的理解,api、service、repository这几层通常是面向业务的,应该使用面向业务的命名;dao层的业务就是和具体数据源打交道,所以命名可以是UpdateXXXByID,希望老师针对软件的每个分层给点命名建议,谢谢!

    作者回复: 先对你的处境表示一下同情。 分层命名一般是团队的习惯,像我现在的团队,一般是用 resource/application/service/repository 来命名,实际上,这里的 application 对应着 DDD 中的应用服务,service 对应着领域服务,在很多团队里,这些都放到了 service 里面。 也有的团队 resource 叫 controller,repository 叫 mapper 或 dao。具体叫哪个,按照团队的约定就好。

    2020-12-29
    2
    8
  • huaweichen
    为了命名,和同事展开了很多争论: 原命名为$personsArray。 我的任务是重构。 我在重构过程中,我把变量换为Collection类型,变量名改为$persons。 同事给我review的建议:“应该把$persons改为$personCollection。1. 因为变量如之前的legacy代码的personArray,表明了这个变量的类型,所以,我们用$personCollection有助于其他人阅读和理解。 2. person的Collection可以是一个person为Collection,也可以是多个persons,于是这个变量不一定永远是复数persons。” 请问老师,怎么怼回去?感觉他们说得也有理啊…… 您的这些理论,有出处reference吗?

    作者回复: 当它把类型从 Array 改成 Collection,就需要改一次变量名,那以后同样的事情还是会发生的。 同样,这里的复数实际上也可以里面只有一个,这并不是问题。 你可以看一下我在文章结尾附上的资料,这是我在《10x 程序员工作法》关于命名的介绍。

    2020-12-30
    2
    5
  • adang
    进入程序员这个行业,第一个使用的框架就是Rails,Rails在很多地方做了很好的约定,例如:Controller名字要用复数,Model名字要用单数,相对应的数据库表名名字要用复数等。老师课程中举的变量名bookList的例子,在Rails中约定的命名就是books。 现在已经不再使用ROR了,但是在动手之前还是会认真思考,尤其是有多种方式可以选择,拿不准要采用哪种的时候会想,如果这种场景在Rails下会怎样处理,这个时候通常心里就有答案了。 现在研发团队成员命名随心所欲。数据库字段驼峰式与蛇形式混合双打;字段名单复数不分,如:表示操作人的字段名定义为people;一个修改账号状态的方法里还会有更新这个账号下关联的其它业务的代码;Example.Criteria c1, Example.Criteria c2 这样的命名更是随处可见。每次读代码都是苦不堪言。

    作者回复: 从最佳实践的角度来说,Rails一直是表现优异的,因为它的设计者是行业中的佼佼者。所以,我在《软件设计之美》中,专门把它拿出来讲。

    2021-01-02
    4
  • 李叶
    精准命名,体现业务含义,表名意图,不暴露细节,不使用技术用语

    作者回复: 很好的总结

    2021-03-24
    3
  • Geek_3b1096
    写了很多processXXXX

    作者回复: 多么痛的领悟

    2020-12-30
    3
收起评论
显示
设置
留言
45
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部