ASP.NET Routing介紹
您覺得ASP.NET Routing中最令人摸不著頭腦的設計是什么?我認為是RouteBase類:
- public abstract class RouteBase
- {
- protected RouteBase() { }
- public abstract RouteData GetRouteData(HttpContextBase httpContext);
- public abstract VirtualPathData GetVirtualPath(
- RequestContext requestContext,
- RouteValueDictionary values);
- }
它為什么是一個沒有任何實現的抽象類,而不是一個接口(如下)?
- public interface IRoute
- {
- RouteData GetRouteData(HttpContextBase httpContext);
- VirtualPathData GetVirtualPath(
- RequestContext requestContext,
- RouteValueDictionary values);
- }
這樣做難道不更漂亮一些嗎?這樣代碼中都可以使用IRoute類型,避免RouteBase這種令人反感的命名出現(個人感覺,不知道有沒有同意的群眾)。退一步說,命名上的“美感”是小事……但是抽象類在.NET平臺中就產生了一個非常嚴重的限制:一個類無法繼承多個基類。因此,在.NET平臺上總是更傾向于使用接口,而不是抽象類。
但是接口里不可以有任何實現,那么可復用的功能又放在哪里比較合適呢?《Framework Design Guildlines》告訴我們:在一個類庫中,***為接口定義一個默認實現,這樣也是開發(fā)人員進行“擴展”的一個“參考”。也就是說,如果真有什么需要復用的實現,我們完全可以這么做:
- public abstract class RouteBase : IRoute
- {
- // reusable implementations
- }
- public class Route : RouteBase
- {
- // concrete implementations
- }
事實上,.NET平臺上有許多類庫也遵循了這個做法。一個典型的做法便是ASP.NET AJAX框架的Extender模型:
- public interface IExtenderControl {
- }
- public abstract class ExtenderControl : Control, IExtenderControl {
- }
甚至在ASP.NET AJAX Control Tookit項目中,還有更進一步的擴展:
- public abstract class ExtenderControlBase : ExtenderControl {
- }
- public class AnimationExtenderControlBase : ExtenderControlBase {
- }
- public class AutoCompleteExtender : AnimationExtenderControlBase {
- }
看來微軟在項目團隊內部推廣《Framework Design Guidelines》還不夠徹底。
在.NET平臺下,一個沒有任何實現的,純粹的抽象類可謂有百害而無一利。我很懷疑寫這段代碼的人剛從C++切換到C#——但是ASP.NET Routing中其實也有接口(如IRouteConstraint),為什么作者自己沒有意識到,也沒有人提出不同意見呢?微軟開發(fā)團隊應該有著嚴格的Code Review過程,怎么會讓這樣的代碼正式發(fā)布?要知道一個接口一旦公開,就不可以刪除了。也就是說,微軟很難彌補這個錯誤。
如果是方法名不好,或者職責有些不明確,這樣還可以在舊方法上添加ObsoleteAttribute(這樣編譯器便會提示用戶這個方法已經過期),并且將舊方法的調用委托給新的實現。例如:
- public abstract class CodeDomProvider : Component
- {
- [Obsolete(
- "Callers should not use the ICodeCompiler interface and should
- instead use the methods directly on the CodeDomProvider class.
- Those inheriting from CodeDomProvider must still implement this
- interface, and should exclude this warning or also obsolete this
- method.")]
- public abstract ICodeCompiler CreateCompiler();
- [Obsolete(
- "Callers should not use the ICodeParser interface and should
- instead use the methods directly on the CodeDomProvider class.
- Those inheriting from CodeDomProvider must still implement this
- interface, and should exclude this warning or also obsolete this
- method.")]
- public virtual ICodeParser CreateParser();
- ...
- }
可是,現在的問題是一個“類”,而這個類已經無處不在了,例如在RouteData中有一個屬性Route,它便是RouteBase類型——如果將其修改為IRoute接口,那么至少也需要項目重新編譯之后才能夠“升級”。而作為一個公開類庫,尤其是.NET這種成熟框架來說,應該做到“無痛”才對。
這次微軟真搞笑了。以上介紹ASP.NET Routing。
原文出處博客園,作者趙劼
【編輯推薦】