jian's profile我的知己在街头PhotosBlogListsMore ![]() | Help |
我的知己在街头Walking through the green fields, sunshine in my eyes.
4/18/2009 KOBE:社区,请向我开炮!我在一个月前的一篇Kobe: 来自微软的Web 2.0服务开发资源工具箱中提到的微软web2.0开发示例Kobe,重蹈了Oxite的覆辙,这次还是栽在MVC应用的跟头上。 也就是这两天,社区集中讨论了Kobe的设计与开发缺陷,前天由Kazi Manzur Rashid的一篇Kobe – MS New Web 2.0 Resource Kit in ASP.NET MVC and My thoughts引爆讨论,但这次的领军人物是Ayende,昨天Ayende连续发表了五篇高质量的Kobe探讨贴:
Kazi Manzur Rashid抱怨Kobe用硬编码的字符串常量而不用枚举,不懂得使用ActionResult对象作为处理结果而是直接修改HttpResponse输出流,Action方法处理视图方式不当,代码命名不规范,还在用Oxite事件里被批过的数据存取模式,同时,作为开源代码,没有提供单元测试也是不能接受的。在文章后面的评论里,Kobe的授权条款也被批评:作为guidance发布,却连张贴代码片段讨论都是不允许的。 Ayende却对Kazi Manzur Rashid指出的一些实现上的边边角角不足感到不以为然,他的意见主要是设计层面上的。 学习一下Ayende的代码复查的思路和技巧也很有意思。Ayende先用Simian工具对代码进行静态分析,发现位于67个文件中的873个方法共有5138行代码是重复的,接着通过代码质量矩阵的Cyclomatic Complexity指标,发现了HomeController.Discovery和GroupController.Profile两个高危目标,然后通过一行行读代码又发现了不少硬编码,bad smell的代码,以及违背MVC原则的代码。 关于Kobe被批评的数据存取模式,Ayende认为一方面Repository模式的使用属个人偏好而与最佳实践无关,并且Kobe并没有将Repository模式用好,太重太繁琐;另一方面Kobe对作为数据源接口的Entity Framework的使用也很粗暴,走的是当DataSet读的路子。整个表现出古老的围绕用存储过程在数据库里打转转的小程序的眉眼,全没有ORM这么多年后现代数据存取思想的风范。 微软的文档向来无可厚非,Kobe的文档没啥可挑刺的,但Kobe的异常处理机制又被Ayende批评了一通,Ayende的思路有Java的影响,他认为异常处理不能图方便而没有任何封装地随便乱用,只有以下两种场景才可以使用异常处理,不然把人家catch了又不干嘛最后还抛弃了是什么意思嘛:
Ayende总结说,一个程序架构设计再好,也可能因为代码实现差劲而变得一无是处。Kobe代码里处处存在误导性变量命名,拷贝粘贴的代码,糟糕的异常处理,背弃面向对象原则的设计,是一个典型的实现缺陷上升成为了架构缺陷的例子。有两个基本原则从来都非常重要,违背DRY(Don't Repeat Yourself)原则迟早会带来麻烦,而违背面向对象设计的SOLID(The Single Responsibility Principle,The Open Closed Principle,The Liskov Substitution Principle,The Interface Segregation Principle,The Dependency Inversion Principle)原则,现世报会来得更快。 微软对社区的反馈很重视,反应也很及时,回复也很诚恳,正视了自己的不足,不像Oxite事件那么恼火了,Phil Haack坦承自己的疏忽,Kobe移除了下载链接开始回炉,Masashi Narumoto写了篇长文Project Kobe community feedback进行解释,从社区讨论到微软做出并执行正确决定都在一天之内,可见微软对此事的关注程度有多高。 MVC简单的三个对象,关系也不复杂,但微软一直没找到感觉,不是它擅长的领域。之前Oxite可以说是并非官方示例,还有借口可找,Kobe事先也被提醒过Oxite的遭遇,接受过ASP MVC Owner Phil Haack的high-level review也于事无补,它还打上了“intended to guide you with the planning, architecting, and implementing of Web 2.0 applications and services.”这样指导社区的标签了的,结果仍然与预期大相迳庭。 对于一个开发新手来讲,判断哪个实现是优秀的值得遵循是困难的,还是要靠社区靠口碑。目前就ASP.NET MVC实现来讲,我推荐参考以下几个开源项目: 有人说,MVC这么简单的事情还有什么难的嘛,Web开发不就是画页面的事情有什么复杂的嘛?有时候面对这种外行指导内行还很高姿态的场合,都气愤不起来只有哑然失笑。微软的开发人员功底不可谓不扎实,为竞争互联网领军地位的付出不可谓不努力,但一直都把不住脉,搜索如是,门户网站如是,MVC开发亦如是,常常做得貌合神离,可见世上之事,诸多知易行难,不是一两句廉价的口水就能YY出来的。关键在于去做,做错了不要紧,至少能不断调整方向。微软的底气就在于,它目前还错得起。 4/16/2009 nRoute:一个Silverlight/WPF导航应用开源框架下图据说是微软对2019年操作系统桌面展望搭建的一个原型,看这架势你信不? 要觉得信息量不够怕是PS的,那真实操作截图都有:
你还不信啊?!!那,这里有真实演示网址Future Desktop,总归信了吧? 早知道你终归是不会信的啦!不过,要不是标题和网址路径出卖了我,估计你八成仍然得半信半疑。 上面的截图确实是来自一个真实的Silverlight应用示例,用Blend2 + VS2008做的,技术底层则是一个名叫nRoute的开源框架。 好吧,我承认,Silverlight3已经有了一个名叫Navigation Framework的东东允许控制控件与页面间的导航,与浏览器历史的交互,定义链接映射(简介见Tim Heuer的这个Navigation Framework video)了,但是Silverlight3不还没有正式发布嘛,而且nRoute作为开源项目并不失其存在的意义,其亮点如下:
我不多废话了,进一步介绍见这里:Introducing nRoute: an application-flow framework for Silverlight and WPF,顺便一句,你可以从nRoute源码中亲自查看Future Desktop的具体实现哈。 4/4/2009 Powershell脚本: 转换CodeSmith模板到T4模板关于代码生成的话题有很多了。无非是将字符串划分为声明,输入,变量,脚本四大块分别处理。 CodeSmith是代码生成领域里的No.1这无疑的,它的界面功能也强大,模板资源也很丰富。T4(Text Template Transformation Toolkit)则是微软官方在VisualStudio 2008中开始使用的代码生成引擎,可惜T4不像微软公布的别的工具那样参考资料充足,而且模板也很少,MSDN上甚至没有一个专门的目录用来介绍它,惟一沾边的就是在介绍DSL工具时带上的Generating Artifacts By Using Text Templates。 我在去年的一篇关于T4:Text Template Transformation Toolkit有提到了T4的一些网上可见得资源,虽然现在已经有了T4 Toolbox这样的模板库插件,而且也有了T4 Editor这样的商业编辑工具,但编写复杂的T4模板依然是一件麻烦而且要求挺高的事情。 面对CodeSmith大量现成的模板资源,T4使用者就只有垂涎的份儿吗?想想看,都是类似ASP形式的语法,用编译器的语法来讲,符号表的处理不都是一样的吗?所以深入想一下不都是字符串处理嘛?于是我花了三个小时的时间,写了一段将CodeSmith模板转换为T4模板的Powershell脚本,下载见这里,执行前需要确定”Set-ExecutionPolicy unrestricted”,用法如下,也可以做成bat批处理文件执行:
从CodeSmith转换到T4,关键是语法的对应关系要理顺。CodeSmith还好,有丰富的help信息,而T4支持的语法,能见到的接近于权威的也只有GarethJ的一篇Update to Text Templating syntax for May 2005 CTP,这还是说的CTP的早期版本,T4发展到现在正式版支持什么样的语法几乎是黑箱。 好吧,我就对照能用的T4语法野蛮地映射照搬吧,处理字符串向来是Pearl等脚本语言的强项,使用Powershell也就是为了练手,比如我之前写的那一系列使用Powershell进行代码编译部署的应用。 之所以说这个转换是野蛮的,是因为很多功能是工具特定的,无法做到一一对应的照搬。比如CodeSmith的CodeTemplate可以对应T4的Template,CodeTemplate的属性参数很多也和T4对应,比如Debug和Language都是相同的,但是CodeTemplate的TargetLanguage,CompilerVersion,NoWarn等这些属性T4是不支持的。再比如Property对象,CodeSmith里有的Optional,Default属性也是T4不支持的。还有就是<%-- --%>这样的注释语法T4也不支持。总之,映射缺失的地方很多,所以我给出的这个脚本,也只能做到基本的语法转换。 我感觉CodeSmith最大的亮点,就是那个SchemaExplorer.dll,操作数据库对象太方便了,现在T4还不会有。等再有空了我整个简化版给T4能用上,这样模板转换后的功能也就更接近一点。 现在这个转换脚本主要是用正则表达式实现的,还有一些不完善的地方,我写完后也没有做全面的测试,转换后的模板文件肯定还要有微调的,大家在使用过程中遇到的问题请反馈给我,我会做更新。 最后顺便说一句,关于T4的好消息,根据Miguel de Icaza在Mono's Text Template Transformation Toolkit (T4)的介绍:“T4 Support in MonoDevelop, with error reporting and document outline”,支持tt文件的语法高亮和编辑时检查哦,不愿用T4 Editor的可以用MonoDevelop试试了。
脚本下载见此:
3/25/2009 从.NET RIA Services发布看微软的数据驱动开发观念演变微软每年的MIX大会,是面向设计师和前端应用开发者的盛会。在3月18日的Mix09大会上,微软发布了.NET RIA Services(项目代号Alexandria)的第一个预览版,以指导富客户端应用的开发实现。.NET RIA Services的代码样例也可以从MSDN Code Gallery上下载,Nikhil Kothari另外有一篇精彩文章.NET RIA Services: From Vision to Architecture阐述了.NET RIA Services的设计思路。 Mix09的视频已经放在互联网上了,我目前看过且深有同感的有两场,分别是Nikhil Kothari的.NET RIA Services - Building Data-Driven Applications with Microsoft Silverlight and Microsoft ASP.NET以及David Ebbo的Microsoft ASP.NET 4.0 Data Access: Patterns for Success with Web Forms,都和数据驱动开发的应用相关。David Ebbo主要讲了ASP.NET Dynamic Data 4.0 Preview 1中刚刚引入的BusinessLogicDataSource对象,在最新的ASP.NET Dynamic Data 4.0 Preview 3就已经变成了更完善的DomainDataSource。Nikhil Kothari则在.NET RIA Services的介绍中大力推了一下端对端方案,并鄙视了一把分层方案,他说“n-Tier is hard, and un-natural”,”un-natural”这个断语说得很伤呢。
我有同感的地方在于,Nikhil Kothari和David Ebbo实际上都提到了一个问题,即数据呈现以及数据定义的关系。他们给出的统一方案就是DomainService,一个将数据及数据定义提供给前端呈现的东东。难道这便是广义上的MVC?长久以来MVC在Web应用中大行其道,而微软在ASP.NET WebForms里推的Model-View-Presenter模式就一直半红不黑。我对MVC没啥意见,只是有两点:一,MVC的那个V,应该在浏览器端,而不是在服务器端完成,Web Forms的服务器端控件用来做了太多事了;二,MVC只适用于一个完整边界的场景,不能跨场景当万金油拭,要想到小事不决就MVC,大事不决则SOA,哈哈。 还是回到DomainService这个对象带来的新观念这个话题。 以David Ebbo的Session为例,在.NET Framework 2.0以前,是没有DataSource控件的概念的,DataSource控件被引入后,相信引起了很多开发人员的观念混淆。因为DataSource控件就定义来讲,属于呈现层,毕竟是控件嘛,使用方便是没错,但是它直接就从数据呈现前端连到数据存储后端,非常非常的不好分层,如果加入自定义业务逻辑代码强分一层,则DataSource对象的使用并没有降低开发成本,还增加了复杂度和维护风险,它很多情况下是没有设计时编译检查的。就我接触到的资料和项目情况来看,就很少有将DataSource讲透用好的。但DataSource的生命力不光没有减弱,反而从ObjectDataSource一路进阶为LinqDataSource,EntityDataSource,演化到马上要推出的DomainDataSource了。DataSource控件的设计依据是什么?它哪有不可替代的独特价值了?这值得我们思索或者说猜测呀。可以说DataSource控件的顽固存在,确实是强化“n-Tier is hard, and un-natural”这个结论的一个注脚。 Nikhil Kothari的Session里,以数据存取为核心,将其它业务逻辑切分,形成了Data Model + MetaData + Shard Code(Rules/Workflows…)的这样一个结构,在这个结构里,也没分层设计什么事情。Dynamic Data的推出,很多人认为不过是微软临时拿出来应急止煞的,可从这个Session中对MetaData模型的强调来看,Dynamic Data可能会是一个重量级的发展方向诶,虽然MetaData这个东西大家爱恨交加,据说Dynamic CRM之所以慢,有一半倒要归为那个Meta数据库导致的反射与拼接漫天飞的功劳。。。 我看到的是,基于Attribute的MetaData对于数据驱动应用的重要性越来越突出了,以前为了架构设计清晰而坚持的Top-Down的分层设计理念削弱了,强调数据流动完整性与边界明确的设计理念声音越来越响亮了,不得不说那句“n-Tier is hard, and un-natural”太愤世嫉俗了-_-! 3/12/2009 Kobe: 来自微软的Web 2.0服务开发资源工具箱Kobe是微软最近推出的一个“getting started”资源工具箱,用于通过微软产品平台来构思,设计和实现Web 2.0服务。 Kobe提供的资源目前包括: Kobe还有一系列的视频演示可参看:
是个好资源诶。 3/2/2009 Code Contracts: 将随.Net Framework 4.0一起发布的契约式设计组件我在一年前的一篇使用Spec#实现Design By Contract理念提到过微软在契约式设计方面取得的一些成果,但几乎有着与Spec#类似理念且团队成员也重合度较高的Code Contracts,成了这次.Net Framework 4.0发布的正选。 论起声势,还是Spec#要大一些,Channel 9上还有一段录像Expert to Expert: Contract Oriented Programming and Spec#可以参看,Code Contracts给我的感觉就是不声不响的,好像这次突然冒出来的一样。 比较起Spec#与Code Contracts的不同来,最大的不同要数语言平台了,Spec#是基于C#语言且对编译器做了扩展,Code Contracts则支持所有.Net语言,不晓得是不是Spec#将被遗弃了,反正开始使用Code Contracts这个被纳入未来.Net Framework框架核心的组件是不会有错的。 相关资源: 2/28/2009 ASP.NET MVC 官方示例动手做:联系人管理ASP.NET MVC网站上刚刚推出了一个示例程序Contact Manager,并提供了Stephen Walther撰写的该示例程序的7次迭代开发过程所对应的7篇教程。
Stephen Walther在这一系列教程中演示了如何将单元测试,测试驱动开发,Ajax,以及软件设计原则与模式结合到ASP.NET MVC框架开发实践中。示例虽然简单,却不但展示出了ASP.NET MVC框架的特性,整个从无到有的敏捷开发过程也是极具可操作性的,非常棒! 1/17/2009 jQuery v1.3发布 : You Will Rock Us
开源社区里有不少有名的JavaScirpt类库项目,老牌如Yahoo的YUI,热门如天然内嵌于Ruby On Rails的prototype,低调如dojo,新晋如mootools,当然,也不能忘了微软推出至今却被社区还以门户之见的ASP.net AJAX(估计社区从没注意到过它有个client端的类库版本!),个个以灵巧而且漂亮著称,但jQuery与它们放在一起仍然卓然不群。 jQuery的两个突出特点在于,一方面它绝不像其它类库那样以把javascript做出一个面向对象框架为目标,从命名就看得出来,query嘛,用CSS/XML选择器查询页面元素才是它安身立命的绝活,另一方面也是决不可忽视的就是仅仅才15k的它性能非常好,这可以见下图。
jQuery告诉大家,面向对象的搞法那是学院派,出来混还是要能干净利索地解决问题才是王道。jQuery的理念可验证性到了什么程度?微软在试图往ASP.NET AJAX中添加元素选择和动画效果操作的功能时,不得不认识到jQuery才是最好的选择,破天荒地头一遭将一个非亲生的开源项目打包到自己的产品中发布,并承诺给以产品支持。jQuery不可思议地将元素选择器变成了主流需求,直接影响到其它类库也匆匆推出同等功能不算,甚至反过来推动了各大浏览器也开始实现W3C最新的Selectors API标准,这体面大发了! 要说jQuery的这个超酷的选择器特色,追本溯源可以从Dean Edwards的cssQuery和Simon Willison的getElementsBySelector这些早年的冷门实验说起,那时还没吹起web 2.0的春风,现在可基本面大好喽。 jQueryv1.3的主要更新除了推出全新且将一统江湖的选择器引擎Sizzle外,别的特性可以见这里:jQuery 1.3 正式版发布。 最后,再给大家看几个jQuery用炫了的例子。
参考: 1/5/2009 Adventure Works示例数据库业务分析(一): 简介Microsoft为了演示SQL Server的产品功能,提供了虚拟业务场景的示例数据库。在SQL Server 2005以前,是pubs 和Northwind 这两个数据库,之后是AdventureWorks数据库,SQL Server联机丛书都是基于所提供的这几个示例数据库来阐述演示配套应用程序和代码示例的。 pubs数据库演示了一个虚拟的图书出版公司的业务场景,Northwind 数据库演示了一个虚拟的从事食品的进出口业务公司的销售业务场景,这两个数据库的业务场景都不是太复杂。而从SQL Server 2005开始提供的AdventureWorks数据库,引入了一个虚拟的Adventure Works Cycles公司。此公司及其业务方案、雇员和产品是下列示例数据库的基础:
从数据结构上看,AdventureWorks数据库是对Northwind数据库和pubs数据库的扩展,体现在数据库中的某些表结构是相似的,比如AdventureWorks数据库的Sales.SalesOrderHeader表对应Northwind数据库的dbo.Orders表,AdventureWorks数据库的Sales.SpecialOffer表对应pubs数据库中的dbo.Discounts 表。 AdventureWorks数据库反映的业务场景不光能充分挖掘SQL Server的功能特性,而且其示例从业务到数据都具有真实世界的参考意义,对于我们设计业务软件系统的数据模型和业务流程非常有价值。但有一点遗憾的就是,Microsoft并没有系统深入地阐述过AdventureWorks的业务场景,从而也就无从指导我们如何了解到为什么要那样构建数据模型,从这一篇出发,我打算通过反向基于SQL Server 2008的AdventureWorks数据库的数据表并结合业务经验来推导Adventure Works Cycles公司的业务流程,达到更好地理解系统设计的目的。 目前网上关于AdventureWorks数据库有价值的资源参见: 12/20/2008 关于Oxite的教训必须得坦率的面对,这不是一个好的案例,而是一个好的教训。 事情得从12月5日Platform D&E (developer evangelists) 部门下面的MIX Online团队将他们自己开发并正在使用的内容管理引擎项目Oxite的源码发布到社区开始说起。现在的官方简介是:
作为目前还没有正式推出的ASP.net MVC的又一个开源项目,这本来是个好消息,社区的反应一开始也很热烈很正面,但和微软发布的其它示例不同,社区接触Oxite不久质疑的声音开始出现了。Oxite的简介暗示了Oxite可以被作为ASP.net MVC的官方范例而在社区推广,但Oxite的设计质量却可诟病处不少,这是一个可以借鉴的good example吗? 社区里的公开反馈其中以Rob Conery的分析意见最为透彻。这位仁兄是受Ruby on Rails框架的Active Record模式启发的SubSonic项目的创建者,以其对MVC模式的深刻理解而被招揽到ASP团队中促进ASP.net MVC的开发,Rob Conery现在自己也个人维护着一个ASP.net MVC的示例项目StoreFront。 Rob Conery认为:
除了Oxite架构设计上的不足外,Rob Conery还提到了一个观点,说起来这属于公共关系的处理领域了,作为Microsoft雇员或团队,当对外部公开谈论某些事情的时候,公众不会认为这是一个独立个体的声音,他们会认为“微软开始。。。”或者“微软发布。。。”,把个人意见作为公司立场。这种误解不会使好的事情变得更好,却会使坏的事情变得更糟,比如Oxite这次造成的错觉。因为据Scott Hanselman的解释,Oxite这次推出并没有经过内部规范流程的审查:
最后,Glenn Block为此次事件做了解释,同时,Rob Conery也开始帮助MIX Online团队对Oxite进行重构。从架构设计和项目管理上,这次Oxite事件都给了我们深刻的反思:
|
|
||||||
|
|