我偶然发现了||=()
的Ruby成语,
如:
def app_logger
@app_logger ||= (
logfile = File.open(::Rails.root.join(LOG_FILE), 'a')
logfile.sync = true
AppLogger.new(logfile)
)
end
我尝试使用{}
代替()
,但它无效。我认为{}
意味着包围一个区块。
这是一个已知的成语吗?这是一种好风格吗?
我没有找到关于这种括号使用的文档。任何指针都会有所帮助。
请注意,这篇文章是关于()
这种方式的使用,而不是||=
的使用。关于后一种习语的帖子很多。
答案 0 :(得分:6)
像Ruby中的很多事情可以完成,其中许多不应该完成,这就是其中之一。
当已经存在其他设施时,使用括号对代码进行分组可能会造成混淆,并且几乎肯定与许多编码样式指南相反。如果我在管理的代码中看到这个,我会马上修复它。
最好的方法是使用begin
/ end
标记来完全清楚发生了什么:
def app_logger
@app_logger ||= begin
logfile = File.open(::Rails.root.join(LOG_FILE), 'a')
logfile.sync = true
AppLogger.new(logfile)
end
end
Ruby中的很多东西都评估为单个值,而(...)
的内容显然是其中之一。
你foo ||= (a=10; a+10)
“更好”的另一个例子也颇具争议。这会进行两次分配和添加,但只是有条件的。通过begin
/ end
,使用a+10
/ a+10
可以更好地以长篇形式编写此文件,以明确if
为结果。
从样式的角度来看,隐藏“重要”部分,{{1}},在一行的末尾是不好的,它可以被忽略。将它作为最后一行使其非常清楚。这也是为什么在长行末尾添加{{1}}语句也很糟糕的原因,它隐藏了只有条件执行的行。
对于简洁性的关注总是被可读性的担忧所压倒。在磁盘上保存几个字节不会对你有所帮助,因为有人误读了你的代码,他们引入了一个严重的错误。
当你陷入自己的聪明之中时,那个某人可能会成为你的未来。在某些时候,我们所有人都遇到了。
答案 1 :(得分:2)
除了@ tadman的答案之外,我还反驳说,以类似Ruby的方式编写方法可以保持可读性并保持良好和紧凑:
def app_logger
return @app_logger if @app_logger
logfile = File.open(::Rails.root.join(LOG_FILE), 'a')
logfile.sync = true
@app_logger = AppLogger.new(logfile)
end
我的意图和理由以这种方式写作,请参阅我对@ fotanus评论的回答。
当我们学习编程和学习新语言时,我们的大脑习惯于看到模式。无论模式是由调试器发出的十六进制代码还是C,Perl,Python,Java或Ruby,我们仍然会看到模式。当我们习惯于看到它们时,我们倾向于将代码更改为类似于那些熟悉的结构。这就是为什么Perl和C程序员最初倾向于编写Java,Python和Ruby,如C和Perl。 “美丽在旁观者的眼中”,但同样的美丽是一种杂草,当它不合适时,就像野花在正式花园或球道中间不合适一样。我们应该用编程语言的白话来写,因为那是居住在那片土地上的人所期待的说话方式。
要记住的是,虽然我们个人可能是一个代码精灵怪物,可以将代码从多行减少到单个字符,让我能够完成工作的是能够编写代码其他人们可以理解,而不必具备相同的口径。代码运算总是达到收益递减点,在它被缩减到最小尺寸之前,特别是当代码在生产环境中运行并且由初级程序员维护并且需要扩展或调试它时,时钟在滴答作响。 Minutes = dollars
我工作的地方,美元有很大的乘数,当炸弹炸弹爆炸时,墙壁会像蟑螂一样泄漏经理。 (哦......我给经理蟑螂打电话了吗?无论如何。)
在活动结束后的早晨被召唤并感谢编写代码使他们能够轻松地调试/修复或修改/扩展比在凌晨2:45调用并要求上网帮助更好。我重视我的睡眠和我的编码伙伴的睡眠,并推动可维护的代码成为我们的首要任务。
这是我的0.02美元。
答案 2 :(得分:0)
在我看来,圆括号真是难看。为什么不在创建logger到方法后委托逻辑?
def app_logger
@app_logger ||= instantiate_app_logger
end
def instantiate_app_logger
logfile = File.open(::Rails.root.join(LOG_FILE), 'a')
logfile.sync = true
AppLogger.new(logfile)
end
但我担心它会打破一些OOP,你的代码也会。为什么AppLoger类无法根据传递的路径打开文件并开启同步?它会更清洁。