RSS

Monthly Archives: 三月 2004

放假归来

上周请假回家一趟,休假期间,VS2005 CTP版本发布、ShadowFax新版本发布(终于有了完整的MSI安装包)、ASP.NET Forums 2.0 Beta RC1发布(同样是一个完整的安装程序包)。

走之前,匆忙将以前的一个通过WebService上传文件到服务器的WinForms程序添加了多线程上传的能力。

.Net Framework对多线程有非常良好的支持。而对于WebService,内置的异步调用方式让我们能相对轻松的加入同时调用多个WebService实例方法的能力。WebService对于异步调用有两种处理方式,一是在调用Begin方法时给它一个CallBack函数,在WebService返回时会自动调用这个CallBack方法,二是利用WaitHandle类让客户端当前线程等待WebService返回。

我是采用的相对简单的第二种方式,同时创建多个WebService代理对象,然后调用它们的Begin方法,利用WaitHandle的static方法WaitAll(),让客户端当前线程等待到这些WebService方法全部返回为止。

今天回公司就发现了上周匆忙写就的程序有Bug,因为客户端程序在上传前会动态压缩传输的数据,而服务器上动态解压和接受多个WebService调用的协调处理未能和客户端保持一致,导致了出错。这充分证明了一个准则:

对于多线程同时调用的程序来说,复杂的不是客户端代码,而是接受调用的服务器端代码。

 

Posted by on 2004/03/29 in 未分类

评论关闭

Provider Model 模式

这篇文章的思想的来源是Rob Howard半月前的一篇文章,Provider Model Design Pattern and Specification, Part 1,本来想等Rob HPart II写完然后再一起总结一下的,可等啊等啊,估计这位哥们儿在忙着准备DevDay2004和做演讲,所以一直都没有等到Part II出来。不过Rob HowardMSDN上的文章从来都是精品,而且这篇文章之前很长一段时间,由于忙着Whidbey的开发,Rob H已经很久时间没有在MSDN上的专栏撰写文章了,所以这篇文章出来的时候甚至被MS的人士称为“Return of the King”,呵呵。

 

言归正传。所谓Provider Modal,基本上都是指的“DataSource Provider Modal”。它是一种让你能够方便的提供多种数据源,并可以“动态”的在各个数据源间进行切换的一种模式。

 

ASP.NET 2.0中,大量采用了Provider Modal模式。比如,PersonalizationMembershipASP.NET提供的内置的能够给开发人员极大方便的特性,它们能够自动保存用户的个性化信息,和维护站点用户信息。它们都需要一种存储方式,就是说,需要找一个数据源来保存他们的数据。但是这个数据源的提供方式,需要有非常大的灵活性、伸缩性、可定制性。比如,我的服务器可能没有安装SqlServer,只安装了MySql,但是我希望不管我的实际的数据库是什么类型(或者根本就没有条件安装大型数据库,而只能提供Access的方式进行保存),都能够作为PersonalizationMembership所能使用的数据源,都能保存它们需要保存的数据。

 

这个时候,Provider Modal模式就可以大展身手了。首先,MemberShip对于能够保存它的数据的Data Provider提出一个要求,比如必须实现IMembershipProvider接口,而这个接口里面定义了保存MemberShip系统中的数据所需要实现的所有方法,比如“CreateUser(String username, String password, String email, out MembershipCreateStatus status)”用来创建新用户,“Boolean ChangePassoword(String name, String oldpassword, String newpassword)”用来修改用户密码。我们要做的,就是针对MySql写一个MySqlMembershipProvider,实现IMembershipProvider要我们实现的所有接口,然后在web.config文件将我们写的这个MySqlMembershipProvider指定给MemberShip用。而对于MemberShip系统来说,它不用关心倒是是谁实现了IMembershipProvider,它只是根据web.config里面的设置,载入那个具体的实现IMembershipProvider的对象,然后调用IMembershipProvider定义的接口方法就可以了。这样我们就拥有了极大的灵活性,可以根据自己的要求定制满足自己需要的Data Provider

 

上面所说的,就是Provider Modal模式了。在很多的场合,在我们需要一个很大的灵活性的数据存储方式多样化的场合,我们可以应用这个模式,让我们的系统变得灵活而具有可扩展性。能够想到的包括Log纪录、Cache保存、用户State状态保存等等,只要我们开始做的时候就明智的应用Provider Modal模式,那么也就给了以后扩展的机会。

 

好像很简单,呵呵,但是掌握更多的实现规范才能更好的实现它。更多的细节和实现规则,请参看Rob Howard的文章。上面ASP.NET 2.0 PersonalizationMembership特性,来自《A First Look At ASP.NET 2.0》。

 

现在就可以得到的Provider Modal的极佳范例,ASP.NET Forum 2.0,现在仍处于Alpha阶段,预计月底发布BetaFinal版本。

 

Posted by on 2004/03/17 in 未分类

3 Comments

深入SOA的一些细节

进来博客堂关于SOA的文章不少,呵呵,看来SOA进入大家的实际项目可能是指日可待啊。

 

因为SOA绝不是一种标准,而且也是刚刚发展推广开的一种架构,所以在网上对于一些细节(也许下面罗列的已经算不得是细节了)的地方, 各有各的看法,各有各的理由。

 

一、Service Façade公开Entity还是公开Argument

 

比如,应该是这样:

CustomerService.AddCustomer ( CustomerInfo customer )

还是:

CustomerService.AddCustomer ( String name, String zipcode, Int32 level )

 

首先看张图,http://bbs.dotnettools.org/upload/1308-Architecture%20Design.jpg(此图取自.NET Tools评测网论坛redmoon的一个介绍产品架构的帖子,同时推荐大家可以去论坛看看redmoonccboyjjxJGTM2004关于SOA的精彩发言)。

 

从这张图可以看到,由Typed DataSet实现的Entity横跨了整个系统(也就是在整个系统间传递了,就像是我以前的那篇文章上所说的,DTO在模块间流动),甚至通过Service的边界传递给了Service Customer。如果你的整个系统都是.NET,并且能够把包含了EntityAssembly部署到系统的各个模块(所以建议将系统中用到的所有Entity单独放在一个项目中,并被其他所有的项目引用),这样做绝对是简洁、明了、高效的选择。

 

但很多人会不同意这样(我估计JGTM2004会不同意,基于他发出的帖子所表达的观点来判断)。因为很多人认为作为一个独立的、自维护的、解耦的Service来说,你公开一个你自己才明白的Entity,别人(就是Service消费者了)根本不懂,何况说不定一个Java系统以后也想要调用这个Service呢。所以,很多人都说,“Services expose Schema and Contract, not Class and Type”,就是说,ServiceService之间要传递中立的,有良好Schema定义的Message

 

再反过来说:好像是在今年二月份的《程序员》杂志上,有一篇文章讲到一个失败的案例,其中有一点就是各个模块间的调用都是通过参数,而不是Entity,结果后期客户增加了一个字段信息,所牵涉的要更改的地方非常之多(因为模块接口都要改),所以那篇文章的作者认为,为了能够在对象结构变化的情况下,接口相对固定,模块接口参数一定要是一个Class

 

二、Entity自己维护相互的Relations吗?

 

比如,CustomerInfo这个纯数据Entity是否应该包含OrderInfo的集合(提供一个Orders属性来公开),同时OrderInfo包含一个CustomerInfo的引用(提供一个Customer属性)?

 

包含?那么当Service CustomerService请求一个CustomerInfo时,其对应的OrderInfo集合也被自动同时从数据库中取出来,并打包到CustomerInfo一起传回来?还是用类似Lazy-Loading之类的方法先不取回来?一起传回来在某些场合是明显的浪费。哇,好像真是头疼的选择。

 

Lazy-LoadingSOA中应用可不是件简单的事。比如客户端请求一个OrderInfo,然后引用其Customer属性,ServiceLazy-Loading来载入正确的CustomerInfo对象并返回,然后客户端再引用这个CustomerInfo对象的Orders属性,这时Service应该能够正确判断出哪些Order已经被载入了而可以从缓存中直接取,哪些没有载入而需要从数据库中取…ORM可能是个不错的选择。

 

如果干脆让Entity不自己维护其Relations关系,那么客户端就要像这样调用Service了:

 

CustomerInfo customer = CustomerService.GetCustomer( “kaneboy” );

// …

OrderInfoCollection orders = CustomerService.GetOrders ( customer.Name );

// …

CustomerService.UpdateCustomer( customer );

CustomerService.UpdateOrder( orders[0] );

 

重复向Service请求,由知道其关系的Service来处理。而且客户端代码可麻烦了,因为CustomerInfoOrderInfo“实际上”不知道他们之间有什么关系,在需要根据其Relations进行某些处理时,就需要代码来手工处理了。

 

好像文章没有做出一个结论,因为本身就无法做一个“绝对”正确的选择。我个人更喜欢Service公开EntityEntity自己维护其Relations,但是,“Do right things in right place”,呵呵。

附注:第二点很多想法来自Udi Dahan – The Software Simplist

 

Posted by on 2004/03/12 in 未分类

17 Comments

忙着满足客户的需求…

这几天忙着满足客户对一个.Net WinForms(调用服务器上的WebService的)程序的需求,提高了WebService数据传输速度(数据传送前先压缩,传到后再解压),解决了WinForms程序占用内存过大的问题(好家伙,载入硬盘上的文件处理的时候,物理内存占用根据文件大小以线性增长,在我自己内存充足的电脑上根本感觉不出来,倒是把客户吓着了…途中还向JGTM2004发了封Email求助),解决了处理某些过程时界面停止响应的问题(多线程解决了)…以前一直在做WebForms相关的东西,对WinForms接触不多,这几天倒是熟悉不少。

On the road to Indigo是Indigo开发组的一个程序经理的Blog,内容不多但是很精彩。其中一篇讲SOA的文章很不错,列出了Service Orientation的几个核心原则:
1、Service Boundaries are Explicit and Costly to traverse
2、Services are Autonomous
3、Services expose Schema and Contract, not Class and Type
4、Services negotiate using Policy

说到第3点,他的观点是Service之间要传递架构和约定,而不要传递具体的类型。嗯,在我以前一篇讲SOA的文章里,说到在系统各个层间流动的是Entity对象,而Service对外公开的Facade接收和传递的也应该是Entity吗?嗯,值得考虑,考虑因素包括到承载各个Service的平台各异(.NET or Java),即使都是.NET也可能不能直接部署包含了Entity的Assembly…

还有一篇文章说明了现有的分布式架构技术中哪些能够在将来和Indigo直接配合通讯(talk Indigo on the wire ):
纯粹的.asmx的WebService是没点问题的;
将来的几乎随Indigo一起发布的WSE也没有问题(不是现在的WSE和WSE2哦);
Enterprise Services(ES/COM+)也是没有问题的;
MSMQ,嗯,没问题;
.Net Remoting,嘿嘿,是不行的…我真怀疑Microsoft发布.Net Remoting技术是不是有必要,刚推出时我曾乐观的觉得它将逐渐替代(至少是在某些场合部分替代)COM+,但…现在看来Microsoft将来会继续扩展ES/COM+使其能直接和Indigo交互,而.Net Remoting,虽然以后的.Net FX中不会将它踢出去,但是前景…

MSBuild Team发布了一个MSBuilde的预览QuickStart教程的下载,提供了示例代码和文档。

ShadowFax可能将成为微软最“有价值”的SOA架构参考示范,三月份ShadowFax开发组又发布了一个最新的版本,并表示四月份可能会发布其最终版本,并继续开发针对Whidbey的下一个版本。嗯,如果现在要下载ShadowFax,必须加入到ShadowFax WorkPlace中(只要你申请,一般都能通过)。

User Interface Process Application Block可能是微软发布的所有Application Block里面最复杂的一个,提供了一个比较完整的MVC框架,可以用于WinForms和WebForms,看了好久的文档才稍微理解了其架构和用意。UIP2也发布了一个测试版本,更加完善了。

因为前阵子接触了不少WebService + WinForms的东东,加上自己手头的项目中也是这样的应用,所以对WSE2也开始感兴趣起来,特别是在看了MVM的那个用WSE2实现CallBack以后。毕竟直接的.asmx WebService在安全性和扩展性上还是比较欠缺。对了,在这个接近400M的ASP.NET Starter Kit 入门指南资源包里面,就包含了一个WebService + WinForms的示范系统,银行助学贷款管理系统,哈哈,应该是蝈蝈写的吧。笑脸

 

Posted by on 2004/03/11 in 未分类

3 Comments

日本程序员写的代码?

前阵子在CSDN上面看到一个帖子,《日本程序员和中国程序员为同一功能写的代码》,大意是说日本程序员写的代码多么多么清晰明了,中国程序员写的代码多么多么差劲。

“日本程序员”写的代码如下:
Dim gridItemIndex As Integer        ‘comment
Dim currentPageIndex As Integer     ‘comment
Dim pageSize As Integer             ‘comment

gridItemIndex = e.Item.ItemIndex
currentPageIndex = meisaiIchiran.CurrentPageIndex
pageSize = meisaiIchiran.PageSize

Dim updateDataRowIndex As Integer   ‘comment
updateDataRowIndex = (currentPageIndex * pageSize) + gridItemIndex
dt.Rows(updateDataRowIndex).Item(t.BindFldName) = txt

“中国程序员”写的代码如下:
dt.Rows(.CurrentPageIndex * .PageSize + e.Item.ItemIndex).Item(t.BindFldName) = txt

接着表明我的观点:首先姑且不论这个帖子内容的真实性。我认为下面“中国程序员”写的代码比上面“日本程序员”写的代码清晰明了得多得多得多,上面“日本程序员”的那一段代码几乎可以放在《重构》里面做反面教材了。

 

Posted by on 2004/03/08 in 未分类

14 Comments

写了个很小的MSN机器人服务器端程序

在网上找了一些资料,花两个晚上写了一个。能够完成的功能不多,但是扩展性很强。

现在我只让它做了一件事,发送“rss:RSS地址”过去,它就把这个RSS地址的内容抓下来然后回复给你。

不过可以通过编程来扩展它的处理功能,现在提供了两个Plug-in接口,一个用来定制信息记录,一个用来定制信息处理和回复。

比如通过继承MSNRobot.Core.ConversationMessageHandler类,重写“String[] HandleConversationMessage(String senderMail, String message)”方法就可以定制自己的信息处理器了,参数senderMail表示发信息给机器人的那个联系人的Email地址,message表示他发送的内容,返回一个String[]就可以将数组依次回复过去。

然后编译出一个dll,在配置文件里面的<ConversationMessageHandlers>节点下加一行:
<Add Assembly=”MyLib.dll” Type=”MyLib.MyMessageHandler” />
就可以把定制的信息处理器加到程序中了。

呵呵,这样想要机器人实现什么功能只要写程序实现就可以了。信息记录接口和这个差不多,可以让你以自己需要的方式(比如保存在SqlServer中)来保存程序中的输出信息。

下载:http://www.iamstudying.com/kaneboy/msnrobot0.1.zip

 

Posted by on 2004/03/05 in 未分类

23 Comments

SOA实践

SOA的理论已经够多了,也许我们可以来实践着在项目中采用SOA架构。

下面来自我自己的经验和理解,一家之言。

1、DTO

Data Transfer Object,或者叫Entity、Data Object。DTO是指在一个对象里面只包含所表示的实体的数据,而不包含任何操作行为。传统的OOP理论认为建立这样纯粹只包含数据的实体类是不正确的,而SOA架构为了能够在分布的、异构的平台上能够顺利的传递数据,则正需要这样的DTO对象。

SOA对DTO的要求是使用方式是:在系统的各个Layer之间传递的,就是DTO,从DAL到BLL,从BLL到各种Service Facade,从Service Facade到外面的服务消费者(包括PL),都传递着DTO。因为这个要求,DTO必须要可被序列化。

2、Layer结构

BLL是不直接对外公开的,对外公开的是在BLL之上的Service Facade,Service Facade里面通常只包含static方法,供服务消费者调用。Service Facade传递和返回的基本上都是DTO,比如:

OrderInfo GetOrder(Int32 orderID);
void UpdateOrder(OrderInfo order);

OrderInfo就是一个DTO。

3、Service Facade的通道多样性

在作为对外的服务接口上,可能提供多种通道的界面,比如可以接收WebService、.Net Remoting、MSMQ、DCOM等等方式的调用,还可能是同步的、异步的调用。所以可能需要提供各种的Service Facade。

ShadowFax通过双重Pipe解决这个问题,第一个管道专门接收各种各样调用请求,然后统一传递给第二个管道,第二个管道再通过调用BLL来处理请求,然后将结果传给第一个管道。

4、每个Service尽量细化

比如有一个Service,调用它必须对调用者进行验证,那么不如再做一个单独的Authentication Service来专门提供验证服务,因为这个单独的Authentication Service可能以后将可以提供给其他的Service使用。

5、Service各自独立(解耦)

可以想象,在一个大型的系统(甚至可以大到整个Internet)里面,如果每个模块、子系统都以Service的方式来提供给外部的服务消费者,那么各个模块和系统都是直接可扩展、可重用的。他们相互相对独立。

好像太简单了一点哈,但这就是我对SOA核心的理解了。

SOA实践方面的资源(本文参考了大量下面所列的资源):
Getting a little closer to SOA
Are objects with behavior bad for SOA?
Udi Dahan – The Software Simplist
Hernan de Lahitte’s blog

 

Posted by on 2004/03/02 in 未分类

18 Comments

从另一层角度来看待“单独定价”

不过可以从另一层角度来看待“单独定价”的问题,那就是“消除知识壁垒”。

首先,软件比硬件更接近一种知识产品,或者说“获取知识的中介产品”。如果在收入水准不同的地区,这样的“获取知识的中介产品”的价格保持一致,则可能会损坏低收入水平地区的人们获取知识的能力。

打个比方,在北京市,一个小学生一个学期可能要花费2000元的各种费用,但是如果我们在陕北农村里面也实行这样的“同等价格”,那么由于先天的限制(陕北农村的儿童不可能选择自己的出生条件),他们只能不读书,而这就完全剥夺了他们获取知识的权利,他们先天条件的限制,同时也妨碍了后天的发展,他们就不可能在未来的竞争中有一点点的机会达到北京市的儿童能够达到的水平。所以国家要推行“9年义务制教育”,实际就是降低收入低的人群获取知识的门槛,让他们能在在一定条件下享受高收入人群能够享受的获取知识的权利(当然不可能完全享受)。

再比如,Jeffrey Richter的《Applied Microsoft .NET Framework Programming》原本的价格是49.99美元,400多人民币,但国内的出版社不可能在国内卖这么高的价格,国内一模一样的影印版的价格是138元人民币。因为国内程序员在受先天条件的限制下(收入比美国程序员低,但中国程序员不可能选择自己的国籍),如果获取编程技能的成本和美国程序员保持一致,那么就会形成很高的知识壁垒,损害了中国程序员获取知识的权利,中美程序员未来的水平会越拉越远。所以为了保证低收入的中国程序员获取知识的成本能够接近(不可能等同)相对高收入的美国程序员,国内的技术书籍就肯定要单独定价了。

所以回到原本的论点。如果在低收入地区,人们要以和高收入地区相同的价格成本获取软件,那么就会损害这些人使用软件的权利,就是说,他们丧失了使用软件、通过软件学习、通过软件获取知识的权利。如果长此以往,就可能损害他们未来的竞争力。所以对于处于特殊地位的“获取知识的中介产品”(教育、书籍、Internet、软件…),各国都有自己的政策让人民能够以相应地区收入能够承担的成本来获得。所以很多国家对于人民教育是由国家大量补贴的,所以很多国家对于Internet接入是象征性收费的,所以不少国家(和学校)宣布大量部署Linux,其实都是为了降低人民获取知识的成本,保证他们未来的竞争力。

实际上,这也就是自由软件阵营(还有软件破解组织?)的人们根深蒂固的观点:软件应该是免费的,每个人都有权利获得软件、使用软件。

当然,这样的观点不一定被所有人认同(我也不完全认同),所以商业软件才能这样兴旺,但是为什么商业软件不部分接收这个观点呢?比如,实行“单独定价”。笑脸

 

Posted by on 2004/03/01 in 未分类

11 Comments