我都赞成前缀做得好。
我认为(系统)匈牙利符号是造成前缀出现的大多数“不良说唱”的原因。
在强类型语言中,这种表示形式毫无意义,例如在C ++“ lpsz”中,它告诉您您的字符串是一个以nul终止的字符串的长指针,在以下情况下:分段体系结构是古老的历史,C ++字符串通常是以nul终止的指针char数组,知道“ customerName”是一个字符串真的不是那么困难!
但是,我确实使用前缀来指定变量的用法(实际上是“ Apps Hungarian”,尽管我宁愿避免使用 “ Hungarian”一词,因为它与System Hungarian的关联不良且不公平),这非常节省时间,并且减少错误的方法。
我用:
- m代表成员
- c代表常数/唯读
- p代表指针(pp代表指针)
- v代表volatile
- s为静态
- 我为索引和迭代器
- 事件e
我希望使类型清楚的地方使用标准后缀(例如List,ComboBox等)。
这使程序员在看到/使用变量时就知道该变量的用法。可以说,最重要的情况是指针的“ p”(因为用法从var。更改为var->,并且您必须更加小心使用指针-NULL,指针算术等),但是所有其他情况都非常方便。
例如,您可以在一个函数中以多种方式使用相同的变量名:(此处为C ++示例,但同样适用于多种语言)
MyClass::MyClass(int numItems)
{
mNumItems = numItems;
for (int iItem = 0; iItem < mNumItems; iItem++)
{
Item *pItem = new Item();
itemList[iItem] = pItem;
}
}
您可以在这里看到:
- 成员和参数之间没有混淆
- 索引/迭代器与项目之间没有混淆
- 使用一组明确相关的变量(项目列表,指针和索引),避免了通用(模糊)名称(例如“ count”,“ index”)的许多陷阱。
- 与“ itemIndex”和“ itemPtr”之类的替代项相比,前缀减少了键入(更短,并且在自动完成时更有效)
“ iName”迭代器的另一个优点是,我永远不会用错误的索引来索引数组,而且如果我在另一个循环中复制一个循环,则不必重构其中一个循环索引变量。
比较这个不切实际的简单示例:
for (int i = 0; i < 100; i++)
for (int j = 0; j < 5; j++)
list[i].score += other[j].score;
(这很难读,并且经常导致原本打算使用“ j”的地方使用“ i”)
与:
for (int iCompany = 0; iCompany < numCompanies; iCompany++)
for (int iUser = 0; iUser < numUsers; iUser++)
companyList[iCompany].score += userList[iUser].score;
(它更具可读性,并且消除了索引编制方面的所有混乱。借助现代IDE中的自动完成功能,键入起来也很容易快捷)
下一个好处是代码段不需要任何上下文即可理解。我可以将两行代码复制到电子邮件或文档中,任何阅读该代码段的人都可以分辨出所有成员,常量,指针,索引等之间的区别。我不必添加“哦,请小心,因为“数据”是指向指针的指针”,因为它被称为“ ppData”。
出于同样的原因,我不必为了理解它而将视线从代码行中移开。我不必遍历代码来查找“数据”是本地变量,参数,成员还是常量。我不必将手移到鼠标上,因此可以将指针悬停在“数据”上,然后等待工具提示(有时永远不会出现)弹出。所以,程序员可以阅读和理解的代码显著更快,因为他们没有时间浪费在寻找上下或等待。
(如果您不认为您会浪费时间在向上或向下搜索工作,请查找您一年前编写的代码,此后一直没有看过。打开文件,然后不读就跳下一半。了解如何在您不知道某个东西是成员,参数还是局部变量之前,您可以从这一点开始阅读很远的信息,现在跳转到另一个随机位置...这就是我们整天仅浏览其他人的代码时所做的事情或尝试了解如何调用其函数)
'm'前缀还避免了(IMHO)丑陋和冗长的“ this->”表示法,并且避免了不一致的情况(即使您小心了,通常也会混入'this-> data'和相同类别中的“数据”,因为没有任何东西可以使名称的拼写保持一致)。
“此”表示法旨在解决歧义 -但是为什么有人会故意编写可能含糊不清的代码?歧义迟早会导致错误。在某些语言中,“ this”不能用于静态成员,因此您必须在编码样式中引入“特殊情况”。我更喜欢有一个适用于任何地方的简单编码规则-明确,明确和一致。
最后一个主要好处是使用Intellisense和自动补全功能。尝试在Windows窗体上使用Intellisense查找事件-您必须滚动浏览数百个神秘的基类方法,而这些方法无需调用即可查找事件。但是,如果每个事件都有一个“ e”前缀,它们将自动在“ e”下的组中列出。因此,前缀可以在智能感知列表中对成员,常量,事件等进行分组,从而更快,更轻松地找到所需的名称。(通常,一个方法可能在其范围内可访问约20-50个值(局部变量,参数,成员,常量,事件)。但是在键入前缀后(我现在想使用索引,所以我键入'i。 ..”),系统仅显示2-5个自动完成选项。“额外键入”
我是一个懒惰的程序员,上面的约定为我节省了很多工作。我可以更快地编写代码,并且我犯的错误少得多,因为我知道应该如何使用每个变量。
反对
那么,缺点是什么?反对前缀的典型参数是:
“前缀方案是坏的/邪恶的”。我同意,“ m_lpsz”及其类似词经过深思熟虑,完全没有用。因此,我建议您使用设计合理的符号来满足您的要求,而不是复制不适合您的情况的符号。(使用正确的工具进行作业)。
“如果更改某项的用法,则必须将其重命名”。是的,您当然知道了,这就是重构的全部内容,也是为什么IDE具有重构工具可以快速,轻松地完成此工作的原因。即使没有前缀,几乎可以肯定的是,更改变量的用法意味着应该更改其名称。
“前缀只是让我感到困惑”。在您学习如何使用之前,每个工具都一样。一旦您的大脑习惯了命名模式,它就会自动过滤掉信息,您根本就不会在乎前缀。但是,在真正变得“流利”之前,必须扎实地使用这样的方案一两个星期。那时很多人都在看旧代码,开始想知道他们如何在没有好的前缀方案的情况下进行管理。
“我可以看一下代码来解决这些问题”。是的,但是当您的注意力已经集中在现场时,您不必浪费时间在代码的其他地方或记住每个细节。
(某些)信息可以通过等待工具提示在我的变量上弹出来找到。是。对于某些类型的前缀,在受支持的地方,当您的代码经过干净的编译后,在等待之后,您可以通读描述并查找该前缀将立即传达的信息。我认为前缀是一种更简单,更可靠,更有效的方法。
“更多的打字”。真?还有一个完整的角色?还是它-使用IDE自动补全工具,通常会减少键入,因为每个前缀字符都会大大缩小搜索空间。按“ e”,班级中的三个事件将以智能感知方式弹出。按“ c”,将列出五个常数。
“我可以使用this->
代替m
”。好吧,可以。但这只是一个更加丑陋和冗长的前缀!只有它带来更大的风险(尤其是在团队中),因为对于编译器来说,它是可选的,因此其用法经常不一致。m
另一方面,它是简短,清晰,明确和非可选的,因此使用它来犯错误要困难得多。