说到“Contract-First”,那么就首先要补充一下这一句:“Services share schema and contract, not class”。
Contract-First绝对是设计Service-Oriented系统中最重要的原则和理念之一。如果要动手做一个Service-Oriented的东东,首先要领会的关键之一,就是Contract-First。Service对外公开的接口,应当就是一个Contract,这个Contract的作用就像是它自己对外说明:“我能够提供哪些哪些服务,这些服务需要哪些哪些参数,会返回哪些哪些值...”如果服务间需要传递数据,那么也需要有Service和Client端公认的Contract,这个Contract用来说明:“我们要传递的这个数据,第一项是一个字符串用来包含姓名信息的,第二项是一个整数,包含了一个年龄信息...”由于Service间通常都会用SOAP包来交流,对于SOAP包的编码格式等信息,也需要用Contract来说明。
虽然已经有N多人在跟帖说“WebService != SOA”,但我还是要先拿WebService来说事儿。如何用Contract-First的概念来构建一个WebService呢?我们需要首先定义用来交换的数据的Contract(Data Contract),xsd就是用来定义数据Schema的。然后,我们再来定义Service和Client间进行通信的消息的Contract(Message Contract),别忘了Messsage-Based是Service-Oriented的基本特点之一。接着,根据这些由xsd来定义的Data Contract和Message Contract,生成我们的描述文件wsdl。wsdl描述了Service的接口和其用到的数据结构。从wsdl,我们就可以生成用来支持开发的实际的类代码文件了。
可以看出,Contract-First的设计理念和平时我们用来构建WebService的方式大相径庭。Contract-First的观点是需要首先确定Service与Client进行交互的各种Contract,数据的、消息的、接口的,而不是我们先把实际的类代码写出来,然后给它加上“[WebMethod]”,使其成为WebService接口。
WSCF是一个支持Contract-First理念设计WebService的工具,它是VS.NET的一个插件,可以非常方便的支持上面所描述的方式和步骤,来构建WebService。
使用Contract-First构建WebService的好处,就是Contract是独立的、可移植的、脱离于代码的。由于我们可以使用xsd来描述Contract,所以只需要和其他Service共享这些xsd描述文件,那么Service间就能共享这些Contract。我们不再需要让另外的Service去引用包含了Person实体对象的程序集,才能达到对方Service能交换Person数据的目的。相反,我们只需要共享出描述了Person结构的Data Contract给对方Service,即使对方Service可能是用Java实现的,它们也能根据这些Data Contract在它们的平台上生成实际的支持代码,并以符合Contract的方式来和本地的Service交换Person数据。
下面的截图出自WSCF:
定义的Data Contract:
定义的Message Contract:
Contract是由xsd文件来描述的:
最后,由Contract,自动生成WSDL描述文件,然后从WSDL生成实际的支持代码:
可以看到,上面的方式完全不同于传统的代码->加上[WebMethod]->自动由.asmx?wsdl生成wsdl等步骤。
说了这么多,再把目光投向Indigo。Indigo已经发布了第一个公开的CTP版本,所以也是时候开始在Blog里面写写Indigo了。Indigo是微软用于构建Connected System的一个开发框架,整个架构都非常符合Service-Oriented的理念。所以,Contract-First同样也是Indigo的基本概念之一。
下面是Indigo里面的一个Data Contract示例,Indigo里面使用[DataContractAttribute]来标识Data Contract:
[DataContract]
public class Person
{
[DataMember]
public String Name;
[DataMember]
public DateTime Birthday;
}
下面就是一个Indigo Service接口示例,同样是使用了Attribute来标识Service Contract,和Service Contract中所包含的Service Operation:
[ServiceContract]
public interface IPersonService
{
[OperationContract]
Person GetPerson(String name);
[OperationContract]
void UpdatePerson(Person person);
}
public class PersonService : IPersonService
{
...
}
下篇Blog将会专门介绍Indigo。