分析ASP.NET Routing最令人疑惑的设计

开发 后端
您觉得ASP.NET Routing中最令人摸不着头脑的设计是什么?笔者认为是RouteBase类,想知道为什么?请阅读下文。
  1. public abstract class RouteBase  
  2. {  
  3.     protected RouteBase() { }  
  4.     public abstract RouteData GetRouteData(HttpContextBase httpContext);  
  5.     public abstract VirtualPathData GetVirtualPath(  
  6.         RequestContext requestContext,  
  7.         RouteValueDictionary values);  

它为什么是一个没有任何实现的抽象类,而不是一个接口(如下)?

  1. public interface IRoute  
  2. {  
  3.     RouteData GetRouteData(HttpContextBase httpContext);  
  4.     VirtualPathData GetVirtualPath(  
  5.         RequestContext requestContext,  
  6.         RouteValueDictionary values);  

这样做难道不更漂亮一些吗?这样代码中都可以使用IRoute类型,避免RouteBase这种令人反感的命名出现(个人感觉,不知道有没有同意的群众)。退一步说,命名上的“美感”是小事……但是抽象类在.NET平台中就产生了一个非常严重的限制:一个类无法继承多个基类。因此,在.NET平台上总是更倾向于使用接口,而不是抽象类。

但是接口里不可以有任何实现,那么可复用的功能又放在哪里比较合适呢?《Framework Design Guildlines》告诉我们:在一个类库中,***为接口定义一个默认实现,这样也是开发人员进行“扩展”的一个“参考”。也就是说,如果真有什么需要复用的实现,我们完全可以这么做:

  1. public abstract class RouteBase : IRoute  
  2. {   
  3.     // reusable implementations  
  4. }  
  5.  
  6. public class Route : RouteBase  
  7. {  
  8.     // concrete implementations  

事实上,.NET平台上有许多类库也遵循了这个做法。一个典型的做法便是ASP.NET AJAX框架的Extender模型:

  1. public interface IExtenderControl { }  
  2. public abstract class ExtenderControl : Control, IExtenderControl { } 

甚至在ASP.NET AJAX Control Tookit项目中,还有更进一步的扩展:

  1. public abstract class ExtenderControlBase : ExtenderControl { }  
  2. public class AnimationExtenderControlBase : ExtenderControlBase { }  
  3. public class AutoCompleteExtender : AnimationExtenderControlBase { } 

看来微软在项目团队内部推广《Framework Design Guidelines》还不够彻底。

在.NET平台下,一个没有任何实现的,纯粹的抽象类可谓有百害而无一利。我很怀疑写这段代码的人刚从C++切换到C#——但是ASP.NET Routing中其实也有接口(如IRouteConstraint),为什么作者自己没有意识到,也没有人提出不同意见呢?微软开发团队应该有着严格的Code Review过程,怎么会让这样的代码正式发布?要知道一个接口一旦公开,就不可以删除了。也就是说,微软很难弥补这个错误。

如果是方法名不好,或者职责有些不明确,这样还可以在旧方法上添加ObsoleteAttribute(这样编译器便会提示用户这个方法已经过期),并且将旧方法的调用委托给新的实现。例如:

  1. public abstract class CodeDomProvider : Component  
  2. {  
  3.     [Obsolete(  
  4.         "Callers should not use the ICodeCompiler interface and should  
  5.          instead use the methods directly on the CodeDomProvider class.  
  6.          Those inheriting from CodeDomProvider must still implement this 
  7.          interface, and should exclude this warning or also obsolete this 
  8.          method.")]  
  9.     public abstract ICodeCompiler CreateCompiler();  
  10.  
  11.     [Obsolete(  
  12.         "Callers should not use the ICodeParser interface and should  
  13.          instead use the methods directly on the CodeDomProvider class.  
  14.          Those inheriting from CodeDomProvider must still implement this 
  15.          interface, and should exclude this warning or also obsolete this 
  16.          method.")]  
  17.     public virtual ICodeParser CreateParser();  
  18.  
  19.     ...  

可是,现在的问题是一个“类”,而这个类已经无处不在了,例如在RouteData中有一个属性Route,它便是RouteBase类型——如果将其修改为IRoute接口,那么至少也需要项目重新编译之后才能够“升级”。而作为一个公开类库,尤其是.NET这种成熟框架来说,应该做到“无痛”才对。

本文来自赵劼博客园文章《ASP.NET Routing中最令人摸不着头脑的设计

【编辑推荐】

  1. ASP.NET控件学习总结
  2. 有关ASP.NET MVC框架的一些基础知识
  3. 再谈ASP.NET缓存机制:开发效率与优化的平衡
  4. 如何避免ASP.NET缓存占用系统资源
  5. 点评一下ASP.NET的WEB控件
责任编辑:彭凡 来源: 博客园
相关推荐

2009-08-19 09:23:40

ASP.NET Rou

2009-07-21 15:11:14

ASP.NET Rou

2009-10-15 14:50:34

ASP.NET Rou

2009-10-26 15:55:43

URL Routing

2009-08-21 10:51:55

ASP.NET Rou解析URL

2014-08-26 09:22:40

ASP.NET MVCRouting

2009-03-12 10:42:38

RoutingIgnoreRouteASP.NET

2009-07-27 11:09:09

ASP.NET招聘系统

2009-08-10 13:32:15

ASP.NET TimASP.NET组件设计

2009-03-09 13:46:31

RoutingWebASP.NET

2009-07-29 17:29:46

ASP与ASP.NET

2009-08-10 10:19:47

ASP.NET组件设计

2009-08-05 16:53:14

ASP.NET组件设计

2015-06-18 14:13:36

ASP.NET

2009-08-03 14:22:33

什么是ASP.NET

2009-07-28 17:17:19

ASP.NET概述

2009-08-10 14:08:15

ASP.NET服务器控ASP.NET组件设计

2009-04-23 10:33:52

ASP.NET设计思想微软

2009-08-07 17:49:44

控件设计器

2009-07-22 17:45:35

ASP.NET教程
点赞
收藏

51CTO技术栈公众号