写点什么

Ruby 编程:清晰明确的代码还是简洁精炼的代码?

  • 2007-07-30
  • 本文字数:966 字

    阅读完需:约 3 分钟

Pier Cawley 撰文探讨了他在一篇介绍延迟初始化属性的博客文章中发现的潜在问题。出现问题的代码如下:

def content<br></br> @content ||= []<br></br>end这段代码的目的是为了支持类的延迟初始化属性。在这个例子当中,除非@content这个实例变量已经初始化完毕,否则在它的访问器方法content方法被调用的时候,它就会被初始化。||=这个操作符意思是“如果左边的变量值为nil,将它的值赋为右边表达式,否则仅返回左边的变量值。”

然而,Piers 指出,对于某些值来说,这样做是会出现问题的,因为 Ruby 处理布尔值和nil的方式比较特殊。我们来看看下面这样一个例子:

a = false<br></br>a ||= "Ruby"这样的代码结果是怎样的呢?由于a已经在第一行被初始化,第二行不应产生任何效果。然而,在代码执行之后,我们会发现a现在的值为"Ruby",而不是false

在熟记 Ruby 中编写nil检查通用方式之后,问题就变得非常显而易见:

if name<br></br> puts name.capitalize<br></br>end在 Ruby 中,nil被解释成布尔值false,因此if子句中的代码只有在name的值不等于nil的时候才能运行。

尽管在通常意义上这不会成为一个问题,但是在延迟初始化属性的代码中,如果付给属性的合法值是nil或者false的时候,这就会成为一个问题。在这种情况下,对属性进行访问之后,属性值就会被重设成缺省值。

当然,这是一个边界情况,但是这样的问题会导致人们花很长时间进行调试,来试图找出到底为什么某些方法有些时候会被重设而另外一些则不会。

Piers为这段代码给出了一个条理更为清晰的代码

def content<br></br> unless instance_variable_defined? :@content<br></br> @content = []<br></br> end<br></br> return @content<br></br>end这样,代码只会在变量还没有被定义的时候才会初始化变量。

通过这个小例子,我们可以把错误归咎于 Ruby 及其部分语言特性——但 _ 哪一类 _ 程序员会把错误归咎于工具而不是他们自身,这已经是众所周知的事实了。尽管 Ruby 代码的简洁性非常有用,但还是有一些情况下使用更加明确表达意图的表达式会更安全一些。在这个例子中,||=并非正确的解决方案,相反初始化代码应当检查变量是否已经被定义。

亲爱的读者,您在以前是否也被这样的问题敲中脑门呢?Ruby 是否存在哪些你希望避免的语言特性,以预防上述难于发现的问题呢?

查看英文原文: Explicit vs. concise code in Ruby

2007-07-30 09:001302
用户头像

发布了 117 篇内容, 共 20.7 次阅读, 收获喜欢 0 次。

关注

评论

发布
暂无评论
发现更多内容

【LeetCode】俄罗斯套娃信封问题Java题解

Albert

算法 LeetCode 28天写作

Open-Falcon 中的 LDAP 认证

冯骐

Python 运维 Open-Falcon ldap Go 语言

2021总结全网最新、最全、最实用Java岗面试真题!已收录GitHub

比伯

Java 编程 架构 面试 程序人生

Golang 中的并发限制与超时控制

冯骐

并发 超时 Go 语言

云安全和访问管理

龙归科技

云计算 安全 云端 企业安全

史上最全整合第三方登录的开源库

happlyfox

OAuth 2.0 28天写作 3月日更

GitHub上获赞10万star的高并发神级进阶资料,面试官再问高并发问题请你把这篇文章发给他!

Java架构之路

Java 程序员 架构 面试 编程语言

四面阿里成功斩获offer,在此分享我的复盘经验总结!

Java架构之路

Java 程序员 架构 面试 编程语言

迄今为止最好用的Flink SQL教程:Flink SQL Cookbook on Zeppelin

Apache Flink

flink

区块链产业革命:解决融资租赁之谜

旺链科技

区块链应用 融资租赁

LeetCode题解:190. 颠倒二进制位,移动n,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

用 Go 写一个轻量级的 ssh 批量操作工具

冯骐

运维 SSH Go 语言

拍乐云加盟UCloud优云精选计划,构建云上的美好互动

拍乐云Pano

ucloud 云服务 RTC 拍乐云 白板

交换机配置的自动备份与变更告警

冯骐

Python 运维 网络 备份 multissh

用 Nginx 的 auth_request 模块集成 LDAP 认证

冯骐

Python nginx 运维 ldap 认证

在主动要求涨工资这事上,不要学我!从第一份工资800开始说起

四猿外

程序员 涨薪 工资 收入 跳槽

神经网络攻防: 02.攻击模型的输出层

P小二

AIPwn AI安全 P小二 神经网络攻防

神经网络攻防:03.使用API修改神经网络参数

P小二

AIPwn AI安全 P小二 神经网络攻防

【经验分享】如何释放企业CMDB价值?——CMDB建设路径浅谈

嘉为蓝鲸

运维自动化 配置中心 CMDB 配置信息 配置管理

用 Go 写一个轻量级的 ldap 测试工具

冯骐

运维 开发 ldap Go 语言

思科设备漏洞 CVE-2018-0171 的快速修复

冯骐

Python 运维 安全 网络 交换机

《精通比特币》学习笔记(第一章)

棉花糖

区块链 读书笔记

Nginx安装后要做的第一件事

运维研习社

nginx WEB安全

Serverless 极致弹性解构在线游戏行业痛点

阿里巴巴云原生

Serverless 微服务 开发者 云原生 消息中间件

阿里P7亲自讲解!驱动核心源码详解和Binder超系统学习资源,跳槽薪资翻倍

欢喜学安卓

android 程序员 面试 移动开发

手把手教学,如何使用低代码快速构建应用程序步骤详解!

优秀

低代码

Pgbouncer最佳实践:系列四

PostgreSQLChina

数据库 postgresql 软件 开源社区

面试官:如何用SpringCloud从零设计一个大型电商平台?

Java架构追梦

Java 架构 面试 微服务 SpringCloud

软件开发,如何快速有效缩短项目周期

雯雯写代码

软件开发

阿里P7亲自讲解!如何快速的开发一个完整的直播app,成功入职腾讯

欢喜学安卓

android 程序员 面试 移动开发

都 2021 年了,也该抛弃 ExpressJS 了

LeanCloud

大前端 nodejs 框架

Ruby编程:清晰明确的代码还是简洁精炼的代码?_Ruby_Werner Schuster_InfoQ精选文章