我完全赞成前缀做得很好.
我认为(系统)匈牙利表示法是造成前缀的大部分“坏名声”的原因。
这种表示法在强类型语言中基本上没有意义,例如在 C++ 中“lpsz”告诉你你的字符串是一个指向 nul 终止字符串的长指针,当: 分段架构是古老的历史,C++ 字符串按照常见约定是指向 nul 终止 char 数组的指针,而且这并不是那么困难要知道“customerName”是一个字符串!
但是,我确实使用前缀来指定usage变量(本质上是“Apps Hungarian”,尽管我更喜欢避免使用“Hungarian”一词,因为它与“System Hungarian”有不好且不公平的关联),这是一个非常方便的节省时间 and 减少错误方法。
I use:
- m 会员
- c 用于常量/只读
- p 代表指针(pp 代表指向指针的指针)
- v 表示易失性
- s 代表静态
- i 用于索引和迭代器
- e 代表事件
我希望在哪里做type显然,我使用标准后缀(例如列表、组合框等)。
这让程序员意识到usage每当他们看到/使用变量时。可以说,最重要的情况是指针的“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;
}
}
你可以在这里看到:
- 成员和参数之间不会混淆
- 索引/迭代器和项目之间不会混淆
- 使用一组明确相关的变量(项目列表、指针和索引),避免通用(模糊)名称(如“计数”、“索引”)的许多陷阱。
- 与“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”)
with:
for (int iCompany = 0; iCompany < numCompanies; iCompany++)
for (int iUser = 0; iUser < numUsers; iUser++)
companyList[iCompany].score += userList[iUser].score;
(这更具可读性,并且消除了索引方面的所有混乱。通过现代 IDE 中的自动完成功能,这也可以快速且轻松地键入)
下一个好处是代码片段不需要任何上下文被理解。我可以将两行代码复制到电子邮件或文档中,任何阅读该代码片段的人都可以区分所有成员、常量、指针、索引等之间的区别。我不必添加“哦,要小心,因为‘data’是一个指向指针的指针”,因为它被称为‘ppData’。
出于同样的原因,我不必将目光从一行代码上移开就能理解它。我不必搜索代码来查找“data”是否是本地、参数、成员或常量。我不必将手移到鼠标上,这样我就可以将指针悬停在“数据”上,然后等待工具提示(有时永远不会出现)弹出。这样程序员就可以阅读并理解代码显著地更快,因为他们不会浪费时间上下搜索或等待。
(如果您认为自己不浪费时间上下搜索来解决问题,请找到一些您一年前编写但尚未查看的代码
自从。打开文件并跳到一半而不阅读它。
在你不知道是否可以之前,看看你能从这一点读到多远
某物是成员、参数或本地。现在跳转到另一个随机
位置...这就是我们单身时整天所做的事情
单步执行别人的代码或尝试了解如何
调用它们的函数)
'm' 前缀还避免了(恕我直言)丑陋且冗长的“this->”表示法,以及它所保证的不一致(即使你很小心,你通常会得到 'this->data' 和'data' 在同一个类中,因为没有任何东西强制名称的拼写一致)。
“this”符号旨在解决歧义- 但为什么有人会故意编写可能不明确的代码呢?歧义will迟早会导致错误。在某些语言中,“this”不能用于静态成员,因此您必须在编码风格中引入“特殊情况”。我更喜欢有一个简单的、适用于任何地方的编码规则——明确、明确和一致。
最后一个主要好处是智能感知和自动完成。尝试在 Windows 窗体上使用 Intellisense 来查找事件 - 您必须滚动浏览数百个神秘的基类方法,而您永远不需要调用这些方法来查找事件。但如果每个事件都有“e”前缀,它们将自动列在“e”下的组中。因此,前缀可以对智能感知列表中的成员、常量、事件等进行分组,从而更快、更轻松地找到所需的名称。 (通常,一个方法可能有大约 20-50 个可在其范围内访问的值(局部变量、参数、成员、常量、事件)。但是在输入前缀后(我现在想使用索引,所以我输入 'i. ..'),我只看到 2-5 个自动完成选项。人们归因于前缀和有意义的名称的“额外输入”大大减少了搜索空间并显着加快了开发速度)
我是一个懒惰的程序员,上面的约定为我节省了很多工作。我可以更快地编码,并且犯的错误也少得多,因为我知道应该如何使用每个变量。
反对的论点
那么,有什么缺点呢?反对前缀的典型论点是:
“前缀方案是坏/邪恶的”。我同意“m_lpsz”及其类似内容经过深思熟虑且完全无用。这就是为什么我建议使用精心设计的符号来支持您的需求,而不是复制不适合您的上下文的内容。 (使用适合工作的正确工具)。
“如果我改变某个东西的用途,我就必须重命名它”。是的,当然可以,这就是重构的意义所在,也是为什么 IDE 拥有重构工具来快速、轻松地完成这项工作。即使没有前缀,更改变量的用法几乎肯定意味着它的名称ought被改变。
“前缀让我很困惑”。就像每个工具一样,直到您学会如何使用它为止。一旦你的大脑习惯了命名模式,它就会自动过滤掉信息,你就不会介意前缀的存在了。但你必须扎实地使用这样的方案一两周,然后你才能真正变得“流利”。就在那时,很多人查看旧代码并开始想知道他们是如何管理的without一个好的前缀方案。
“我只需查看代码即可解决这个问题”。是的,但是当答案就在您眼睛已经关注的地方时,您不需要浪费时间查看代码中的其他位置或记住代码的每个小细节。
(部分)信息只需等待工具提示在我的变量上弹出即可找到。是的。在支持的情况下,对于某些类型的前缀,当您的代码干净编译后,等待一段时间后,您可以通读描述并立即找到该前缀将传达的信息。我觉得前缀是一种更简单、更可靠、更高效的方法。
“打字多了”。真的吗?多一个完整的角色?或者是 - 使用 IDE 自动完成工具,通常会减少输入,因为每个前缀字符都会显着缩小搜索空间。按“e”,您班级中的三个事件会在智能感知中弹出。按“c”,会列出五个常数。
“我可以用this->
代替m
"。嗯,是的,你可以。但这只是一个更丑陋、更冗长的前缀!只是它带来了更大的风险(尤其是在团队中),因为对于编译器来说optional,因此它的用法经常不一致。m
另一方面,它是简短、清晰、明确且非可选的,因此使用它更难犯错误。