我有一个变量,我像一个常量(它永远不会改变)。我无法将其声明为常量,因为该值会在运行时添加。像常量一样工作的变量的命名约定
你会利用变量名来帮助你理解数据的含义吗?
或者你会不是因为这违反了约定,使事情更混乱?
较大的问题:
即使场景不是典型的场景,但您是否遵守了约定,但足够接近以至于它本身可以帮助您理解事物?
我有一个变量,我像一个常量(它永远不会改变)。我无法将其声明为常量,因为该值会在运行时添加。像常量一样工作的变量的命名约定
你会利用变量名来帮助你理解数据的含义吗?
或者你会不是因为这违反了约定,使事情更混乱?
较大的问题:
即使场景不是典型的场景,但您是否遵守了约定,但足够接近以至于它本身可以帮助您理解事物?
封装它。
#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
被称为不止一次例外。
是否可以将其标记为只读?那么公约并不重要。
如果它能帮助您(和其他人)在六个月的时间内理解您的代码,请执行此操作。如果不行,不要。这真的很简单。
就我个人而言,我会利用它。这是Java中的惯例,由于其面向对象的性质,常量总是在运行时分配。我知道如果我不小心分配给它,我肯定会注意到下一次扫描这段代码。
我会将它命名为变量,我更愿意保持我的命名非常一致。 正如Rob已经提出的那样,readonly(至少在C#中可用)。 或者一个没有setter的房产。
我不认为我的个人需要在这里至高无上 - 如果我已经编写了代码,那么在未来如果需要的话,我已经比其他任何人更适合回溯;所以我首先要说的是“任何人” - 一个现在或未来的队友,他们需要像我一样彻底地理解代码(理想情况下)。除了强制性的代码评审作为向代码库提交任何东西的先决条件(一种极好的做法,以及我目前雇主的无条件的规则)之外,如果我曾经让我的注意力集中起来,我很可能会被调用它(这确实发生了 - 这就是为什么我喜欢这些强制性代码评论,适用于我自己以及其他人!)。
“在启动时只设置一次变量”是一个足够特殊的情况,可能值得添加到您的团队的指导方针中 - 将其视为“比变量更接近常数”可能会很有意义,但只有在整个代码库中统一使用相同的规则/准则时才有所帮助。如果规则不存在,我会检查是否存在关于添加它的共识;否则,为了我个人的口味,我不会违背准则......这就是“自我编程”和“代码库团队所有权”的根源,这是我用燃烧热情服务的两个原则。顺便说一下,在编码准则方面,我是一个单人团队(虽然这不是一个最佳的情况,但我觉得我可以毫无争议地获得一致的一致意见,即“一旦启动“变量作为常量,就命名惯例而言! - )。但是对于一个更大的团队来说,这是更多的工作,而且可以采用任何方式。
如果我可以投票多次,我会这样做。这正是正确的答案。好的命名是一致的沟通的一部分,这意味着正确的答案不是我们任何人的感受,而是关于团队和组织。 – CPerkins 2009-08-30 16:33:21
@CPerkins,谢谢!我们完全同意。 – 2009-08-30 18:30:44
你遵循惯例,即使 情况是不典型的 公约,但足够接近,这 可以帮助你,身体力行, 了解的东西?
遵循一个约定,当情景是非典型的时候可能会混淆或减慢其他人(或者甚至在一段时间后)。我会避免给变量赋予它不是的东西的幌子。
而且,事实上,你有这种非典型的情况可能是,也许一些其他的,比较典型的模式可以遵循的指示。虽然,我没有任何立即建议替代方案。
我想使它成为资本(因为它是不是从设计的角度可变更恒定),并添加周围,说明其独特的应用程序的注释。
FWIW我自己的习惯是使用所有盖帽为#define
S和对枚举。对于const
变量我要么使用没有特别的约定,或者当我做它与一个“k
”的前缀名称(“konstant” - 不是“c
”这已经是在使用的东西像“数”或“字符”) 。
我发现我喜欢'k
'约定,并且可能会更频繁地使用它,甚至可能将它用于枚举,为可怕的预处理器宏保留尖叫的全帽标识符。
首先,按照您项目的编码标准。你应该为其他人阅读代码编码,而不是你自己。您的个人喜好不应该优先于项目级的规则和惯例等
在没有项目编码标准,你应该遵循你正在处理的语言“最佳做法”。
在Java中,最佳实践是您应该使用camel case标识符声明伪常量。这就是Sun Java编码标准所说的,这也是绝大多数专业Java开发人员所使用的。
在C和C++中,(经典)约定是全部大写字母用于定义为预处理符号的常量。因此,由于这不是预处理符号,因此您应该使用您的编码标准认为适用于某个变量的任何符号。
伪常数不应该改变的事实不会阻止某人修改代码,使其实际发生意外或故意更改。如果使用/滥用是一种编码规范,使标识看像一个真正的constaint,你将成为问题的一部分:
实际上,处理伪常量的一种更好的方法是封装它。在Java中,您将声明它为私有成员并提供getter和setter。 setter应该做些什么来防止伪常量在第一次被设置后被改变。任何体面的Java JIT编译器都会内联一个简单的getter,所以这不会影响运行时性能。
约定就是这样,约定。他们在那里帮助代码可以理解。如果他们选择得不是太差,并且他们一贯使用,他们通常会这样做。最后一点大概是他们最重要的事情:就应该始终如一地应用。
其中有一点是防止一些公约,使代码更易读,即使他们一贯性原则 - 至少对于新来者和人民的代码库之间进行切换 - 是当他们与其他公约发生冲突。在C和C++中,我知道两个有关在ALL_CAPS中使用名称的常见约定:
为预处理器保留它们;作为预处理器标识符,我认为它是特殊的:它们不遵守通常的作用域规则并且防止与它们发生冲突很重要
将它们用于常量(宏和枚举器)。
两个问题来,除了不熟悉,如果你使用他们的逻辑不变的东西这些都是事实变量:
他们不在的地方(如数组大小)可用,其中语言想到常量表达式
我的经验教我,维修往往会令他们更不恒定的,他们现在的样子。
使用单个私有静态字段创建包装类。创建一个initField(..)和一个getField(..)静态方法。如果静态字段不为空,initField将抛出/断言/否则错误。 (原语,你可能需要使用一个原始和一个布尔跟踪初始化。)
在java中,我更喜欢通过这些不同类型的变量为系统属性。然后用静态类可以做这样的事情:而不是使用-D指定它
public final int MY_INT = Integer.getInteger("a.property.name");
你也可以使用一个属性文件(参见java.util.Properties)。然后你得到:
public class Foo {
public static final int MY_INT;
static {
Properties p = new Properties();
try{
p.load(new FileInputStream("app.props"):
} catch(IOException e) {
//SWALLOW or RETHROW AS ERROR
}
MY_INT=Integer.parseInt(p.getProperty("my.int","17")); //17 is default if you swallo IOException
}
...
}
我的直接印象是什么,你“在运行时设置,则永远不会改变”是一个常数,但必须以业务规则是不变的。另外,你应该使用mutators/accessors,因为使用ALL CAPS几乎不能保证“常量”。
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.");
}
}
}
如果你总是使用赋值函数来设置的值,即使在[BetterClass]本身,你知道,Foo的“不变性”不被侵犯。当然,如果有人直接设置foo的值(我需要在凌晨2点之前退出工作!),但仍然没有保证。但是代码审查应该指出类似的东西。
所以我的建议是把foo当作普通的成员变量 - 对于几乎是const的东西,不需要特别的命名约定。
但是,即使在私有变量上也要使用增变器/存取器。这些通常非常快,您可以在其中执行业务规则。这应该是你的惯例。
(如果您正在为嵌入式医疗设备编写代码,请假装您从未看过此贴子)。
提供错误信息通常不是最佳实践。
隐含声称的东西是一个常数,当它只是目前没有改变,是发出错误的信息。
一个问题是:什么样的变量?
在静态变量的情况下,在我称之为缺少更好的术语的“启动时”之后不会改变,我使用ALL_CAPS ...对于全局变量也是如此(如果语言支持他们的话)......
通信语义实际上是命名约定,并看到一个ALL_CAPS明确规定的点,即A)我不会写它二)我可以缓存它(到一个局部变量例如,或者在AS3中,即使是一个实例变量也是有意义的,因为静态访问非常缓慢)...
它是否是“真正的常量”并不重要......这更多的是实现细节,应该隐藏起来(可靠!信息信息隐藏是好的,也是重要的,但至关重要的是,共享的信息是值得信赖的)......它可以真正交换......例如,我经常开始构建应用程序与一些硬编码配置,包含一些静态常量...后来,我决定我不希望这是硬编码的,而是来自某个配置文件,所以我加载它,并在启动过程中,我启动所有的伪常量...实际的应用程序仍然把它们视为常量,因为在启动后,这就是这些值...这对我来说似乎是完全有效的......
在实例级别,我不是100%确定,如果我曾经跑过变成一个案例,在那里我可以很肯定地说,一些领域永远不会改变...通常,这使得这个班不灵活...
其他的临时工ñ,你可以通常声明只读属性,有编译时错误,这也是一件好事...
我不确定这是否是您的选择语言是合法的,但在C++中,这会为你工作的目的:
#include <iostream>
int main()
{
int i = 0;
std::cin >> i;
const int CONST = i;
std::cout << CONST; //displays i
system("PAUSE");
return 0;
}
我不知道这是做一个道德的事情,但是这确实解决你的问题(除非你真的需要你的记忆)。
就像其他任何东西 - 范围和上下文都需要知道什么东西是恒定的。所以 - 没有办法满足每个人。
按照您选择的语言使用的样式 - 80%的时间,这将是足够清晰。另一种选择是高度超越命名系统,为了达到理想的技术正确性而牺牲生产力(如果你能达到这个目标,很少有人甚至会真正意识到这一点。)
在Java中,他可以声明它是最终的并且可以完成它。 – 2009-08-30 09:30:09