浏览 20828 次
锁定老帖子 主题:Ruby Quiz
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-04-14  
potian 写道
cookoo 写道
Trustno1 写道
@timeout = options["timeout"] || DEFAULT_TIMEOUT

按我这个行业的习惯,这样写真的很成问题.一来||的左右求值序到底是那种并不确定,依赖于语言和编译器解释器的实现.第二,如果  options["timeout"] 如果是一个函数运算,这个函数是不是执行依赖于||另外一端的求值以及编译器是不是进行截断求值,非常的可怕的写法.


在c是个问题, 在ruby不是问题, 呵呵.


c 有问题吗,10多年用下来好像还是第1次听说


比如说这种代码把

bool c=a==true||do_something()==false;
这种代码就是二义性的.do_something到底是不是执行,仰赖于a的取值.你不能保证在有side effection的情况下,a的求值总是满足do_something的调用条件.
而且在某些安全性的情况下,比如说我通过内存溢出的漏洞,覆盖a的值,那么就能控制do_something的执行.这是一种非常危险的写法.
所以我的倾向是,||,&&只用于bool型变量的运算,而不要带任何函数返回值的运算.
0 请登录后投票
   发表时间:2006-04-14  
1. 不管是用Ruby写还是用Java写,良好的编程和阅读习惯都不需要指明类型,因为上下文已经说得很清楚了,如果你这样去阅读代码,恐怕一天读不了几句话.代码可理解性的关键在于明确表达你的逻辑和计算意图,匈牙利命名法在这一点上是有害的,你必须首先把变量中的类型部分去掉,才能开始阅读真正的代码含义.最可读的代码是最接近自然语言,不包含缩写(或者只用众所周知的缩写)

2. 你恐怕搞错了动态和强弱类型之间的区别
Ruby虽然是动态语言,但它却是强类型的,它当然知道这是一个Hash.关于副作用,我不懂什么意思,这是写代码的人决定的,有时侯确实需要利用副作用,这和可读性有什么关系.

你讲的对称性我也不理解
0 请登录后投票
   发表时间:2006-04-14  
gigix 写道
zkj_beyond 写道
脚本语言可以写出十分灵活的代码。可它比较难懂
通常不会比Java程序更难懂,我觉得


引用
<script>
var str = "I had a ((gem:an adjective)) sandwich for lunch today. It dripped all over my ((gem)) and ((a noun)). ";
/**** Start ****/
var h = {};// it's a Hash
document.write(str.replace(/\(\(([^)]+)\)\)/ig,function($1,$2){
        var k = $2.split(":")[0],o=$2.split(":")[1]||k;
        return "<b style='color:red'>"+ (h[k]||(h[k]=prompt("Give me "+o,"")))+"</b>";
}));
</script>


ruby我还没开始,就javascript代码。
1、在javascript中把函数当成参数传递,确实比较难懂。
2、按照马叔的重构里说,尽量用小函数代替那些复杂的代码。
3、象以上代码如果我是
var str = "I had a ((gem:an adje:cti:ve)) sandwich for lunch today. It dripped all over my ((gem)) and ((a noun)). ";
0 请登录后投票
   发表时间:2006-04-14  
Trustno1 写道
potian 写道
cookoo 写道
Trustno1 写道
@timeout = options["timeout"] || DEFAULT_TIMEOUT

按我这个行业的习惯,这样写真的很成问题.一来||的左右求值序到底是那种并不确定,依赖于语言和编译器解释器的实现.第二,如果  options["timeout"] 如果是一个函数运算,这个函数是不是执行依赖于||另外一端的求值以及编译器是不是进行截断求值,非常的可怕的写法.


在c是个问题, 在ruby不是问题, 呵呵.


c 有问题吗,10多年用下来好像还是第1次听说


比如说这种代码把

bool c=a==true||do_something()==false;
这种代码就是二义性的.do_something到底是不是执行,仰赖于a的取值.你不能保证在有side effection的情况下,a的求值总是满足do_something的调用条件.

这种两义性确实可能造成不可读性,但是这是你写成这样的,早期的C程序里面确实有人把这种东西用到极端,一个循环只有一个条件等等的情况,但合理地运用这种副作用也是C的一个习惯用语.任何东西都是一个度的问题,

引用

而且在某些安全性的情况下,比如说我通过内存溢出的漏洞,覆盖a的值,那么就能控制do_something的执行.这是一种非常危险的写法.

C是弱类型的,Ruby是强类型的,但这和可读性问题不大


引用

所以我的倾向是,||,&&只用于bool型变量的运算,而不要带任何函数返回值的运算.

度的问题,前面我写的话可以读成

超时等于传入的参数,否则使用缺省值,否则....
0 请登录后投票
   发表时间:2006-04-14  
zkj_beyond 写道
gigix 写道
zkj_beyond 写道
脚本语言可以写出十分灵活的代码。可它比较难懂
通常不会比Java程序更难懂,我觉得


引用
<script>
var str = "I had a ((gem:an adjective)) sandwich for lunch today. It dripped all over my ((gem)) and ((a noun)). ";
/**** Start ****/
var h = {};// it's a Hash
document.write(str.replace(/\(\(([^)]+)\)\)/ig,function($1,$2){
        var k = $2.split(":")[0],o=$2.split(":")[1]||k;
        return "<b style='color:red'>"+ (h[k]||(h[k]=prompt("Give me "+o,"")))+"</b>";
}));
</script>


ruby我还没开始,就javascript代码。
1、在javascript中把函数当成参数传递,确实比较难懂。
2、按照马叔的重构里说,尽量用小函数代替那些复杂的代码。
3、象以上代码如果我是
var str = "I had a ((gem:an adje:cti:ve)) sandwich for lunch today. It dripped all over my ((gem)) and ((a noun)). ";


我已经说了,这个例子的可读性不好,但是就这个例子,Ruby的Block也体现出好处了.

Ruby和其它脚本语言的区别之一,特别是Perl和PHP,在于它继承了很多Smalltalk里面"正统"的东西,它从一开始就是把自己的目标定义为一种完全的面向对象语言,提供给程序员最自然的表达方式
0 请登录后投票
   发表时间:2006-04-14  
引用
我已经说了,这个例子的可读性不好,但是就这个例子,Ruby的Block也体现出好处了.

Ruby和其它脚本语言的区别之一,特别是Perl和PHP,在于它继承了很多Smalltalk里面"正统"的东西,它从一开始就是把自己的目标定义为一种完全的面向对象语言,提供给程序员最自然的表达方式

先自打一大板。

昨天看了这个贴子后我就下载了ruby。
0 请登录后投票
   发表时间:2006-04-14  
potian 写道
1. 不管是用Ruby写还是用Java写,良好的编程和阅读习惯都不需要指明类型,因为上下文已经说得很清楚了,如果你这样去阅读代码,恐怕一天读不了几句话.代码可理解性的关键在于明确表达你的逻辑和计算意图,匈牙利命名法在这一点上是有害的,你必须首先把变量中的类型部分去掉,才能开始阅读真正的代码含义.最可读的代码是最接近自然语言,不包含缩写(或者只用众所周知的缩写)

问题是,如果不需要上下文就可以了解清楚的事情,就没必要劳烦上下文了,所谓求人不如求己。
否则,还要取决于DEFALUT_TIMEOUT离这个语句的语法距离。按照惯例,不会太远,也不会太近,取决于团队对于常量声明位置的约定。
前面说过,阅读代码至少有两种情形,一种是为了理解代码,另一种是在出错的时候查找问题甚至有时候还要修改代码。如果仅仅为了理解,那么我同意你说的
引用

代码可理解性的关键在于明确表达你的逻辑和计算意图

但是,如果是为了查错,那么,不仅仅需要看明白这段代码想干什么,还要整明白代码是不是正确的干了它想干的事情。

引用

2. 你恐怕搞错了动态和强弱类型之间的区别
Ruby虽然是动态语言,但它却是强类型的,它当然知道这是一个Hash.

我必须承认,这是一个错误。把ruby和其它的一些动态语言搞混了。在一些语言里面,允许使用object['propertyName']的方式来访问属性。因为这个方式有它固有的方便性,所以我直接默认为ruby也有这个特性(应该没有?)
但这个和强弱类型没关系,只是运算符重载而已。
而且,动态强类型只是在赋值以后有意义,赋值阶段意义并不大。
就这个@timeout而言,在这个语句上你是看不出它的类型的。因为不知道options["timeout"]返回的是一个字符串,一个整数,还是其它什么的。只要返回的不是null,那@timeout的类型就是返回值的类型,否则,等于DEFAULT_TIMEOUT的类型。
通过这条语句,阅读者知道编写者想要表达的是@timeout的类型等同于DEFAULT_TIMEOUT的类型,但编写者是不是做到了这一点,必须看到过options['timeout']的赋值才能确定。
所以,如果仅仅为了理解意图,我认为看到这条语句就可以了。但是如果为了查错,那这条语句表述的信息是不充分的。

引用

关于副作用,我不懂什么意思,这是写代码的人决定的,有时侯确实需要利用副作用,这和可读性有什么关系.

OO里面副作用的定义感觉有点含糊,应该说是弱化了。
按说有副作用不是问题,只要把方法的目标明确的定义为产生副作用。但是,如果把这类函数放到条件子句里面,就会有问题,因为这个时候返回bool值是主要目的,其副作用很容易被代码阅读者忽略掉。而且,因为可能被短路,也会带来理解上的麻烦。


引用
你讲的对称性我也不理解

其实T1表述的意思比我更加严厉一点,我的倾向是逻辑运算符||/&&两边只能使用boolean型的变量,或者返回boolean变量的只读函数。
所谓对称性我的理解是在一个运算符左右不要出现不同类型的变量。否则,或者用到了语言的自动转型能力,这个时候就在考察阅读者的转型判断力,或者用到了另一些特性(比如这里的逻辑操作符把非null的当做true的处理)。实际上,ruby对于false的定义在这里帮了很大的忙,否则这个赋值语句问题就大了。

总的来说,我们对可读性的理解应该有出入。我的看法是可读性和代码长短并没有必然的关系(对单个函数而言),关键是不要在代码中使用一些隐含的东西或技巧。把该说的东西,用明确而又普通朴实的方式说出来,那可读性就强一些。当然,会很罗嗦。
或者,把阅读者当做语言的入门者。
0 请登录后投票
   发表时间:2006-04-14  
举个例子,从可读性的角度来说,下面的代码(假设max为奇数,否则更加没法比)
int sum=0;
for(int i=1;i<=max;i++);{
   sum += i;
}

肯定比
int sum = (1+max);/2 * max

要强。
当然,有时候为了效率,是需要牺牲可读性的。但是,是不是需要为了简洁而牺牲可读性呢?
0 请登录后投票
   发表时间:2006-04-14  
长短肯定是一个问题,但不是最重要的,我对可读性的理解很简单,就是最好按程序读下去就理解了

上面的代码不仅仅是在可读性上的差别,从语言翻译的角度来说,他们并不是等价性的,当然第一种在可读性上更好.(奇数偶数倒是没什么关系)

当然语言的熟悉是必须的,对C可读性好的写法,对Java不一定是可读的,每种语言都有它的习惯用语,我们是建立在对两种语言熟悉程度差不多的情况下,阅读代码的难易程度,譬如上面的代码,在ruby中写成
  (1..max);.inject { |sum, i| sum+i}


如果熟悉Ruby(或者smalltalk等等)就会读成从1到max,每个整数依此累加,

如果不熟悉,那就变成天书了.
0 请登录后投票
   发表时间:2006-04-14  
引用

上面的代码不仅仅是在可读性上的差别,从语言翻译的角度来说,他们并不是等价性的,当然第一种在可读性上更好.(奇数偶数倒是没什么关系)

那个式子有问题,所以导致奇偶数有关系,写成这样就没关系了:
int sum = (1+max); * max / 2

前面那个属于思维短路了。没去想交换律,

引用

当然语言的熟悉是必须的,对C可读性好的写法,对Java不一定是可读的,每种语言都有它的习惯用语,我们是建立在对两种语言熟悉程度差不多的情况下

应该说我们的最主要差异就在这里了,代码的编写者/评审者一般容易精通代码所使用的语言,但是阅读者很难说了。所以编写者的代码水平应当向预计的阅读者看齐。
或者说,最佳情况能够让菜鸟级的水平(刚入门的那种)看明白。这样,就可以让一个成本稍低的团队去维护一个成熟的分支代码库。
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics