类似常量的变量命名规范

3
我有一个变量,它像常量一样使用(它永远不会改变)。我不能将其声明为常量,因为值是在运行时添加的。
您是否会将变量名称大写,以帮助自己理解数据的含义?
或者您不会这样做,因为这违反了惯例并使事情更加混乱?
更大的问题是: 即使情境不符合惯例,但很接近以至于可能帮助您个人理解事物,您是否仍要遵循惯例?
16个回答

10

如果这样做有利于你(和其他人)在半年后理解你的代码,那就去做。如果没有好处,那就不需要做。其实很简单。

个人认为应该将它大写。在Java中,常量总是由于其面向对象的特性在运行时分配的约定。我会更加放心,因为如果我意外地给它赋值了,下次我浏览那一块代码的时候肯定会注意到。


9
我认为在这里我的个人需求不是最重要的——如果我已经编写了代码,那么在将来需要追溯代码时,我比任何其他人都更有优势;因此,我首先考虑的是“任何其他人”——一个现在或将来需要像我一样彻底理解代码的队友。

此外,在提交任何内容到代码库之前进行强制性的代码审查(这是一种绝佳的实践,也是我目前雇主的不变规则),如果我注意力不集中,我很可能会被召唤起来(这确实会发生——这就是为什么我喜欢那些强制性的代码审查,无论是对我自己还是对其他人!)。

“只在启动时设置一次的变量”是一个特殊的情况,可能值得将其添加到团队的指南中——将其视为“更接近于常量而不是变量”可能非常有意义,但只有在整个代码库中始终使用相同的规则/指南才有帮助。如果没有该规则,我会检查是否存在关于添加它的共识;否则,出于个人品味的考虑,我不会打破指南……这是“无自我编程”和“团队对代码库的所有权”的根本原则,我以炽热的热情服务于这两个原则。

顺便说一句,如果我在编码指南方面是单人团队(虽然这种情况并不理想),我认为我可以轻松获得一致同意,将“仅在启动时设置”的变量视为常量的命名约定!-)。但对于较大的团队来说,这需要更多的工作,并且结果可能无法预测。

1
如果我可以投票超过一次,我会这样做。这正是正确的答案。良好的命名是一致沟通的一部分,这意味着正确的答案不是我们中任何人感觉到的,而是关于团队和组织。 - CPerkins

1

我会给它命名为一个变量,我喜欢保持我的命名非常一致。 正如罗布已经建议的那样,readonly怎么样(至少在C#中可用)。 或者一个没有setter的属性。


1

把它封装起来。

#include <iostream>

class ParamFoo
{
    public:
        static void initializeAtStartup(double x);
        static double getFoo();
    private:
        static double foo_;
};

double ParamFoo::foo_;

void ParamFoo::initializeAtStartup(double x)
{
    foo_ = x;
}

double ParamFoo::getFoo()
{
    return foo_;
}

int main(void)
{
    ParamFoo::initializeAtStartup(0.4);
    std::cout << ParamFoo::getFoo() << std::endl;
}

这应该很清楚地表明,您不应该在应用程序启动之外的任何其他地方设置此值。如果您想要增加保护,可以添加一些私有的守卫 boolean 变量,以便在多次调用 initializeAtStartup 时抛出异常。

1

我的直觉是,你在运行时设置的东西,然后永远不会改变,只有在业务规则不变的情况下才是常量。此外,你应该使用mutators/accessors,因为使用全大写字母几乎不能保证“constness”。

public class BadClass
{ 
    public static final double PI = 3.1;     
      // PI is very constant.  Not according to the business roles modeled by my 
      // application, but by nature.  I don't have a problem making this publicly
      // accessible--except that [Math] already does, with much better precision)

    public static /*final*/ int FOO = null;
      // FOO is constant only by convention.  I cannot even enforce its "constness".
      // Making it public means that my enemies (overtime, for example) can change 
      // the value (late night programming), without telling me.
}

相反地,

public class BetterClass
{
    public static final double PI = 3.1;
    private /*final*/ Integer foo = null; 

    public int getFoo() {
        return this.foo.intValue();
    }
    public void setFoo(int value) {
        // The business rules say that foo can be set only once.
        // If the business rules change, we can remove this condition 
        // without breaking old code.
        if ( null == this.foo ) {
           this.foo = value;
        } else {
           throw new IllegalStateException("Foo can be set only once.");
        }
    }
}

如果您始终使用mutator来设置值,即使在[BetterClass]内部,您也知道foo的“constness”不会被违反。当然,如果有人要直接设置foo的值(我需要在晚上2点之前停止工作!),仍然没有保证。但是,这样的事情应该在代码审查中指出。

因此,我的建议是将foo视为普通成员变量--不需要为几乎是const的东西制定特殊的命名约定。

但是,即使对于私有变量,也要使用mutators/accessors。这些通常非常快速,并且您可以在其中强制执行业务规则。这应该是您的惯例。

(如果您正在编写嵌入式医疗设备的代码,请假装您从未看到过此帖子)。


0

可以将其标记为只读吗?那么惯例就不那么重要了。


0
你是否会遵循惯例,即使情况并不典型,但足够接近以至于可以帮助你个人理解事物?
在情况非典型的情况下遵循惯例可能会让其他人(甚至是你自己)感到困惑或减慢速度。我会避免将变量伪装成它不是的东西。
此外,你拥有这种非典型情况的事实可能表明其他一些更典型的范例可以被遵循。虽然我没有任何关于替代方案的直接建议。

0
我会将它大写(从设计角度来看,它比变量更加恒定),并在其周围添加注释,说明它在应用程序中的独特性。

0

就我个人而言,我的惯例是在#define和枚举类型中使用全大写字母。对于const变量,我要么不使用特定的约定,要么使用前缀为“k”的名称(表示“konstant”,而不是已经过度使用的“c”用于诸如“count”或“char”之类的东西)。

我发现我喜欢“k”约定,并可能更频繁地使用它,甚至可能将其用于枚举类型,将大声的全大写标识符保留给可怕的预处理器宏。


0
首先,遵循项目的编码标准。你应该为其他人阅读代码而编写代码,而不是为自己编写代码。你个人的偏好不应优先于项目范围内的规则和约定等。
如果没有项目编码标准,你应该遵循所处理语言的“最佳实践”。
在Java中,最佳实践是使用驼峰命名法声明伪常量。这是Sun Java编码标准所说的,也是绝大多数专业Java开发人员使用的方式。
在C和C++中,(经典的)惯例是将全大写用于定义为预处理器符号的常量。因此,由于这不是预处理器符号,你应该使用你的编码标准认为适合变量的任何内容。
伪常量不应该改变的事实并不能阻止某人意外或故意修改代码以使其实际更改。如果你使用/滥用编码约定使标识符看起来像真正的常量,那么你就是问题的一部分:
  1. 试图阅读/调试您的代码的人首先会假定标识符是一个真正的常量,而不会探究它可能不是的可能性。
  2. 然后当他们查看声明时,会有很多喊叫和威胁抛出窗外。

实际上,处理伪常量的更好方法是封装它。在Java中,您可以将其声明为私有成员并提供getter和setter。 setter应该做一些事情,以防止伪常量在第一次设置后被更改。任何体面的Java JIT编译器都会内联简单的getter,因此这不应影响运行时性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接