Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

中文命名的特定问题, 相关风格及规范 #45

Open
nobodxbodon opened this issue Nov 4, 2017 · 24 comments
Open

中文命名的特定问题, 相关风格及规范 #45

nobodxbodon opened this issue Nov 4, 2017 · 24 comments
Labels

Comments

@nobodxbodon
Copy link
Member

早先有一些尝试, 以及编写Java上手时归整的一些. 有些是Java特定的. 希望一同探讨, 早日发现潜在问题, 总结出一些不同编程语言普遍适用的规则以及特定编程语言相关的规则.

如何区分类/方法/变量/常量: 没有了大小写区分,词性又会有歧义,考虑用前/后缀?

有对变量进行前缀区别函数/变量的实践. 似乎类似匈牙利命名法. 但是感觉有些不大直观,比如g代表get和s代表set.在示例项目中, 我用的是get/setxx. 感觉还有改进空间. 下面是一些动议:

  • 类名尽量用名词或名词短语. 用"类"结尾, 便于和一般变量名区别. 测试类用"测试类"结尾.
  • 接口(interface)名用"接口"结尾
  • 方法/函数命名尽量用动词开头
  • 常量命名以"常量_"作前缀, 考虑只用在"真"常量上, 就是初始化后不能被改变的量(Immutable).
  • 包名(Java)用中文(如第三方不支持, 则用小写英文), 不用下划线

如何命名临时变量: 英文的a, i, j之类

详见nobodxbodon/program-in-chinese#2 (comment), 对于纯粹作为循环中的索引, 个人认为不需强求改为中文, 因为它的语义很少. 但是如果想突出它的语义, 那么当然可以用对应中文, 这和英文命名是类似的. 比如:

for(int 排名; 排名 < 总人数; 排名++) {
  System.out.println(排行榜[排名]);
}

英文单复数如何表达?

这是个有趣的主题. 其实英文命名如果带复数往往意思是"这个变量有可能含有多个元素", 比如List<String> names = new ArrayList<>(). 但实际上这个变量是可能包含一个元素的, 这种情况下就和复数形式不一致.
而中文中的名词默认情况下是不分单复数的, 感觉这其实更合适"这个变量有可能含有多个元素"这个语义. 那么, 关键就在于如何表示单数了. 比如:

for (String name : names) {
...
}

中文是否可以考虑:

for (String 某名字 : 名字) {
...
}
@kenpusney
Copy link

这是现代汉语作为分析语必然要面对的一个问题。

不过一个通常用的实践是,用OO方式写代码的时候大概都会是SVO(主-谓-宾)的形式,也即,<施动者>.<动作>(<受动者>)。这样其实也就不会出现什么“方法”和“变量”命名冲突了。

另外,类或者getXxx、setXxx 之类的,既然你期望引入中文编程,就没必要一定拿Java这堆模型来设计语言。比如,直接引入“属性(property)”,远比定义一堆getter/setter好得多。

另外临时变量用“某(some)”,“临时(temp)”这种前缀其实在现在的编程实践中都不是一个很值得推荐的做法。更不要试图用匈牙利命名法来给输入和理解增加负担。

@nobodxbodon
Copy link
Member Author

@kenpusney 多谢! 顶楼确实非常针对Java中的中文命名. 主要的考虑是, 即使新的中文编程语言现在出现, 很可能要5-10年才能成熟和推广. 那么在这之前以及之后的一段时间, 当今的英文编程语言还会占据很大一部分市场(考虑到现有软件的生命期), 因此探讨一下英文编程语言中的中文风格也是有益处的. 另外, 这些风格也可能影响新中文编程语言的设计.

用OO方式写代码的时候大概都会是SVO(主-谓-宾)的形式,也即,<施动者>.<动作>(<受动者>)。这样其实也就不会出现什么“方法”和“变量”命名冲突了。

顶楼有一点"方法/函数命名尽量用动词开头", 也是出于类似考虑. 但是变量名可能难以做到完全不用动词开头. 因为即使是名词短语也很可能用动词开头. 但方法和变量名即使在英文代码中也是无法一眼区分的, 因此主要关注的还是区分类名(上面采取的是后缀"类")

另外,类或者getXxx、setXxx 之类的,既然你期望引入中文编程,就没必要一定拿Java这堆模型来设计语言。比如,直接引入“属性(property)”,远比定义一堆getter/setter好得多。

很同意. 如果是新的中文编程语言, 绝对不会用这个get/set前缀.

另外临时变量用“某(some)”,“临时(temp)”这种前缀其实在现在的编程实践中都不是一个很值得推荐的做法。更不要试图用匈牙利命名法来给输入和理解增加负担。

很同意. 个人也认为匈牙利命名的缩写部分在现在的命名风格中已经不再推崇了. 不过临时变量的命名也许值得探讨一下. 毕竟也有没有什么语义的情况, 个人现在实践中, 经常就沿用英文字母了, 比如for循环中的i.

@farteryhr
Copy link

farteryhr commented Apr 9, 2018

https://en.wikipedia.org/wiki/Naming_convention_(programming)
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions
一些关于英语大小写、下划线乱象的参考(与微软爸爸的标准,里面有很多关于合成词缩写词的鲜活的例子,男人看了会沉默)
感觉虽然中文在这方面先天优势,不会乱不会纠结,但是某些时候若用大小写携带某些语义有用,也要另想办法。

@nobodxbodon
Copy link
Member Author

看到第二个链接里的logOff而不是logOut, signOut而不是signOff; logOn而不是logIn, signIn而不是signOn; 还有canceled而不是cancelled, 就呵呵了.

还没细看wiki的页, 不过之前想过在所有编程语言中使用一套尽可能一致的中文命名方法, 避免英文命名在不同历史阶段留下的各种不同风格. 也算一种后发优势吧.

某些时候若用大小写携带某些语义有用,也要另想办法

除了之前提到的区分类/方法/变量/常量的目的, 其他还有什么情况呢?

@dou4cc
Copy link

dou4cc commented Apr 11, 2018

如果程序语言都支持i18n了,源码肯定也不是文本了,不妨用颜色或者其它办法区分单复数?

@farteryhr
Copy link

farteryhr commented Apr 11, 2018

不妨用颜色或者其它办法区分单复数?

单复数与类我是偏向加词缀,常量、变量什么的区分倒是可以考虑颜色【然而话说色盲色弱选手
也可以考虑粗体、下划线(毕竟下划线还是以前的专名号

的确这么一波讨论下来觉得发展中文编程首先要实现更高级的代码编辑器的渲染,至少跟代码里的标识符要有关……

@nobodxbodon
Copy link
Member Author

颜色的规范难度恐怕不比词缀小, 个人感觉和IDE功能耦合有点大. 现在想来, 之前没有特别区分常量命名, 好像也没什么问题, 语义上就比较清楚了. 而且还有编译期检查.

@dou4cc
Copy link

dou4cc commented Apr 12, 2018

@nobodxbodon 程序的正确与否和命名是否得当无关,命名只有助记作用,无需严谨。

@ofooo
Copy link

ofooo commented Aug 6, 2018

常量和变量其实都可以算变量。或者加个后缀“常数”,比如 e常数、文本上限常数等等。
用颜色的想法不知道怎么想出来的。。。。写代码的时候如何编辑一个文字的颜色????难道要点击鼠标改颜色吗~~~谁写代码还得来回用鼠标。。。。有点异想天开~~~

单数价格前缀“某”是个好想法。
或者确定是复数的加个后缀“们”?人们,同学们 虽然有些会不自然,但是代码毕竟不是口语,习惯了就好了~~

@nobodxbodon
Copy link
Member Author

@ofooo

或者加个后缀“常数”

顶楼提到加类似前缀, 主要考虑一般所有常量排在一起, 看起来可能更整齐, 如下. 不过下划线的确不大自然.

  private static final String 常量_单字节累加寄存器名 = "AL";
  private static final String 常量_单字节计数寄存器名 = "CL";
  private static final String 常量_单字节数据寄存器名 = "DL";
  private static final String 常量_单字节BX寄存器名 = "BL";
  private static final String 常量_单字节SP寄存器名 = "SPL";

或者确定是复数的加个后缀“们”?

之前也尝试过: #54 (comment)
后来发现也许更多时候是单复数模糊的. 详请见在代码中进行中文命名(类/变量/方法等)的优势"中文单复数模糊性更符合语义"小节

@farteryhr
Copy link

farteryhr commented Aug 6, 2018

@ofooo

用颜色的想法不知道怎么想出来的。。。。写代码的时候如何编辑一个文字的颜色????难道要点击鼠标改颜色吗~~~谁写代码还得来回用鼠标。。。。有点异想天开~~~

当然不是啦……语法高亮听说过么……要手动编辑么……

我说的就是一种稍微高级点的语法高亮,编辑器渲染的时候搞点鬼。
比如约定,用英文字母来打头,大写C大头为类名,那么代码里是C某类,渲染出来就删掉那个影响视觉的C,变成变色的某类,常量就写作K某常量,渲染作另一个风格的某常量,等等。
易语言纯文本不也是.打头关键字嘛,渲染出来加蓝,虽然编辑的时候完全是结构化编辑是另一回事了。

再进一步,如果做插件抱上了强如vscode, intellisense的大腿,一边编辑一边后台执行分析,一个token是在哪儿声明有什么性质,都能得到了,就直接自动加颜色加风格了,一个意思。

@4b5ent1
Copy link
Member

4b5ent1 commented Aug 6, 2018

我来说下自己的看法,感觉这个问题不必局限java,基本适用于所有C类PL:python, typescript, etc.

如何区分类/方法/变量/常量: 没有了大小写区分,词性又会有歧义,考虑用前/后缀?
英文单复数如何表达?

类和方法个人认为不太需要区分。因为如果一定要区分,写个class 香蕉类 就可以了。变量和常量,感觉也不需要区分,如果一定要区分,变量前面加v就好了,比如:v总和。常量同理可以加s(c留给class)

总结一下对应的可选前缀:i接口,c类,m方法,s静态,v变化,n复数

比如for(String name: names)的这种,写成for(String 名:N名字)是比较好认的

如何命名临时变量: 英文的a, i, j之类

临时变量我觉得完全可以继续用英文,中英文混合,可以让英文的优先级视觉低一点无妨。就好像小学生选择题都是ABCD,也没有说一定要改成甲乙丙丁,是一个道理。

如果程序语言都支持i18n了,源码肯定也不是文本了,不妨用颜色或者其它办法区分单复数?

如果不想跟ide紧耦合,那么尽量还是兼容现有的一些规则比较好。


如果是我的话,在python里面应该是很少需要大量使用中文命名的。一般都是必要的时候统一规范,比如实体用中文,非实体不用中文,模板用中文,字符串用中文。完全中文化,有时候是画蛇添足了。

用中文替代英文的原则应该是中文比英文方便的时候,用中文。一个字母可以搞定的事情,就不需要另外用汉字了。

@cflw
Copy link
Member

cflw commented Oct 18, 2018

中文命名最大的问题并不是区分xxx,也不是来自于中文本身的语法缺陷。既然中文命名要应用于中文编程,就要解决最严重的重名问题。当全局变量、常量、类成员变量、函数参数、函数局部变量重名的时候,必须加点东西以示区分。类、结构、接口等复合类型也是同样道理。名词单复数也一样。所谓的区分xxx其实都是在为解决重名而服务的。自然语言没有能力解决编程语言中的重名问题,所以才会有各种各样的命名法。英文编程里的各种大小写下划线命名法在区分xxx的同时也解决了重名问题。

而问题的解决方法上面几楼都已经提到了,要么用中文前后缀区分,要么用英文前后缀区分。我个人比较赞同用英文缩写区分,因为我一开始在非中文编程语言尝试中文编程的时候就想到用英文缩写。用英文缩写最大的优点就是可以跟国际接轨,什么C类I接口g全局变量m成员变量都是学微软的那一套,省去了自己从零发明一套命名法的麻烦。

现在看了一些纯中文命名的代码,再结合我以前的经验,感觉纯中文命名最大的问题就是为了区分不同的类型/变量,要在名称里额外添加很多字,字数太多显得啰嗦,看不到重点,代码可读性差,一堆密密麻麻的方块字聚在一起容易引起视觉疲劳。而且纯中文代码在没有语法高亮支持的情况下阅读体验非常糟糕。半中半英可以适当刺激视觉,在阅读代码时还可以忽略的英文部分(或者一扫而过),只看中文部分(只看重点),极大地提高阅读效率。

我认为好的中文命名法,必须具备高输入效率、高可读性、快速取名能力。输入效率的取决于名称长度和输入法的好坏,纯中文的话汉字数量变多会增加键盘击键数,延长打字时间;可读性由命名风格决定,好的命名风格使代码容易阅读;快速取名能力保证了什么名称都能随手拈来,给名称做词性限制反而束手束脚想不出好名称,中文命名好坏快慢更多的取决于个人的语文能力。

顺便说一下,顶楼的实践一文其实是我写的。后来我根据多年的编程经验又写了第二版:https://blog.csdn.net/acebdo/article/details/80554791
这篇文章主要通过一些硬性规定的英文前缀来区分不同分类,每个名称只要1~2个英文字母作为前缀,能在任何场合区分单复数,兼容国际上的一些命名法。我觉得我的这篇文章差不多解决了面向过程编程、面向对象编程、函数式编程等不同编程范式的重名问题。

@4b5ent1
Copy link
Member

4b5ent1 commented Oct 18, 2018

@cflw 你写的那个方案还是啰嗦了一点。不过你说的基本上也是以前的汉化方案存在的问题。

这个是我的方案:pyzh/song#26

@nobodxbodon
Copy link
Member Author

@cflw 多谢分享经验! 非常高兴看到中文命名的实践项目:

组里有些中文命名的API项目(比如简繁转换, 汉化JUnit4, 英汉词典), 感觉这对推广中文命名颇有益处, 因为用户就可以发现接口中文命名的优势(见v2用户反馈帖). 如果有兴趣/打算开发一些针对常用功能的库(Python爬虫/功用库?)的话, 欢迎创建issue/repo(邀请已发).

英文命名规范发展了数十年, 相信中文命名规范也需要在实践(尤其是团队开发)中磨砺和总结. 希望对细节问题的切磋探讨不会妨碍合作实践.

个人认为, 从可读性考虑, 感觉英文缩写需要开发者先了解英文命名规范, 对新手来说门槛高一些. 另外IDE本身也有一些辅助作用. 比如"用命名分类区分不同函数的功能/作用范围", 现在IDE的自动补全/outline视图等等会通过不同图标区分显示. 是否需要用命名承载这些功能也是个课题.

@cflw
Copy link
Member

cflw commented Oct 20, 2018

@Absente 我也觉得我的的方案强制加前缀确实很啰嗦,不过代码写多了之后看起来会有一种排版工整的感觉。不知道你们看了我的代码后是什么感觉。

看了你的方案,我也提几个意见:

  • 因为我已经习惯了用一个字母代表一个单词的缩写,而你这种1~3个字母代表一个单词的方法让我感觉很凌乱。
  • 标题的《Python变量命名规范》说明它不具备可以应用于不同编程语言的普遍适用性。
  • 我的方案是根据重名频率和使用频率这两方面考虑的,在大部分情况下不会重名时,我会直接收手不会继续细分下去。而你的方案里有一些缩写是不常用的,甚至把指针这种Python里几乎不会出现的东西也添加进去。
  • 缩写有冲突,你的方案里的t即代表元祖,也代表列表尾,h也有头和句柄的双重含义。这样子的代码不会引发歧义吗?

谢谢 @nobodxbodon 的邀请,不过我开发的代码库是给我自己用的,发布到github只是为了跟大家分享。重复造轮子是编程界大忌,用中文编程造一些轮子更多的只是推广作用,实际应用价值很小。还不如做点实际项目来得实在。

@nobodxbodon
Copy link
Member Author

@cflw 上面的几个API项目开发的时候没有发现同样功能的(简繁转换虽然有工具, 但是没看到maven里发布的Java库). 无论如何, 随时欢迎加入. 在交流方面和非组员没多大区别, 主要是组内广播和建组内repo方便, 还有一个组内微信群
关于代码可读性方面, 看了一下小说下载脚本, 感觉浏览时最显眼的就是中文部分, 没记错的话英文前缀并没有什么语义方面的辅助. 个人一直是尽量用全中文命名(如五笔编码编辑器), 一部分原因是想看看这样是否有什么开发维护时的大问题. 受限于项目规模(都是单人小项目), 暂时没有发现什么大缺陷.

@4b5ent1
Copy link
Member

4b5ent1 commented Oct 20, 2018

@cflw 回复一下你的观点:

标题的《Python变量命名规范》说明它不具备可以应用于不同编程语言的普遍适用性。

第一,关于普适原则,我认为,只要有交集就可以,在别的PL里,可以用别的写法。interface这类通用概念,py有java也有。

缩写有冲突,你的方案里的t即代表元祖,也代表列表尾,h也有头和句柄的双重含义。这样子的代码不会引发歧义吗?

第二,我认为多义性是好的。这类似OOP里面的duck typing,类似erlang里面的同名不同目函数。比如erlang里面f/1和f/2,因为参数目不同实际上是两个函数。而你举例的t和h/t,实际上,可以对应为t/0和t/1。

@farteryhr
Copy link

看了上面这些标准,有所感悟,不过关于前缀我的想法还是,不做太细的要求,取大众惯例的核心就好。
比如OOP起来,成员函数随时都在调用,前面是.后面是(),还要加个f就累赘了……

只要覆盖常用情况,难以表述又原有惯例的,如C类,I接口,m成员变量(有m了除此之外都是成员函数了),然后c常量,Ee为枚举类、数据,我觉得就差不多了。
一些高频词,比如表示“个数”的时候n(俗话说得好n个),“是否”用下b,“集合、数组"的时候a(或者t,l,这里就不太统一了,看是否根据实际数据结构而变)。

getter、setter可以用“取、置”。s这个字母实在是太容易撞,set(设置、集合)、string、struct,不宜写入规范。
剩下就可以不再强求英文字母,自行命名稍长两字准确一点也好,也避免规范跟个人灵活使用撞车难以避开的情况。

@nobodxbodon
Copy link
Member Author

基于实例的中文关键词选取类似, 可否通过团队合作开发一些基础项目(比如面向学生群体的, @Absente 在微信群中刚探讨的常见计算机作业/面试题集锦, 或者与核心学科结合)?
不仅可以从实践中检验磨合命名规范, 也有助于对外推广.

@4b5ent1
Copy link
Member

4b5ent1 commented Oct 23, 2018

@farteryhr 你说的这个问题,其实就是标准尚未统一的问题。这里是现在收集的所有简化关键词https://github.com/program-in-chinese/overview/wiki/英文关键词汉化

个人的标准规范是:pyzh/song#26

@nobodxbodon
Copy link
Member Author

此答评论区:

比如“findNoByUsername() 以用户名寻编号()”、“findNameByID() 以名寻号()”,“findByName寻之以名()“

通过客户编号交易账号和基金代码查找并按发生日期升序排列——
如果可以把“、”当做“_”来用,那么我们可以写作“以客户编号、交易账号、基金代码寻之并以发生日期升序排列”,这样也不错啊,而且觉得冗长的原因无非是命名能力缺乏户号,基金码,是日,都挺好听的啊

中文命名的确考验语文能力。

@liuxilu
Copy link

liuxilu commented Jan 9, 2021

这真是「为掩涕兮长太息」「肇以嘉名锡余」……
「命名能力缺乏」「考验语文能力」。噫,此何异于「这点英文都不会就别编程了」也!

@nobodxbodon
Copy link
Member Author

@liuxilu 有些误会?命名的用词和用语往往有不小推敲空间,是否用母语命名都是如此,而用母语时也许使得这一空间更大了,详见:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants