按照变量的类型命名是一种不好的做法吗?

发布于 2024-09-16 08:54:44 字数 1087 浏览 4 评论 0原文

我使用下划线命名风格(而不是驼峰命名法)对 C++ 进行编程,STL 和 boost 也使用这种命名风格。然而,由于类型和变量/函数都以小写命名,因此如下的成员变量声明将导致编译器错误(或者至少是麻烦):

position position;

名为 position 的成员变量,其类型为 < em>位置。我不知道如何命名它:它通常是位置,但它也是对象的位置。在驼峰情况下,这对编译器来说没问题:

Position position;

但在 C++ 中它会导致问题。我不想切换到驼峰式大小写,使用匈牙利表示法或添加尾随下划线,所以我想知道:无论如何,像类型一样命名成员是一个好习惯吗?

在 C 中,为此使用神秘的单字母变量是很常见的:

int i;

但我发现有点神秘:

position p;

我可以使用变量命名的经验法则来避免这种情况吗?

如果您需要解决的话,我的代码中有更多示例:

mouse_over(entity entity) // Returns true if the mouse is over the entity

manager &manager; // A reference to the framework's manager

audio audio; // The audio subsystem

编辑:

我很好奇 Bjarne Stroustrup 本人是否对这个问题有话要说。显然,他没有,但他建议了可以解决我的编译器问题的编码约定:

例如,非标准库用户定义类型大写,非类型以小写字母开头

,这与 STL 和 boost 一致,所以我可能会使用它。然而,大多数人都认为无论编译与否,都应该避免这种命名。斯特鲁斯特鲁普也是如此:

选择仅大小写不同的名称是不明智的。

I'm programming C++ using the underscore naming style (as opposed to camel case) which is also used by the STL and boost. However, since both types and variables/functions are named all lower case, a member variable declaration as follows will lead to compiler errors (or at least trouble):

position position;

A member variable named position which is of type position. I don't know how else to name it: It's generally a position, but it is also the position of the object. In camel case, this would be fine with the compiler:

Position position;

But in C++ it causes problems. I don't want to switch to camel case, use Hungarian notation or add a trailing underscore because of that, so I'm wondering: Is it a good practice to name a member like a type anyways?

In C, it is pretty common to use cryptic one-letter variables for this:

int i;

But I find that a bit, well, cryptic:

position p;

Are there any rules of thumb for variable naming I can use to avoid this?

There are more examples in my code if you need something to work on:

mouse_over(entity entity) // Returns true if the mouse is over the entity

manager &manager; // A reference to the framework's manager

audio audio; // The audio subsystem

Edit:

I was curious to see if Bjarne Stroustrup himself has something to say on this issue. Apparently, he hasn't, but he suggests coding conventions that would work around my compiler problems:

For example, capitalize nonstandard library user-defined types and start nontypes with a lowercase letter

That'd be consistent with STL and boost, so I might use that. However, most of you agree that this naming should be avoided whether it compiles or not. So does Stroustrup:

it is unwise to choose names that differ only by capitalization.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

提笔书几行 2024-09-23 08:54:44

本地含义很少是该类型的良好唯一全局描述:

cartesian_point_2d position;  // rectangular, not polar coordinates
mouse_over(ui_entity entity); // not a business layer entity
xyz_manager& manager;         // what's a manager without something to manage?
audio_system audio;

The local meaning is rarely a good unique global description of the type:

cartesian_point_2d position;  // rectangular, not polar coordinates
mouse_over(ui_entity entity); // not a business layer entity
xyz_manager& manager;         // what's a manager without something to manage?
audio_system audio;
醉殇 2024-09-23 08:54:44

为变量提供与其类型相同的名称几乎总是一个坏主意,因为这使得很难分辨哪些代码引用该类型以及哪些代码引用该变量。例如,考虑以下类:

struct position
{
    void operator()() { }
};

// later on, somewhere:
position position;

现在,如果我们看到一行代码使用:

position()

我们无法轻易判断它是构造 position 对象还是调用 position::operator() ()。我们必须返回并查看当前范围内是否存在名为 position 的对象。

命名约定是一件非常敏感、主观且有争议的事情。我只是建议选择一种以某种方式区分类型和变量的方法。就我个人而言,我选择将类型大写,并将变量保留为以小写字母开头。

如何区分它们并不重要(使用大写或尾部下划线的建议都很常见),只要您的用法保持一致即可。

Giving a variable the same name as its type is almost always a bad idea, because it makes it very difficult to tell what code refers to the type and what code refers to the variable. For example, consider the following class:

struct position
{
    void operator()() { }
};

// later on, somewhere:
position position;

Now, if we see a line of code that uses:

position()

we can't readily tell whether that constructs a position object or calls position::operator()(). We have to go back and see whether there is an object named position currently in scope.

Naming conventions are a very touchy, subjective, and argumentative thing. I would just recommend picking one that distinguishes types from variables in some way. Personally, I choose to capitalize my types and leave my variables as starting with a lowercase letter.

It doesn't really matter how you distinguish them (your suggestions of using capitalization or a trailing underscore are both common), just so long as your usage is consistent.

兰花执着 2024-09-23 08:54:44

根据变量的类型来命名变量确实是一种不好的做法。代码应该尽可能与类型无关。这意味着对实际类型的任何引用都应仅限于声明(同样,尽可能多)。尝试将类型信息嵌入到变量名中会违反该原则。不要这样做。

人们可能想要嵌入到变量名称中的是变量的语义。如“宽度”、“长度”、“索引”、“坐标”、“矩形”、“颜色”、“字符串”、“转换器”等。不幸的是,许多人在看到它时,错误地认为名称的这些部分旨在描述变量的类型。这种误解常常使他们在稍后的代码中陷入这种糟糕的做法(按照变量的类型命名变量)。

这种误解的一个典型的众所周知的例子就是所谓的匈牙利表示法。匈牙利表示法意味着在变量名称前添加描述变量语义的特殊统一前缀。在这种原始形式中,匈牙利表示法是一种非常有用的良好命名约定。然而,在许多实际情况下,它会被扭曲成完全不同的东西:在变量名前加上描述其类型的前缀。后者当然不是一个好主意。

Naming variables after their type specifically is indeed a bad practice. The code is supposed to be as type-independent as possible. That implies that any references to actual types should be restricted to declarations (again, as much as possible). Trying to embed type information into variable name would violate that principle. Don't do it.

What one might want to embed into variable name is the variable's semantical meaning. Like "width", "length", "index", "coordinate", "rectangle", "color", "string", "converter" and so on. Unfortunately, many people, when they see it, incorrectly assume that these portions of the names are intended to describe the type of the variable. This misunderstanding often makes them to engage into that bad practice (of naming variables after their types) later in their code.

A classic well-known example of such misunderstanding is so called Hungarian notation. Hungarian notation implies prefixing variable names with special unified prefixes that describe the semantic of the variable. In this original form Hungarian notation is an extremely useful good naming convention. However, in many practical cases it gets distorted into something completely different: prefixing the variable names with something that describes their type. The latter is certainly not a good idea.

在巴黎塔顶看东京樱花 2024-09-23 08:54:44

是的,这是一个不好的做法。如果变量名具有较长的生命周期或重要的含义(临时变量也可以),则变量名应该更具体。请记住,C++ 的类型非常严格 - 您不能拥有一个变量,但又不确定它的类型是什么。例如,变量 Type 类型基本上仅意味着它没有名称。

Yes, it is a bad practice. Variable names should be more specific if they have a long lifetime or important meaning (temporaries are ok). Remember that C++ is very strictly typed- you can't have a variable and not be very sure what it's type is. A variable Type type, for example, basically just means that it doesn't have a name.

表情可笑 2024-09-23 08:54:44

就我个人而言,我将班级名称大写。

我不同意,在这种具体情况下,“选择仅大小写不同的名称是不明智的”。选择容易混淆的相似名称是不明智的。 PoSItIoNPoSiTIoN 非常相似。 Positionposition 不是。只要确保当您搜索代码时,您知道并且可以控制搜索时区分大小写还是不区分大小写。

如果我有一个只使用特定类型的一个变量的函数,那么我可能会以该类型来命名它,因为在英语中,如果某件事是“我们正在谈论的唯一位置”,我们会指它是“位置”。因此,变量名称可以合理地为position

如果做不到这一点,在你的例子中我可能会选择:

position pos;  // pretty sure people will realise I don't mean "positron".

mouse_over(entity target) // Returns true if the mouse is over the entity

manager &fmanager; // A reference to the framework's manager

devices::audio audio; // The audio subsystem
audio self; // "this" audio subsystem
audio audio_out; // The audio subsystem I'm configured to use for output

最后一个例子应该表明这些问题可以通过命名空间来解决 - 在定义 audio 的命名空间之外,你可以安全地将其称为音频。在该命名空间内,经常对音频子系统进行操作的函数要么是音频类接口的一部分,而这些接口恰好是自由函数(在这种情况下,请使用诸如 self、< code>other、lhsrhs),或者是某种具有音频子系统作为依赖项的分层设备或系统(在这种情况下,出于什么目的而依赖?)。

顺便说一句,entitymanager 对于类来说是糟糕的名称,因为它们都没有告诉您有关该类代表什么的任何信息。每一个离散的事物都是一个“实体”,虽然并非所有事物都管理其他事物,但“管理”却是极其模糊的。

Personally, I capitalise my class names.

I disagree with, "it is unwise to choose names that differ only by capitalization", in this specific case. It's unwise to choose names which are confusingly similar. PoSItIoN and PoSiTIoN are confusingly similar. Position and position are not. Just make sure that when you search the code, you know and can control whether you're doing so case-sensitive or insensitive.

In cases where I have a function that only uses one variable of a particular type, then I might well name it after the type, since in English if something was, "the only position we're talking about", we'd refer to it as, "the position". Hence the variable name could reasonably be position.

Failing that, in your examples I might go with:

position pos;  // pretty sure people will realise I don't mean "positron".

mouse_over(entity target) // Returns true if the mouse is over the entity

manager &fmanager; // A reference to the framework's manager

devices::audio audio; // The audio subsystem
audio self; // "this" audio subsystem
audio audio_out; // The audio subsystem I'm configured to use for output

The last example is supposed to indicate that these problems might be solved by namespaces - outside the namespace in which audio is defined, you can safely refer to it as audio. Inside that namespace, functions operating on the audio subsystem frequently either are parts of the audio class interface which just happen to be free functions (in which case use conventions like self, other, lhs, rhs), or else are some kind of layered device or system which have an audio subsystem as a dependency (in which case, dependency for what purpose?).

entity and manager are terrible names for classes, by the way, since neither of them tells you anything about what the class represents. Every discrete thing is an "entity", and while not everything manages something else, "manage" is hopelessly vague.

笑咖 2024-09-23 08:54:44

这就是为什么我采用旧的 MFC 做法,在成员变量前添加 m_ 前缀,如“m_position”。许多 Java 人出于本质上相同的原因会做“thePosition”,尽管如果你当时指出相似之处,他们会变得有趣并对你咆哮。

This is why I picked up the old MFC practice of prefixing member variables with m_, as in "m_position." A lot of the Java people would do "thePosition" for essentially the same reason, though if you pointed out the similarity at the time they'd turn funny colors and rant at you.

子栖 2024-09-23 08:54:44

我经常遇到同样的“问题”。我认为这是一个抽象问题:对于 Position,我建议进一步抽象并引入 Point 类型或类似的东西。或者指定ment是什么位置:

position mouse_pointer_pos;

I have the same "problem" on a regular basis. I think it's a problem of abstration: In case of Position I'd suggest to abstract a bit more and introduce a type Point or something like that. Or specify what position is ment:

position mouse_pointer_pos;
原谅我要高飞 2024-09-23 08:54:44

简短且半错误的答案:如果您在一个地方有足够的变量需要非神秘的变量名称,则可能您的变量太多。

尽管在某种程度上我实际上不同意这一点。我认为它有一定道理,但仅此而已。

C++ 中的一些短变量名称只是传统的,人们知道它们的含义,因为他们已经使用 C/C++ 编程有一段时间了。使用 i 作为索引变量就是一个示例。

我认为变量名应该根据其用途来命名。职位是什么职位?经理管理什么?为什么音频子系统的这个特定实例需要存在?

结尾的 _ 表示法用于区分成员变量名称。当有人突然开始提到 x 时,看到 x_ 并知道它来自类,并且不是在封闭范围或全球范围。

Short and semi-wrong answer: If you have enough variables that you're working with in one place that you need non-cryptic variable names, maybe you have too many variables.

Though I actually disagree with that, to some extent. I think it has a grain of truth, but only that.

Some short variable names in C++ are just traditional and people know what they mean because they've been programming in C/C++ for awhile. Using i for an index variable is an example.

I think variable names should be named for their purpose. What's the position the position of? What's the manager managing? Why does this particular instance of the audio subsystem need to exist?

The trailing _ notation is used to distinguish member variable names. It can be very helpful when someone starts mentioning x out of nowhere to see x_ and know that it's coming from the class, and isn't declared in an enclosing scope or the global scope.

幽蝶幻影 2024-09-23 08:54:44

遵循现有的指南,例如 Google 的 C++ 风格指南

您可以 意识到命名是一个重要问题,但根据我的经验
过多地思考它与不了解它一样有害。

我尝试过匈牙利语,但不喜欢它,我见过的大多数优秀程序员
知道不要用它。

我要说的要点是它使代码的可读性降低。

You can just follow existing guidelines, e.g. Google's C++ style guide

It's good to be aware of naming being an important issue, but in my experience
thinking too much about it is as harmful as not being aware of it.

I've experimented with Hungarian and didn't like it, most good programmers I
know don't use it.

The main point I would make is it makes code less readable.

森罗 2024-09-23 08:54:44

不,我偶尔会这样做,这不会在 Microsoft 世界中造成问题。例如,

class compiler
{
    symbol_table symbol_table;
};

从未引起任何混乱。顺便说一句,我称我的猫为“猫”,这也没有引起混乱。

No, I do this on occasions and it does not cause problems in the Microsoft world. For example,

class compiler
{
    symbol_table symbol_table;
};

has never caused any confusion. By the way, I called my cat 'cat' and that hasn't caused confusion either.

烟雨凡馨 2024-09-23 08:54:44

在我看来,这种命名约定的最大问题是程序员不清楚表达式是指类型还是对象。消除这种歧义的一种方法是将代码包装在命名空间内(理应如此)并使用显式限定,即使在内部使用时也是如此:

namespace my_ns {

struct audio { ... };
struct string { ... };

// Internal function whose logic doesn't require explicit qualifications.
void do_something()
{
    // Use explicit qualification nevertheless.
    my_ns::audio audio;
    audio.play("impenetrable.sd2"); // okay

    my_ns::string string;
    string.size();          // okay
    // string{}.size();     // oof, tryna re-instantiate object? compilation error
    my_ns::string{}.size(); // okay, size of just created temporary string
}

}

这非常类似于使用标准类型(例如 std::stringstd::string)的方式代码>.由于所有用户定义的类型都将使用其名称空间进行限定,因此类型和对象之间不会存在歧义。当然,这样做的缺点是更加冗长:

namespace my_ns {

struct audio {
    // Using explicit qualification; pretty verbose.
    void play(my_ns::string a1, my_ns::string a2, my_ns::string a3);

    // Without explicit qualification; saves 21 characters.
    void play(string a1, string a2, string a3);
};

}

The biggest problem with this naming convention imo is that it's unclear to the programmer whether an expression refers to a type or an object. A way to eliminate such ambiguity is by wrapping your code inside a namespace (as it should) and using explicit qualifications, even on internal usage:

namespace my_ns {

struct audio { ... };
struct string { ... };

// Internal function whose logic doesn't require explicit qualifications.
void do_something()
{
    // Use explicit qualification nevertheless.
    my_ns::audio audio;
    audio.play("impenetrable.sd2"); // okay

    my_ns::string string;
    string.size();          // okay
    // string{}.size();     // oof, tryna re-instantiate object? compilation error
    my_ns::string{}.size(); // okay, size of just created temporary string
}

}

This is much like the way you use standard types such as std::string. Since all user-defined types will be qualified with their namespace, there'll be no ambiguity between types and objects. The downside of this is, of course, more verbosity:

namespace my_ns {

struct audio {
    // Using explicit qualification; pretty verbose.
    void play(my_ns::string a1, my_ns::string a2, my_ns::string a3);

    // Without explicit qualification; saves 21 characters.
    void play(string a1, string a2, string a3);
};

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文