Daniel's blog

.Net - Just cool!

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  23 随笔 :: 0 文章 :: 107 评论 :: 1 引用

2005年11月18日 #

VisualStudio引进的ASMX的确大大简化了XML Web Services的开发过程,但也存在一个比较突出的弊端,那便是VisualStudio的设计使用的是Code-first approach,先编写代码,再由.NET Framework动态生成Web Services的WSDL,而不是实施SOA更加认同的Contract-first approach。近日实践了一把在开发ASMX Web Services时运用Contract-first approach,然后通过bea Weblogic Workshop来comsume。

Step 1:生成XSD,即Web Method传入和传出XML的Schema,比如我有个叫Test1()的Web Method, 那分别为它定义Test1Request和Test1Response,如下是一个例子:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="TestInterface" targetNamespace="http://groupm.com/TestInterface.xsd" elementFormDefault="qualified" 

xmlns
="http://groupm.com/TestInterface.xsd" xmlns:mstns="http://groupm.com/TestInterface.xsd" 

xmlns:xs
="http://www.w3.org/2001/XMLSchema">
    
<xs:complexType name="Test1Request">
        
<xs:sequence minOccurs="1" maxOccurs="1">
            
<xs:element name="keyword1" type="xs:string" />
            
<xs:element name="keyword2" type="xs:int" />
        
</xs:sequence>
    
</xs:complexType>
    
<xs:complexType name="Test1Response">
        
<xs:sequence>
            
<xs:element name="records" type="Record" maxOccurs="unbounded" minOccurs="0" />
        
</xs:sequence>
    
</xs:complexType>
    
<xs:element name="Test1Request" type="Test1Request">
    
</xs:element>
    
<xs:element name="Test1Response" type="Test1Response">
    
</xs:element>
    
<xs:complexType name="Record">
        
<xs:sequence>
            
<xs:element name="id" type="xs:int" />
            
<xs:element name="name" type="xs:string" />
        
</xs:sequence>
    
</xs:complexType>
</xs:schema>


Step 2:生成此XSD对应的.NET类,命令为:xsd.exe /classes filename.xsd,有了这个类文件就可以在Web Method中方便地使用符合Schema的XML数据了(而不是手工去分析传入的XML数据)。

Step 3:生成WSDL,我用了能集成进VisualStudio的WSCF工具来完成这个工作,其间设定了Web Method及其参数和返回值使用的Schema,以下是一个例子:

<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://groupm/TestService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:import1="http://tempuri.org/XMLSchema1.xsd" targetNamespace="http://groupm/TestService" name="TestService" xmlns="http://schemas.xmlsoap.org/wsdl/">
  
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
  
<types>
    
<xsd:schema>
      
<xsd:import schemaLocation="D:\Daniel\My Documents\Visual Studio 2005\Projects\M21116-2\M2WebService\XMLSchema1.xsd" namespace="http://tempuri.org/XMLSchema1.xsd" />
    
</xsd:schema>
  
</types>
  
<message name="testIn">
    
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
    
<part name="messagePart" element="import1:TestRequest" />
  
</message>
  
<message name="testOut">
    
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
    
<part name="messagePart" element="import1:TestResponse" />
  
</message>
  
<portType name="TestServiceInterface">
    
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
    
<operation name="Test">
      
<documentation xmlns="http://schemas.xmlsoap.org/wsdl/" />
      
<input message="tns:testIn" />
      
<output message="tns:testOut" />
    
</operation>
  
</portType>
  
<binding name="TestService" type="tns:TestServiceInterface">
    
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
    
<operation name="Test">
      
<soap:operation soapAction="http://groupm/TestService:Test" style="document" />
      
<input>
        
<soap:body use="literal" />
      
</input>
      
<output>
        
<soap:body use="literal" />
      
</output>
    
</operation>
  
</binding>
  
<service name="WebService">
    
<port name="WebServiceSoap" binding="tns:WebServiceSoap">
      
<soap:address location="http://localhost/M2WebService/WebService.asmx" />
    
</port>
  
</service>
</definitions>

注意:最后的service标签,工具不会自动生成,需要手工加入。

Step 4:生成.NET代码,这一步我也使用WSCF来完成,生成的是一个Interface和一个ASMX,此ASMX已经可以通过浏览器查看,只不过还未实现其中的业务逻辑。

Step 5:编写ASMX的业务逻辑代码,使Web Service能够真正运作。
注意:每次使用WSCF都会重新生成接口和ASMX,所以如果WSDL发生变化而需要更新,须注意不要覆盖了原先的代码。

Step 6:在Weblogic Workshop中新建一个Application,在Schema中import Step 1中生成的XSD文件,此时Weblogic会编译此文件并生成相应的XML Bean。

Step 7:在默认的Project中新建一个Java Control,选择Web Service,设定WSDL为Step 2中生成的文件,完成后便可通过这个控件开始使用此Web Service。
注意:Weblogic提供了完备的测试机制,可以自动生成测试文件,并可在测试过程中通过XML来传入Web Method的参数,这点比VisualStudio方便很多。

总结:目前此种开发方式虽然达到了很高的互操作能力,但由于集成开发环境的缺憾,生产效率会被大大降低,所以是否采用Contract-first approach还是的根据业务的需求来确定。


posted @ 2005-11-18 14:36 Daniel 阅读(1000) | 评论 (0)编辑

2005年10月2日 #

前些日子也是从这里得到邀请的,不知道还有没有朋友想要,发完为止吧。
daniel_ngn@hotmail.com
posted @ 2005-10-02 08:33 Daniel 阅读(248) | 评论 (5)编辑

2005年10月1日 #

若是一个page1.aspx向page2.aspx提交的流程,则在page2.aspx的顶部添加如下声明:
<%@ PreviousPageType VirtualPath="~/page1.aspx" %>

设置page1.aspx的PostbackUrl属性为~/page2.aspx。

假设page1.aspx的codebehind中有名为test()的方法,则在page2.aspx中可以这样调用:
  if (PreviousPage != null && PreviousPage.IsCrossPagePostBack)
  {
   return ((page1)PreviousPage).test();
  }



顺便记录一下注册客户端脚本的方法:
static readonly string script = "<script language=\"javascript\">\n" +
"alert (\"Sorry, but we couldn't validate your credit card\");\n" + "</script>";

ClientScript.RegisterStartupScript(script.GetType(), "Error", script);
posted @ 2005-10-01 09:22 Daniel 阅读(1392) | 评论 (7)编辑

和以前的用法有点不同,所以记录下来了。

ArrayList list = new ArrayList();
foreach (GridViewRow row in GridView1.Rows)
{
 CheckBox box = (CheckBox)row.Cells[3].Controls[1];
 if (box.Checked)
  list.Add(row.Cells[0].Text);
}
return list;


Dim list As ArrayList = New ArrayList()
For Each row As GridViewRow In GridView1.Rows
    Dim box As CheckBox = CType(row.Cells(3).Controls(1), CheckBox)
    If (box.Checked) Then
        list.Add(row.Cells(0).Text)
    End If
Next
Return list
posted @ 2005-10-01 08:59 Daniel 阅读(313) | 评论 (2)编辑

2005年9月29日 #

用户故事是从用户的角度对系统功能的描述,通过与用户一起探讨而得出,事实上XP的实践应由用户亲手撰写用户故事,但对很多用户来说并不容易,所以很多的实践过程中是开发人员和用户一起撰写。

开发人员依照用户故事中的描述估测完成每个任务需要的时间,并从项目经理处认领自己负责的任务,通常鼓励开发人员每次认领不同类型的任务,以提升对整个项目的认识及对不同类型技术的掌握。此处估测的时间在项目初期可能和实际完成时间有较大差距,但通过一段时间的实施之后,故测的时间也能八九不离十了。

领得自己负责的任务后,开发人员寻找结队伙伴,并开始实施过程。两者在边讨论边设计的过程中产生软件设计,并付诸测试和代码,此处产生的成果只有单元测试和代码而已,至于设计可以全部置于草稿纸上,一旦测试和代码完成便没有任何意义。若讨论过程中有明显的分歧,应该以任务负责人的想法为先。应该注意的是,这里为每个任务都分配了“负责人”,但XP的思想是整个开发团队对代码负责,而不是个人,因为事实上即使是单个任务也是由多个开发人员共同完成的。XP鼓励要经常更换结队伙伴,即使只是在一个任务中。

以下是一个用户故事的样例:

故事2运行处理退款请求故事(优先级:高  技术风险:低)
估算:开发时间 2周
2.1 获得某时间段银行的退款明细          0.5天
2.2 分页显示某时间段银行的退款明细列表,提供选择退款记录    2.5天
2.3 运行处理退款              2天
2.4 (约束)2.3可以补充退款信息卡号、姓名信息,如果要求输入卡号要输入2遍复核
2.5 (约束)2.4输入卡号提供3个4位输入第4个不限位数的分割输入,利于校对
2.6 (约束)2.4卡号栏目后面要留输入标注(本)(异)来区分本地卡和异地卡的空间
2.7 (约束)2.3可以选择部分或全部明细进行退款处理
2.8 (约束)2.3处理后退款明细记录状态要变更为运行已处理状态,并置运行处理日期
2.9 (约束)2.3按确认后要一个确认对话框,防止误操作
2.10 可以按条件获得退款明细列表          1天
2.11 (约束)2.10条件可以为:银行&退款处理状态&退款请求日期段
2.12 (约束)2.10条件可以为:商户&退款处理状态&退款请求日期段
2.13 (约束)不需要查询还在申请状态的退款
2.14 分页显示按条件获得运行已处理的退款明细列表      1.5天
2.15 (约束)2.14表头里须含查询条件信息及总笔数与金额信息
2.16 可以下载退款明细列表           2.5天
2.17 (约束)2.16数据组织成execl表格格式
2.18 (约束)2.16表可以按每个支付网关生成一份
2.19 (约束)2.16表可以按每个商户生成一份
2.20 (约束)2.16表中,部分支付网关除基本栏目外,一些栏目可以配置打印与否。
2.21 可以把运行已经处理过的退款交易回退给运行部门重新处理。
2.22 (约束)2.21可回退的退款交易必需是还没有被财务退过款的。

posted @ 2005-09-29 12:25 Daniel 阅读(1641) | 评论 (8)编辑

2005年9月28日 #

用HTML语法来编写xls文件尤其简单快捷,同时也具有基本的字体设置、单元格合并等功能,对于样式不是非常复杂的报表倒是不错的途径。
比如下列文本:
<table><tr><td>Data</td></tr></table>
在Excel中就能正常渲染,感觉比使用COM组件更方便点,对于普通的报表就无须COM或者VSTO来杀鸡用牛刀了。
还有点要注意的,我不知道这样写出来的报表怎样指定其单元格的数据类型,也就是说如果有一长串数字要作为字符串显示,推荐在数字前面或末尾加上&nbsp;,若是要将一连串数字以带小数的形式显示(即保留数字末尾的.00,Excel会默认去除小数末尾的0),单纯给它加上&nbsp;,会导致此单元格在Excel中无法参与运算,可以将数值格式化成带千位分隔符的形式:102,222.00,这样不仅可以保留末尾的0,也能在Excel中运算了。
posted @ 2005-09-28 13:41 Daniel 阅读(1095) | 评论 (4)编辑

最近稍微尝试了一下Microsoft Enterprise Library,感觉淋漓畅快,所以从新手的角度描述一下这个好玩的东西。

Microsoft Enterprise Library来源于MSDN patterns & practices,现在的版本是June 2005。它由一系列的.net项目和辅助工具构成,这些项目生成的DLL便是Enterprise Library的核心。这些类库是微软patterns & practices开发团队通过长期的项目实践、内部经验和大量客户反馈总结出的一系列设计模式的合集,目的是帮助开发人员方便地在项目中运用被业界广泛认可的最佳实践。

Enterprise Library是由许多Application Block组成的,每个Application Block都能实现一个特定领域的功能,比如数据库访问、日志记录、缓存管理、配置管理、加密、用户认证和授权、异常捕捉,它们既可以单独使用,也能够互相协作。由于微软提供了类库的全部源码,所以Enterprise Library具备很高的扩展性和灵活性。

使用Enterprise Library的典型步骤是:
1、为项目添加对所需使用的Application Block的引用(一个或多个DLL文件)。
2、通过Enterprise Library Configuration这个内置的辅助工具(我最喜欢的部分)对需要使用的Application Block进行配置。开发人员在可视化的环境下完成配置,工具会自动撰写应用程序的配置文件App.config和各个Application Block的配置文件(一些.config文件)。
3、在代码中调用这些Application Block以实现特定领域的功能。
4、配置项目的编译后动作,将所有的.config文件复制到应用程序可执行文件所在的目录。

推荐大家尝试一下Microsoft Enterprise Library的Hands on lab,会发现其实这套东西很容易上手,能为项目开发提供不少新的思路,免除很多原先要靠自己实现的机制,而且整个架构的灵活性、可靠性、可扩展性都会得到提高。

posted @ 2005-09-28 12:43 Daniel 阅读(2990) | 评论 (14)编辑

2005年9月27日 #

此篇援引资深项目经理tony的切身感受,对于实施XP过程中所需具备的多方面勇气,tony概括为以下几点:

一.你有勇气相信你现在写的测试、代码足够满足需求

二.你有勇气在需求变化时重构代码

三.你有勇气相信不做设计(实际上是在开发中设计)的开发,能在最后把各个零散的故事搭建成一个成型的系统


我想具备勇气便是已经战胜了自己,打破了最为艰难的一道屏障,实施XP便有了最根本的思想保证,其它的一切大可归为技术问题,总有解决的办法,唯有人心是最难冲破的一道坎儿。
posted @ 2005-09-27 21:02 Daniel 阅读(931) | 评论 (8)编辑

2005年9月26日 #

这里主要想讨论一下单元测试,目前Unit Test越来越被主流开发平台看好,先是Eclipse、NetBeans,现在又是VisualStudio 2005,甚至在Team System中还能施加强制Unit Test的Policy,将来的Weblogic Workshop 9可能也会进行相关集成,业界对此重视程度可见一斑。虽然Unit Test的好处不言而喻,但至今在中国,多数的项目开发仍然不会实施单元测试,即使有实施的,很多也是在外部Policy的压制下被迫进行单元测试的编写,以满足那字面上的测试用例代码覆盖率,真正程序员主动给程序配上单元测试的项目少之又少。其中很重要的一个原因便是多数人认为单元测试极大地浪费了他/她们的开发时间,降低工作效率。其实自从前段时间对XP的实践之后,我能清晰地感觉到Unit Test带来的不仅是软件质量的提升,更是开发效率的提高,这是什么道理呢?看完本文便有答案了。

一个不能忽视的问题是,目前很多软件开发过程中的测试仍然只是随便搞点数据,跑过算数,所谓测试用例的个数毛估估的也是个别现象,我认为这不能算是成功的测试,而且也会为日后项目的进展埋下隐患。说老实话,单元测试并不容易,当然如果我程序的每个类实现的都是加法减法这样的操作,那单元测试或许是相当好写的,可现实世界纷繁复杂的业务逻辑、大量的数据库操作占据了绝对主流,如何进行单元测试呢?

单元测试也有一些原则,首先便是测试先行!无论要实现什么功能,XP的主张:先写测试。在书写测试的过程中,程序员学习并深入了解需要实现的业务逻辑,发现疑问并寻求解答。这是Test Driven Development(TDD)的基本实践,可以避免程序员盲目书写程序代码可能蕴藏的隐患,在没有完全了解或自以为完全了解业务逻辑的情况下写出来的代码很有可能会在将来的某一天被重构或修正掉,与其到那个时候去费工作量,还不如静下心来考虑考虑将要做的程序到底是怎样运作的,有哪些意外情况可能会发生。

其次是无依赖原则,即任何一个单元测试的运行及其结果都不依赖于外部环境,这些环境可能包括操作系统环境变量的配置、数据库中的数据、运行的时间等等。无论何时运行,只要代码不变,结果都应该是一致的。其中接触最多的可能就属数据库了,在单元测试中,开始对代码进行测试之前,首先要准备好测试可能需要的数据,通过把准备数据的代码写入单元测试中,可以达到一劳永逸的效果,一次编写,多次执行,也为自动测试提供了可能。当然设计这些数据往往很费脑筋,要能做出足够量的能测出所有相关业务逻辑的数据并不是很轻松的工作,但也正是在这样的设计过程中,充分考验程序员对需求的认知程度,最大程度避免程序的漏洞和死角。

然后是无踪迹原则,即测试运行前后系统状态保持一致,数据库的数据也不因测试而发生增减,所有测试生成的数据一律删除。这就如同是MGS中的Snake不能留下任何潜入的足迹一样,XP主张单元测试也要不留痕迹,这也是多次自动运行结果一致的重要保障。所以在编写单元测试时,清场的代码千万不可忽视,尤其是那些由正常的业务逻辑代码生成的数据,一定要想办法抓住特征,予以删除。

最后是进化原则,这也是XP的简单教条在测试方面的体现。无论何时都不应期望在一开始就写出面面俱到毫无破绽的测试用例。随着经验的增长,首次测试案例的质量会愈加提升,但在一开始就进行过度测试是不可取的实践。在集成测试中必然会暴露单元测试未能成功捕捉的bug,此时对原先的单元测试进行修改,并通过衰退测试(即用新的测试代码捕捉原有程序的漏洞)验证新的单元测试是有效的。单元测试也和业务代码一样始终处于不断修正、充构、进化的道路上。

说到这里,再来总结一下为什么单元测试提高了开发效率,首先是其一次编写多次自动执行的特征使得准备完善测试数据的工作量得到大大减轻,其次在发生代码重构时,把单元测试全部运行一遍便足以保证重构没有给系统带来破坏性的打击,这种情况下若是没有单元测试,那某些牵一发而动全身的重构或代码修改可能导致的后果就没人能说清楚了,组织人力对所有可能受影响的模块进行人工测试又是另一个庞大的工作量。看似单元测试使程序员多写了很多代码,事实上在很大程度上降低了可能的工作强度,而且使程序员也更为自信,做到面对任何代码修正都心中有底。

当然,单元测试只是测试的一个方面,之后还有界面测试、压力测试等等,我并不想以偏概全,因为自己也曾经吃过光重视单元测试忽视其它测试的苦头,我想说明的是单元测试在目前国内开发实践中的运用还是相当欠缺,而它能解决的问题却是最多的,希望有更多程序员出于自身的需要、发自内心地投入到单元测试的队伍中来。

posted @ 2005-09-26 13:32 Daniel 阅读(837) | 评论 (1)编辑

NO.1 Omnicom (天联广告 李岱艾 恒美 浩腾媒体等)

NO.2 WPP集团  (奥美 JWT 达彼思 百帝 电扬 精信 传立媒体 尚扬媒体 迈势媒体 灵立媒体等)

NO.3 IPG集团   (麦肯 FCB 灵狮 优势麦肯等)

NO.4 Publics集团   (盛世长城 李奥贝纳 阳狮恒威 实力媒体 星传媒体等)

NO.5 Dentsu集团  (***广告)

NO.6 Havas集团   (灵智大洋等)

posted @ 2005-09-26 13:04 Daniel 阅读(547) | 评论 (0)编辑