通过语法醋来劝阻不合理的编程方法

来源:互联网 发布:国产游戏制作软件 编辑:程序博客网 时间:2024/05/07 05:55

 

语法糖[1]长久以来在框架和语言设计的讨论中霸占着公众的焦点。它有能力把习惯用法变成常规,以及通过语法的美,简洁和方便实用来推动一个常用的编程风格。我们都爱语法糖 – 而且我们要把它应用在所有地方:令人恐惧的低端编程,令人头晕目眩的高端编程和爽口的中端编程。这也是让Ruby这样的语言和别的平淡的语言对比,感觉如此甜蜜的原因。

 

 
但是糖并不是所有我们所需要的。好的设计不光在于强调合理的编程风格,而且在于淡化不合理的编程风格。就像我们可以在某种特定的风格或者方法上洒上语法糖来鼓励程序员使用它,我们也可以通过语法醋[2]来劝阻程序员使用这种风格或者方法。语法醋的使用并不常见,但这丝毫没有降低它的重要性。
 
请允许我解释一下我上面的说法。今天的早些时候,我终于给Rails里面的ForTagHelper#form_tag方法引入了块(Block)化的魔术。在这个特性被引入之前,我们一直是这么写代码的:
<%= start_form_tag :action => "create" %>
My pretty form!
<%= end_form_tag %>
是的,作为一个热爱块编程,拥有Ruby境界的程序员来说,这种史前的手动通过开始和结束点来控制一个小模块的运行,显得几乎是令人作呕。下一步是什么?手动的开始和结束你的交易(transaction)?手动的处理异常返回?
 
不,不,当然不是这样的。这种开始/结束的罪行仅仅是少些Ruby foo[3](尤其是我的)的时期的遗留产物。我们很早就发现了处理复杂的ERB[4]模板,块和讨厌的输出缓存的技术。这个发现被集成在CaptureHelper里面,但是出于某种原因,我们从来没有把同样的技术运用于form_tag上。
 
我现在已经走题了,我们讨论的是语法醋,而非过去的时光。在新的form_tag被实现以后,我们就可以这么做:
<% form_tag :action => "create" do %>
My pretty form!
<% end %>
是的,是的,这是漂亮的令人发指。可是,醋在哪里呢?在边缘例子上了[5]。看,form_tag在没有block的时候仍然可以作为自己以前的独立自我而实现功用。换句话说,你仍然可以这样写代码:
 
<%= form_tag :action => "create" %>
My pretty form!
</form>
 
但是,这个是什么意思?关闭的form-tag (/form)现在只在纯粹的HTML里面出现,这样的语法凸显了通过Ruby打开一个标签,用平淡[6]的HTML作为结束是多么让人咬牙切齿的不对称[7]。这么做是因为我们已经实际的申明不支持end_form_tag. 哪怕这样的方法可能会在某些不使用块来调用form_tag的组合中仍然有用。
 
好了,现在是点睛之笔[8]。当我们仍然允许form_tag的非块化使用,我们通过强迫使用者遭受缺乏对称的折磨,已达到边缘化和不鼓励这种做法。打个比方,form_tag的块化使用就如同你驾驶在平稳的柏油路面上一般舒适,而非块化的使用仍然不会“此路不通”,只不过你必须得行驶在颠簸的石子路上。在某种情况下,非块化的使用form_tag还是可能更好的(想象一下如果你需要打开一个表格,但是需要在另外一个表格里面关闭它,这种用法是块化form_tag无法实现的)。所以,我们想允许边缘的使用,但是强调你在这么做的时候是经过仔细的综合考虑[9]。
 
我知道这只是一个微不足道的例子。可能它不够资格来代表这么重要的设计讨论,但是我仍然把它看作另外一面底线的战鼓,来敲响那些支持允许和禁止以及那些支持鼓励和劝阻的设计策略的人之间的战役[10]。在Rails的阵营里,我们是后面一种策略的忠实信徒。
 
 
永远不要以为你自己是一种语言或者框架的设计师,就把自己看作无所不能,无所不知的圣人。那些用你的语言或者框架来实现一个现实的应用的程序员几乎可以保证,对于他们工作相关的问题,要比你理解的深刻的多。很少会由你来彻底的否认某种做法的情况出现。你的角色只是引导,通知和向程序员们强调这些值得斟酌的地方。
 
最好的解决办法就是通过程序员的美感来实现合理设计的目的(至少在那些把程序美感当作一个宝贵的特性的开发者社区)。我会把那些通用的,就是说大部分人更推崇的,做法设计成漂亮的格式。在设计方案上撒些语法糖来鼓励正确的编程风格。然后,把那些不通用的,就是说看起来可疑的,做法设计成丑陋的模式。如果程序员真的需要用到这些不通用的语法,那这些语法醋不会成为阻挠他们实现的障碍。但是如果一个程序员[11]并不是经过深思熟虑而使用非通用的语法,设计者就应该尽你所能把她从这些不必需的编程陋习,引回到编程的正道上来。
 
 
注解:
1. David原文中用的词Syntactic Sugar. Syntactic Sugar是指在不改变语法含义的前提下,把语法变得更加方便人的阅读。很好的一个例子就是在C里面,一个数组中的元素完全可以通过位移来定位访问,比如说通过*(a + i)来访问数组a的(i+1)个元素,但是可以a[i]这样的语法显然更加有利于人的理解。
 
2. David原文中用的是Syntactic Vinegar. 这个我在别的地方没有看到过,估计是David发明的词,含义和语法糖相反,因为糖是甜的,大部分人都喜欢吃,而醋是酸的,大部分人都不喜欢,专门指那些让人感觉不舒服的语法设计。
 
3. foo是一种编程中通用的变量代号,一般用来表达不确定的函数,值,文件等,但是很少用来表达人。foo可能是File Or Object的缩写。foo类似于我们一般在数学公式中用x,y,z表示变量,用a,b,c表示参数。
 
4. ERB是一种把Ruby代码嵌入HTML文件的方法。ERB可能是Embedded Ruby的缩写。
 
5. David这里的原词是Edge Case.Edge Case专指某一个条件极端化的例子,比如说上百万客户同时访问一个网站的情况。有个类似的术语,叫做Corner Case,专指两个或两个以上条件极端化的例子,比如上百万客户同时访问一个网站,而正好有一半的服务器处于死机状态,并且维护的工程师有很多出去办事的情况。 几何学上讲,Edge专指一个维度的极端,而Corner至两个或多个维度的极端交界处。
 
6.原文中用的是Vanilla.Vanilla原意是香草冰激淋,但是因为香草冰激淋属于老少咸宜的口味,所以所有的冰激淋厂家刚开始都会推出香草口味,而且属于任何一家冰激淋店都必备口味,所以也引申为平淡无奇,老生常谈的意思。
 
7. 在自然科学中,大家都知道对称就是美,所以这也是David故意把不推荐的编程方法设计成非对称的原因。因为不对称而丑陋,因为丑陋所以程序员不会刻意使用它。
 
8. 原文是Punch Line. 专指笑话中最后一句让人捧腹大笑的话,引申为点睛之笔。
 
9. David用的是balancing on it. 美国俗语里,on balance专指从各个方面综合考虑得失。
 
10. David这里用的是Battle,而非War.因为两种设计思想斗争由来已久,这篇文章只是敲响一场新的战役的战鼓。
 
11. 有意思的是,David这里用的是she,而非常见的第三人称代词he.是不是在David的潜意识里,女程序员犯这种低级错误的概率要高的多呢?No comment here. :-)。
 
原文链接: http://www.loudthinking.com/arc/000601.html