WCF分布式开发步步为赢(6):WCF服务契约继承与分解设计

简介:
上一节我们学习了 WCF分布式开发步步为赢(5)服务契约与操作重载部分。今天我们来继续学习WCF服务契约继承和服务分解设计相关的知识点。WCF服务契约继承有何优势和缺点?实际项目里契约设计有什么原则和依据?面向对象的设计经验有何值得借鉴的地方?这里我们会一一给出详细的介绍。本文首先介绍的是WCF服务中契约继承的一些概念、例子代码分析,其次来讲解服务契约的设计问题。首先介绍的也是进行服务设计的必要性,服务设计的原则,示例代码分析。最后是全文的总结部分。结构如下:【1】OO面向对象设计原则,【2】服务契约继承,【3】服务契约分解概念,【4】服务契约分解原则,【5】服务契约分解代码分析,【6】总结。
【1】面向对象设计原则OO:
    这里我们有必要先回顾一下面向对象的经典的设计原则。这些设计原则对我们WCF服务契约的设计来说有重要的参考价值。服务契约实际利用了接口来定义实现,语法类似,WCF框架也是基于现有的语言体系,对此扩展了编程模型,比如增加了属性设置机制等。如果你曾经接触过OO面向对象的这些概念,那么这些设计原则理解起来不会困难。很多编程书籍里都会有介绍,设计模式相关书籍里会有比较详细的介绍。这里介绍几个主要的概念,为下文的继承和设计WCF服务契约部分作铺垫:
<1>单一职责原则(SRP): 一个类应该仅有一个引起它变化的原因。
<2>开放封闭原则(OCP): 类模块应该是可扩展的,但是不可修改(对扩展开放,对更改封闭)。
<3>Liskov 替换原则(LSP): 子类必须能够替换它们的基类。
<4> 依赖倒置原则(DIP): 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。 抽象不应该依赖于实现细节,实现细节应该依赖于抽象。
<5>接口隔离原则(ISP): 不应该强迫客户程序依赖于它们不用的方法。
【2】服务契约继承:
     服务契约的定义和接口定义类似,接口可以继承与多个接口。但是WCF契约属性是不支持继承的。由于WCF框架自身的问题,不支持契约属性的继承,因此这给我们服务契约属性的声明和使用却有不少限制。在使用契约继承属性的过程中腰注意服务端契约的属性继承问题,此外就是客户端添加服务引用后,无法还原服务端契约层级的关系,所有的操作契约由一个契约类封装。因此实际编程我们要兼顾到两个方面的情况。
【2.1】服务端契约层级:
接口支持继承。但ServiceContract特性不支持继承的,我们查看其实现代码可以知道Inherited = false,即不支持继承,部分代码如下:
    [AttributeUsage(AttributeTargets.Class  |  AttributeTargets.Interface, Inherited  =   false , AllowMultiple  =   false )]
    
public   sealed   class  ServiceContractAttribute : Attribute
    {
        
    }
     因此在定义多层服务契约接口的时候,我们必须在每层接口上标记ServiceContract属性,以支持WCF服务契约属性。
 示例代码如下:
    // 契约属性不支持继承,如果需要继承契约属性,接口标志契约属性,定义一个交通工具基接口契约
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  IVehicle
    {

    }
    
// 接口继承关系不支持ServiceContract继承
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  ITruck : IVehicle
    {
    }
货车服务类能够实现整个WCF契约层级接口,我们这里实现了Run跑和Carry运输货物的契约,代码如下:
     // 货车服务类实现货车服务契约
     public   class  WCFServiceTruck : ITruck
    {
        
// 实现接口定义的方法
         public   string  Run()
        {
            Console.WriteLine(
" Hello! ,This an inherite demo " );
            
return   " Hello! Truck is running   " ;
        }
        
// 实现接口定义的方法
         public   string  Carry()
        {
            Console.WriteLine(
" Hello! ,This an inherite demo " );
            
return   " Hello! Truck is carrying   " ;
        }

    }
宿主可以为契约层级最底层的接口公开一个单独的终结点,配置文件设置代码如下:
       < service behaviorConfiguration = " WCFService.WCFServiceBehavior "  name = " WCFService.WCFServiceTruck " >
        
< endpoint
           address
= " http://localhost:9003/WCFServiceTruck "
           binding
= " wsHttpBinding "
           contract
= " WCFService.ITruck " >
        
</ endpoint >
        
< endpoint address = " mex "  binding = " mexHttpBinding "  contract = " IMetadataExchange "   />
        
< host >
          
< baseAddresses >
            
< add baseAddress = " http://localhost:9003/ " />
          
</ baseAddresses >
        
</ host >
      
</ service >
【2.2】客户端契约层级:
    客户端添加服务端数据引用,导入一个服务终结点的元数据时,反序列化生成的客户端契约将不再维持原来的层级关系。一个单独的契约,名称为终结点公布的契约名。含了层级中继承相关所有接口定义的操作契约。OperationContract特性中的Action与ResponseAction属性,可以保留原来定义每个操作的契约名。我们要想恢复服务端契约继承的层级关系,客户端可以手工修改代理以及导入契约的定义,恢复契约层级。手动恢复方式其实带给我们很多灵活性,但是也增加了工作量和复杂度。实际项目里一般接触不多,这里就不详细介绍,需要的话可以查阅相关的资料。
【2.2】服务契约分解概念:
     下面我们继续讲解服务契约设计的一些概念知识。其实服务契约的设计在WCF分布式应用项目中属于比较重要的部分。服务契约的设计和实现相对来多比较复杂,除了注意已有的设计原则之外还要注意WCF契约相关的特性。面向服务分析与设计的属于一个较新的领域。实际的服务分析和设计我们还是借助于已有的经验和原则,来指我们更好地设计服务契约。这也是本节给出一个面向对象重要设计原则的原因。
因为WCF服务契约的定义借助现有的编程语言如C#,契约设计实际首先就是对服务接口的设计。我们应该如何设计服务接口?如何知道服务接口中应该定义哪些操作?每个接口又应该包含多少操作?等等都是我们必须考虑的问题。Service Contract Factoring就是要考虑服务接口的分解问题。在面向服务的应用程序中,可重用的基本单元就是服务接口。因此如何设计服务接口就是重中之重。
【4】服务契约分解原则:
这里我们设计服务接口时候即遵循单一职责和接口隔离等原则,又要考虑系统的开发成本。合理的接口是专业的、松耦合的、规则化和可重用的接口。这些优势同样有利于整个系统的松耦合和可重用等特性。总的来说,契约分解的目的就是使接口包含的更少操作。
如果我们定义了太多的细粒度服务接口,虽然它们易于实现,但集成它们的代价太高。如果我们仅定义了一个复杂的服务接口,虽然集成的成本会降低,但却接口的实现和可维护性较差。我们设计面向服务的系统时,需要平衡两个影响系统的因素,接口成本和集成成本。参见下图。
系统服务的代价为实现的代价与集成的代价的综合。上图显示了最小代价与服务接口规模和数量之间的关系。设计良好的系统应该在系统集成成本和契约接口设计实现成本之间作何平衡点,达到系统整体开发成本的降低。
【5】服务契约分解代码分析:
这里我们来讲解一个简单的服务契约设计的例子。这里我们还继续使用交通车为例子进行讲解。
我们首先定义一个接口交通工具IVehicle,定义了如下:
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  IVehicle
    {
        
// 操作契约,跑,开的契约
        [OperationContract]
        
string  Run();
        
// 操作契约,拉人、载人的契约
        [OperationContract]
        
string  Take();
        
// 操作契约,运输货物的契约
        [OperationContract]
        
string  Carry();
    }
    这里的交通工具接口,分别定义了跑,拉人和载货三种操作。放在一个接口中。这就违反了接口设计中的主要的原则ISP接口隔离原则。我们不应该强迫服务继承他们不需要的操作。接口隔离原则ISP:使用多个专门的接口比使用单一的接口要好。从服务设计的角度来说:一个类对另外一个类的依赖性应当是建立在最小的接口上的。如果服务类只需要某一些方法的话,那么就应服务类可以继承相应的接口实现这些需要的方法,而不要实现不需要的方法。继承接口意味着作出承诺,服务类必须实现,也就是所谓的契约的概念。
因此,我们将服务契约分解为接口层级的方式,通过接口分解和继承,实现操作的分离。这里可以重新定义两个接口货车ITruck和小轿车ICar,分别定义自己的拉货Carry();和载人Take()的操作,当服务类需要实现拉货操作的时候就继承避免了接口设计的职责的混淆。代码如下:
// 契约属性不支持继承,如果需要继承契约属性,接口标志契约属性,定义一个交通工具基接口契约
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  IVehicle
    {
        
// 操作契约,跑,开的契约
        [OperationContract]
        
string  Run();
    }
    
// 接口继承关系不支持ServiceContract继承
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  ITruck : IVehicle
    {
        
// 操作契约,运输货物的契约
        [OperationContract]
        
string  Carry();
    }
    
// 接口继承关系不支持ServiceContract继承
    [ServiceContract(Namespace  =   " http://www.cnblogs.com/frank_xl/ " )]
    
interface  ICar : IVehicle
    {
        
// 操作契约,拉人、载人的契约
        [OperationContract]
        
string  Take();
    }
 
【6】总结:
   以上就是对WCF服务继承和分解设计相关知识的介绍,下面简要做下介绍:
    <1>:本文开始讲解了OO面向对象的设计原则,作为经典的面相对象的设计经验,也是设计模式文章里的重要的知识点,对WCF服务设计有主要的参考价值,比如SRP单一职责、ISP接口隔离等原则;
    <2>:我们应该避免设计过多或者过少的接口,应该考虑系统的服务接口定义实现的复杂度和系统服务集成的成本。综合起来权衡,取得一个平衡点。服务契约成员的最佳数量(根据经验总结,仅代表本人观点)应介于3到5之间。开发者在制订WCF编码规范时,应该指定一个上限值(例如20)。无论在何种情况,都不能超过该值。
另外避免定义类属性操作(Property-Like Operation)这样的定义十分类似C#的属性访问器,例如:
[OperationContract]
string  GetCarNumber(); 
我们不应该干涉客户端属性访问,客户端在调用抽象操作时,不用关心具体的实现细节,只负责调用操作,而由服务去管理服务对象的状态。
<3>:WCF服务设计原则只是一些参考原则,对实际的开发工作起知道作用。包括前面叙述的面相对象的经典的设计原则和设计模式的宝贵经验。实际项目中需要结合自身的实际情况,实时调整和设计服务契约接口的设计,以期设计去更加合理和高效的服务契约。最后是本文的参考代码: Files/frank_xl/WCFServiceFactoringFrankXuLei.rar,下一节我们继续学习WCF数据契约的知识,请继续关注~。
参考资料:
1.《Programming WCF Services 》,By Juval Lowy;




 本文转自 frankxulei 51CTO博客,原文链接:http://blog.51cto.com/frankxulei/320410,如需转载请自行联系原作者


相关文章
|
4月前
|
安全 前端开发 开发者
“你还活着吗?” “我没死,只是网卡了!”——来自分布式世界的“生死契约”
Lease机制是分布式系统核心协调技术,通过带时限的授权确保一致性与可靠性,广泛用于领导者选举、状态判定等场景。授权者承诺在Lease有效期内不变更权限,接收方需在到期后重新申请。基于Lease可避免“双主”问题,提升容错能力。ETCD等协调服务内置Lease支持,允许多key绑定同一Lease,降低刷新开销,提升性能。
171 2
|
9月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
346 5
|
8月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
848 35
|
数据管理 API 调度
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
HarmonyOS Next 是华为新一代操作系统,专注于分布式技术的深度应用与生态融合。本文通过技术特点、应用场景及实战案例,全面解析其核心技术架构与开发流程。重点介绍分布式软总线2.0、数据管理、任务调度等升级特性,并提供基于 ArkTS 的原生开发支持。通过开发跨设备协同音乐播放应用,展示分布式能力的实际应用,涵盖项目配置、主界面设计、分布式服务实现及部署调试步骤。此外,深入分析分布式数据同步原理、任务调度优化及常见问题解决方案,帮助开发者掌握 HarmonyOS Next 的核心技术和实战技巧。
1555 76
鸿蒙HarmonyOS应用开发 | 探索 HarmonyOS Next-从开发到实战掌握 HarmonyOS Next 的分布式能力
|
10月前
|
消息中间件 人工智能 监控
文生图架构设计原来如此简单之分布式服务
想象一下,当成千上万的用户同时要求AI画图,如何公平高效地处理这些请求?文生图/图生图大模型的架构设计看似复杂,实则遵循简单而有效的原则:合理排队、分工明确、防患未然。
424 14
文生图架构设计原来如此简单之分布式服务
|
8月前
|
消息中间件 缓存 算法
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
591 0
分布式开发:数字时代的高性能架构革命-为什么要用分布式?优雅草卓伊凡
|
SQL 分布式计算 DataWorks
MaxCompute MaxFrame评测 | 分布式Python计算服务MaxFrame(完整操作版)
在当今数字化迅猛发展的时代,数据信息的保存与分析对企业决策至关重要。MaxCompute MaxFrame是阿里云自研的分布式计算框架,支持Python编程接口、兼容Pandas接口并自动进行分布式计算。通过MaxCompute的海量计算资源,企业可以进行大规模数据处理、可视化数据分析及科学计算等任务。本文将详细介绍如何开通MaxCompute和DataWorks服务,并使用MaxFrame进行数据操作。包括创建项目、绑定数据源、编写PyODPS 3节点代码以及执行SQL查询等内容。最后,针对使用过程中遇到的问题提出反馈建议,帮助用户更好地理解和使用MaxFrame。
|
SQL 分布式计算 数据处理
云产品评测|分布式Python计算服务MaxFrame | 在本地环境中使用MaxFrame + 基于MaxFrame实现大语言模型数据处理
本文基于官方文档,介绍了由浅入深的两个部分实操测试,包括在本地环境中使用MaxFrame & 基于MaxFrame实现大语言模型数据处理,对步骤有详细说明。体验下来对MaxCompute的感受是很不错的,值得尝试并使用!
313 1
|
11月前
|
机器学习/深度学习 存储
DeepSeek进阶开发与应用4:DeepSeek中的分布式训练技术
随着深度学习模型和数据集规模的扩大,单机训练已无法满足需求,分布式训练技术应运而生。DeepSeek框架支持数据并行和模型并行两种模式,通过将计算任务分配到多个节点上并行执行,显著提高训练效率。本文介绍DeepSeek中的分布式训练技术,包括配置与启动方法,帮助用户轻松实现大规模模型训练。数据并行通过`MirroredStrategy`同步梯度,适用于大多数模型;模型并行则通过`ParameterServerStrategy`异步处理大模型。DeepSeek简化了分布式环境配置,支持单机多卡和多机多卡等场景。
|
分布式计算 数据处理 MaxCompute
云产品评测|分布式Python计算服务MaxFrame
云产品评测|分布式Python计算服务MaxFrame
247 2