posts - 115, comments - 1532, trackbacks - 85, articles - 9
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

Code is Configuration

Posted on 2007-02-24 10:44 Cat Chen 阅读(8667) 评论(19)  编辑 收藏 所属分类: ASP.NETRubyRails

Ruby on Rails强调Convention over Configuration,也就是习惯优于配置,这对我来说是一个很有吸引力的特性。.NET是配置优先的(据说Java也是),最好什么都不是硬编码而是可配置的,开发出来的产品最终可以在部署时根据实际情况配置,或者再被调用时按照调用者的需求配置。为什么RoR可以是习惯优于配置呢?如果什么都硬编码了,遇到需要改动的情况怎么办?按照我现在对RoR的理解,思考了一下,寻找到一种可能的解释——RoR的代码也就是配置!

在.NET里面,函数或者是指令,都是描述行为的。一组指令组成一个函数,代表着一组顺序执行的行为;之后一组函数组成一个类,代表着一类行为的聚合。而RoR指令给人的感觉却不是这样,RoR中有些指令完全可以认为是描述性的,就好像配置一样,而且是顺序无关的。

举个例子,创建数据表的migration,你可以认为它是ruby语法写的CREATE TABLE,而且它做的也就是CREATE TABLE,但实际上它是schema!它已经描述了数据表是怎样的了,而不仅仅是生成数据表,生成数据表仅仅是migration执行时瞬时的行为,生成数据表之后Rails自动提供ORM功能,不再需要另外的schema或者自动生成的code来重复描述schema。这正是其符合DRY原则的地方,在整个RoR应用当中,只有migration这一处描述了schema,其它地方均无再次描述schema的地方。然后再对比一下我们在ASP.NET中的做法,重复描述数据表schema的地方实在不少,无论使用哪种ORM工具都如此,希望以后大家都能用上DLinq从而避免这个问题。

再举个例子,model中可以直接用helper函数指定每一个属性要符合的业务逻辑,从而提供验证功能。还记得我们在ASP.NET中这有多麻烦吗?首先,根据决不信任客户端提交原则,在View中要验证数据,验证一方面要能抵御恶意编写的提交,另一方面要对不符合业务逻辑的提交给出反馈,这辛苦了Validator控件,而且我们自己也要写不少代码(如果部分输入设计复杂验证逻辑的话)。接着,业务逻辑层再来一次验证,这是为了业务逻辑层的完备性,在脱离原有表现层而被第三方调用时也能确保数据的合法性。然而在RoR中却不用那么麻烦,在model中一次声明规则就行了,view中输入的数据如果不符合model的规则自然会在view中得到反馈,这种逻辑既是声明性的,又符合DRY原则。

最后,说说ASP.NET可以从RoR学习的规则。首先,MVC分离是有必要的,仅仅垂直分3层是不够的。我之前也有想过,为什么要在表现层提供众多的Validator控件,而不是在业务逻辑层提供验证相关的Helper类呢?这些Helper类,加上业务逻辑层反馈到表现层的通道,就能够做到只需要实现一次验证。或许Validator控件,也是简化表现层设计的一个做法吧,为了吸引别人学习ASP.NET,MS做了很多东西让它看起来很容易用,却让人难以全局协调。其次,一个类象征现实中一类事物的隐语仅仅是针对model的一个说法,其它时候我们更需要函数,类就仅仅是用来聚合函数。例如一条验证规则,这是一条配置,同时也是一个函数调用,需要完成验证这一顺序操作的是函数,而不是类。如果你要用类去表示规则,例如config文件映射出各个ConfigurationSection那样,这就增加了处理步骤,因为最终你还不是把类里面的属性读取出来交给函数处理这条规则。

Feedback

#1楼    回复  引用  查看    

2007-02-24 12:40 by Ariel Y.      
好文, 不得不支持一下

#2楼    回复  引用  查看    

2007-02-24 13:06 by 命运有自己的梦!      
你也在研究ROR?我也研究过一些,开发思路很不错哦!

传音石--网罗天下资源 http://www.massany.com

#3楼    回复  引用  查看    

2007-02-24 15:25 by JesseZhao      
感觉很mvc,模板都是很好的概念

#4楼    回复  引用  查看    

2007-02-25 09:20 by iCaca      
Good!

#5楼    回复  引用  查看    

2007-02-25 09:51 by 亚历山大同志      
LZ,主要的问题是 Ruby是动态语言,ASP.NET的C#是静态类型的语言,它需要编译,每一次修改都需要重新编译项目,重新部署发布,而Ruby不用,为修改规则改改代码是不用重新编译整个项目的,所以才说的如此轻松。
验证的那一段我比较赞同,asp.net的验证控件很多时候没有解决根本问题,很多时候还会因为js的问题而失效,确实需要改进。
But,c#一日不动态。code is configuration就一日难以实现,LZ不是看多了ROR,而忘记了ASP.NET是如何的了吧,呵呵,by the way ,我也在看python,最近在实践Karrigell。^_^

#6楼    回复  引用  查看    

2007-02-25 10:57 by 冬冬      
不错,学习了,最近也开始向RoR迈进。
“MS做了很多东西让它看起来很容易用,却让人难以全局协调”,正解!

#7楼 [楼主]   回复  引用  查看    

2007-02-25 12:17 by Cat Chen      
@亚历山大同志
ASP.NET支持非编译页面,例如使用IronPython的页面,不过C#页面不能这样做,那就期望C#加入更多动态语言特性吧。

其实ASP.NET编译是很好控制的,因为我们可以随意开发自己的BuildProvider,而不需要动其核心。正如我们改变了aspx/cs/config文件后请求时自动重新编译一样,我们可以加入新的BuildProvider来编译新的资源,而这些资源实现Code is Configuration的设计。

#8楼    回复  引用  查看    

2007-02-25 13:36 by Ariel Y.      
BuildProvider确实能实现动态编译, 但是对于微软的开发平台, 同时实现Visual Studio的动态Intellisense也是一个重要的环节. 这样才能实现一个完整的体验.
是想如果.net开发环境没有Intellisense会是什么样一番景象.

就像WebSite Project的Membership Profile一样. 但是好像Web Application Project目前还无法做到.

Cat在这方面有想过吗?

#9楼 [楼主]   回复  引用  查看    

2007-02-25 15:55 by Cat Chen      
@Ariel Y.
因为.NET没有convention可言,所以IntelliSense才那么重要。RoR不会依赖IntelliSense,因为只要大家都习惯了按照一个convention去写代码就是了。

当然,要习惯IntelliSense的用户转变为凭感觉按convention去写代码不容易,呵呵。

#10楼    回复  引用    

2007-02-25 22:04 by 怪怪 [未注册用户]
@Cat Chen
.NET是没有convention可言,那是因为微软没有给出来,但微软也没有说你不能有自己的convention,只是如何定制、在哪个层面来定制而已。你完全可以构建自己的符号表和关系表,然后实现自己的框架,而且什么动态编译之类的其实根本不在这个考虑范畴,在.NET中挑几个合用的类调调方法重新组合一下就完事了。

这是个思维问题,并不是说在.NET下Web应用就必须如何如何构建,或者其它语言就怎么样。关键是你需要什么样的特性。比如,个人认为控件树本身是一个进步,只是ASP.NET把控件树的具体表现形式实现的过于死板和难于定制。

至于工作量和难度的问题,其实从数据库->表现层,哪怕什么工具都不用,在.NET上不过几行代码的问题。关键不就是表现层本身我们非得让我们的实现呈现足够的.NET控件特性,或者有时候不得不去符合.NET那些模版方法的顺序,才造成了种种麻烦。

说实话个人对RoR的思路抱有抵制态度,一方面是从语言上讲,比起真正成熟的各种静态、动态语言,还不免有点粗制滥造,但如果真的不过如此,不把它当回事便罢。关键是它面向的群体说实在的根本不是真正的程序员,这些产品出现的目的,就是发展到足够成熟的一天,凭一些每个人(比如咱们现在看不上的那些很一般的美工--并非指精通网页设计尤其是美术设计的大拿)背背书就能掌握的规则,就可以构建出足够好的应用,从而咱们这些程序员就失业了。

不过当然这也是一个必然的趋势,我觉得如果有志于搞技术的各位同志们,不得不开始警醒了,这些东西不是来方便你和我的,而是来取代咱们中间的大多数人的....

#11楼    回复  引用    

2007-02-25 22:21 by 怪怪 [未注册用户]
至于你说到的,代码本身就是配置这个问题,配置是一个参照,在.NET和Java里其实是用一个新的层解析一个"持久化"后的对象来实现,那个谁谁不是说过,计算机科学就是如何增加一个层去解决问题的科学。按照你的理解,RoR只是把新增一个层这个过程,变成找出一个合适的层,直接以它来当作参照,从而避免了新增一个操作某“持久化”对象的层这一步骤。

关键是个能动性的问题。研究别人的东西说实话永远是相对简单的,如何把咱们自己的开发经验转化为真正的适用于某一需求的架构,别人做了,咱们也不能等死啊。真是有点战战兢兢了。

#12楼    回复  引用    

2007-02-25 22:31 by 怪怪 [未注册用户]
关于Validator这个例子,怎么说呢,我觉得多次验证是怎么也不可避免的,除非你不需要客户端验证。难道RoR就不需要写JS? 或者说,每次验证,你都用统一的JS发送回服务器,由你的Helper或者任何函数验证,然后把响应发回给客户端?当然如果刨除掉客户端验证,确实在服务器端只应有一个验证的过程,但我觉得,ASP.NET和这种设计并非是互斥的,关键还是如何组织的问题。关于控件是为了重用,绝非为了增加不必要的过程,我觉得ASP.NET里的很多东西,把它们当成一个具体实现的例子即可,并非说非要围绕它们去实现。一方面在用ASP.NET时候,围绕着微软提供的东西去实现,一方面又说本来应该是怎么怎么样的,那自然就变成了矛盾了....

#13楼 [楼主]   回复  引用  查看    

2007-02-25 22:36 by Cat Chen      
@怪怪
我说多次验证,不是Validator在客户端和服务器端算作两次,而是Validator在表现层算作一次,然后业务逻辑层的验证再算一次。

#14楼    回复  引用    

2007-02-25 23:03 by 怪怪 [未注册用户]
@Cat Chen
嗯,所以我不是加了"如果刨除客户端验证"。首先确定谁是必须有的,一般来说是逻辑层,然后我个人感觉无外乎几种方法解决你说的问题:

第一种,然后把验证逻辑提出来,逻辑层用、表现层由自己实现的的Validator包装调用。

第二种,彻底抛弃Validator,再表现层和逻辑层的应答过程中进行约定,也能合理解决。

第三种,在自己的架构中有专门处理验证的逻辑。

第一种是适应M$的做法,然后最终失业。第二种是很正常的做法,最终失业。第三种经过不断的提炼,逐渐形成你自己东西中的一部分。我个人觉得如果不想失业,只有第三种方法才是每个人的出路。但你有你的东西、我有我的东西,大众接受的只能是其中几种,最终的结果就是推广和竞争,剩下几种有限的,给那些构建应用的非程序员使用,其它程序员失业。

靠,想改行了。

#15楼 [楼主]   回复  引用  查看    

2007-02-26 00:22 by Cat Chen      
@怪怪
程序员从来都是“自相残杀”的行业啊,不断提高自动化程度就是为了让同类(甚至包括自己)失业。

#16楼    回复  引用    

2007-02-27 12:44 by 禾口王 [未注册用户]
自已写的程序让自己失业的程序员是伟大的程序员

#17楼    回复  引用    

2007-03-03 06:33 by 晕死 [未注册用户]
到头来还是一场口水战

#18楼    回复  引用  查看    

2007-09-01 23:41 by 银河      
我也赞同习惯优于配置

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-03-16 09:13 编辑过


相关链接: