ASP.NET Routingの中で最も頭に入らないデザイン

5568 ワード

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プラットフォームでは、1つのクラスが複数のベースクラスを継承できないという非常に深刻な制限が発生しています.したがって、.NETプラットフォームでは、抽象クラスではなくインタフェースを使用する傾向があります.
しかし、インタフェースには何の実装もできません.では、多重化可能な機能はどこに置くのが適切ですか.「Framework Design Guildlines」は、クラスライブラリでインタフェースのデフォルト実装を定義することが望ましいことを示しています.これは、開発者が「拡張」を行うための「参照」でもあります.つまり、もし本当に多重化が必要な実装があれば、私たちは完全にそうすることができます.
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など)がありますが、なぜ著者自身が意識していないのか、異なる意見を出す人もいないのでしょうか.マイクロソフトの開発チームは厳格なCode Reviewプロセスを持っているはずですが、どうしてこのようなコードを正式に発表することができますか?インタフェースが公開されると、削除できないことを知っておく必要があります.つまり、マイクロソフトはこの間違いを補うのが難しいということです.
メソッド名が悪い場合や、職責が不明な場合は、古いメソッドに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にはRouteBaseタイプの属性Routeがあります.これをIrouteインタフェースに変更すると、少なくともプロジェクトの再コンパイルが必要になります.公開クラスライブラリとして、特に.NETという成熟した枠組みでは、「無痛」にすべきだ.
今度のマイクロソフトは本当に面白いですね.
 
注1:これはもちろん大げさなやり方で、抽象類には優位性がないわけではありません.『抽象類とインタフェースをもう一度話してください』に注目してください.