Ken*_*ran 8 naming-conventions
好的,所以你可以阅读关于标识符命名的指导原则,直到你脸色发青蓝......骆驼的情况下,pascal的情况下,让它们描述性......但它们无法帮助你真正选择给定的最佳名称应用领域.
最容易选择(恕我直言)是一个或两个单词的名词组:
但并不是每个类都整齐地适合一个名词,所以我看到很多人通过在它们的末尾添加-er将动词变为名词:
我看到这个问题的最大问题是很多时候他们都很模糊......特别是经理.究竟是什么管理?
所以我的问题是你如何为一个班级选择一个好名字?"好",我的意思是内容丰富,毫不含糊.
我知道我知道.几乎每个现代IDE都内置了重构支持,您可以更改名称而不必睁眼,那么重点是什么?一个选择不当的名字会混淆和误导任何偶然发现它的人,直到它被重命名为止,这仍然是一个有效的问题.
我一直在阅读罗伯特·C·马丁的" 清洁代码",并且还没有从第17章开始阅读这一部分,但我认为它最接近于回答这个问题.
N1:选择描述性名称
选择名字不要太快.确保名称是描述性的.请记住,随着软件的发展,意义往往会不断变化,因此经常重新评估您选择的名称的适当性.这不仅仅是一种"感觉良好"的建议.软件中的名称占软件可读性的90%.你需要花时间明智地选择它们并使它们保持相关性.名字太重要了,不能随意对待.请考虑以下代码.它有什么作用?如果我向你展示精选名字的代码,它对你来说将是非常有意义的,但就像这样,它只是一个符号和魔术数字的大杂烩.
Run Code Online (Sandbox Code Playgroud)public int x() { int q = 0; int z = 0; for (int kk = 0; kk < 10; kk++) { if (l[z] == 10) { q += 10 + (l[z + 1] + l[z + 2]); z += 1; } else if (l[z] + l[z + 1] == 10) { q += 10 + l[z + 2]; z += 2; } else { q += l[z] + l[z + 1]; z += 2; } } return q; }这是代码应该写的方式.这个片段实际上不如上面那个完整.然而,您可以立即推断它正在尝试做什么,并且您很可能根据推断的含义编写缺失的函数.神奇的数字不再是魔术,算法的结构具有引人注目的描述性.
Run Code Online (Sandbox Code Playgroud)public int score() { int score = 0; int frame = 0; for (int frameNumber = 0; frameNumber < 10; frameNumber++) { if (isStrike(frame)) { score += 10 + nextTwoBallsForStrike(frame); frame += 1; } else if (isSpare(frame)) { score += 10 + nextBallForSpare(frame); frame += 2; } else { score += twoBallsInFrame(frame); frame += 2; } } return score; }精心选择的名称的强大之处在于它们通过描述重载代码的结构.这种重载设置了读者对模块中其他功能的期望.您可以通过查看上面的代码来推断isStrike()的实现 .当您阅读isStrike 方法时,它将"非常符合您的预期".
Run Code Online (Sandbox Code Playgroud)private boolean isStrike(int frame) { return rolls[frame] == 10; }N2:在适当的抽象级别选择名称
不要选择沟通实施的名称; 选择名称反映您正在工作的类或功能的抽象级别.这很难做到.同样,人们在混合抽象层次方面也非常擅长.每次对代码进行传递时,您可能会发现一些命名为太低级别的变量.您应该利用这个机会在找到它们时更改这些名称.使代码可读需要致力于持续改进.考虑下面的调制解调器 界面:
Run Code Online (Sandbox Code Playgroud)public interface Modem { boolean dial(String phoneNumber); boolean disconnect(); boolean send(char c); char recv(); String getConnectedPhoneNumber(); }起初看起来很好.这些功能似乎都合适.实际上,对于许多应用程序而言.但现在考虑一个应用程序,其中一些调制解调器没有通过拨号连接.相反,它们通过将它们硬连接在一起而永久连接(想想现在为大多数家庭提供互联网接入的电缆调制解调器).也许有些是通过USB连接向交换机发送端口号来连接的.很明显,电话号码的概念处于错误的抽象层次.此方案的更好的命名策略可能是:
Run Code Online (Sandbox Code Playgroud)public interface Modem { boolean connect(String connectionLocator); boolean disconnect(); boolean send(char c); char recv(); String getConnectedLocator(); }现在名字没有对电话号码做出任何承诺.它们仍可用于电话号码,或者可用于任何其他类型的连接策略.
N3:尽可能使用标准命名法
如果名称基于现有约定或用法,则更容易理解.例如,如果您使用的是DECORATOR模式,则应在装饰类的名称中使用Decorator一词.例如, AutoHangupModemDecorator可能是装饰调制解调器的类的名称,该类 能够在会话结束时自动挂起.模式只是一种标准.例如,在Java中,将对象转换为字符串表示的函数通常命名为 toString.遵循这些惯例比制造自己的惯例更好.团队通常会为特定项目创建自己的标准名称系统.埃里克埃文斯称这是该项目无处不在的语言.您的代码应广泛使用此语言中的术语.简而言之,您可以越多地使用与项目相关的特殊含义重载的名称,读者就越容易知道您的代码在谈论什么.
N4:明确的名称
选择使函数或变量的工作明确无误的名称.考虑一下FitNesse的这个例子:
Run Code Online (Sandbox Code Playgroud)private String doRename() throws Exception { if(refactorReferences) renameReferences(); renamePage(); pathToRename.removeNameFromEnd(); pathToRename.addNameToEnd(newName); return PathParser.render(pathToRename); }除了广义和含糊的术语之外,这个函数的名称并没有说明函数的作用.在名为doRename的函数中有一个名为renamePage的函数,强调了这一点.这些名称告诉你两个函数之间的区别是什么?没有.该函数的更好名称是 renamePageAndOptionallyAllReferences.这可能看起来很长,而且它只是从模块中的一个地方调用,因此它的解释值超过了长度.
N5:长名称使用长名称
名称的长度应与范围的长度相关.对于小范围,您可以使用非常短的变量名称,但对于大范围,您应该使用更长的名称.如果它们的范围是五行,那么像i和j这样的变量名称 就可以了.考虑旧标准"保龄球游戏"中的这个片段:
Run Code Online (Sandbox Code Playgroud)private void rollMany(int n, int pins) { for (int i=0; i<n; i++) g.roll(pins); }这是非常清楚的,如果变量i被像rollCount这样恼人的东西所取代,那么 它将被混淆.另一方面,具有短名称的变量和函数在长距离上失去意义.因此,名称的范围越长,名称就越长,越精确.
N6:避免编码
名称不应使用类型或范围信息进行编码.诸如m_或f之类的前缀在当今的环境中是无用的.此外,项目和/或子系统编码(例如 vis_(用于视觉成像系统))分散注意力并且是多余的.同样,今天的环境提供所有信息,而不必破坏名称.保持您的名字免受匈牙利污染.
N7:名称应描述副作用
名称应描述函数,变量或类的所有内容.不要用名称隐藏副作用.不要使用简单的动词来描述不仅仅是简单动作的功能.例如,请考虑来自TestNG的此代码:
Run Code Online (Sandbox Code Playgroud)public ObjectOutputStream getOos() throws IOException { if (m_oos == null) { m_oos = new ObjectOutputStream(m_socket.getOutputStream()); } return m_oos; }这个功能比获得"oos"更多; 如果尚未创建"oos",它会创建它.因此,更好的名称可能是 createOrReturnOos.
1) 不要缩写。仅当首字母缩略词符合行业标准(如 HTML)时才使用首字母缩略词。
2)在你的名字上保持一致。
3) 使用您的应用程序所在域中的术语。当想出一个名称时,假设在添加人们不熟悉的新名称时,您可以花费的子弹数量有限。
您可能会觉得您班级中的某些细微特征将它与“Foo”区分开来,并且由于这种细微差别而倾向于为它编造一些新概念。如果使用它的 80% 的人不会关心这种细微差别,请坚持使用已知术语。
4) 在大多数面向对象语言中,自动完成很重要。如果可能,第一个词应该是人们在探索命名空间时最有可能输入的词。其他人觉得用英文读好更重要,所以这有点值得商榷。