Whidbey Provider Design Pattern pitfalls

Note: this entry has moved.

A couple weeks ago Rob Howard (from the ASP.NET team) announced the "disclosure" of the Provider Design Pattern they are using in Whidbey ASP.NET (v2).

I've got a couple complaints with this implementation:

  • Naming: Brad Adams (the guy behind design guidelines), is explicitly discouraging the practice of adding a "Base" prefix/suffix to abstract classes targeted to be the root of a class hierarchy. Yet, the pattern explained by Rob defines ProviderBase, MembershipProviderBase and so on. Not good. If these guidelines aren't followed by MS, you can't expect independant developers to do so, right?
  • Collection typing: as defined, each functionality (i.e. Membership, RoleManager, etc.) defines a Providers property of type ProviderCollection, defined as follows: public class ProviderCollection : IEnumerable { // Methods // public void Add(ProviderBase provider); public void Clear(); public void Remove(string name); public void SetReadOnly(string name); // Properties // public ProviderBase this(string name) { get; set; } public int Count { get; set; } } Therefore, I need to cast whenever I need to access a particular provider. Now that Whidbey has generics, it seems appropriate to define the collection as: public class ProviderCollection<T> where T:ProviderBase : IEnumerable { // Methods // public void Add(T provider); public void Clear(); public void Remove(string name); public void SetReadOnly(string name); // Properties // public T this(string name) { get; set; } public int Count { get; set; } }

    Membership, therefore, would only need to define its Providers property as follows:

    public ProviderCollection<MembershipProviderBase> Provider { get; set; }
  • Configuration:  As defined, the ProviderBase class contains an Initialize method with the following signature: public abstract void Initialize(string name, NameValueCollection config); Well, can anybody tell me why the config is not an XmlNode or an XPathNavigator at least? Given the configuration is already in XML form, why resort to converting it to a NameValueCollection?!
    Complex providers may need far more configuration that can't  be expressed with attributes in the element. This is a serious issue that may limit the usefulness of the pattern.

While the first two are a matter of taste in the end, the last one should be fixed promptly. I didn't hear any voice complaining, however. Am I the only one envisioning complex providers with the need to configure themselves with hierarchical XML information? It's all too common everywhere!
You want a a concrete example? Here it goes:

What if I develop a provider that implements automatic DB schema installation and migration? My super provider could allow the full DB schema to be specified in the configuration itself:

<configuration> <system.web> <roleManager defaultProvider="MySuperSqlProvider" ...> <providers> <add name="MySuperSqlProvider" type="Kzu.MySuperSqlProvider, Kzu" description="Auto-deploy provider"> <schema name="MySuperProvider"> <table name="TheTable"> <colum name="ID" type="nvarchar" size="255" /> ...other columns... </table> ...other tables... </database> </add> </providers> </roleManager> </system.web> </configuration>

The provider can detect the presence of the schema and create it automatically if necessary. I could even go as far as saying that it could even define through configuration the way to migrate a schema if it's incompatible, or whatever.

Another one: maybe my provider uses a webservice. I may need to pass complex information to the provider, such as credentials, proxy information, SOAP message skeletons, or whatever. None of this is possible with a NameValueCollection.

8 Comments

  • Exactly, there's no Provider type in the current bits, therefore, it SHOULD be used to name the abstract base class.

    But, like I said, the naming thing is a matter of taste at most, and it's the smallest of the problems. Configuration is far more important.

  • Keep in mind that the point of Rob's article was to show how you can use the provider pattern in .NET 1.1. Generics aren't available in .NET 1.1, therefore he used a strongly typed collection.

  • Well, generics aren't used in the Whidbey version either. That's what worries me.

  • Generics aren't being used in the 2.0 version because MS still needs to have collections for languages that don't implement Generics yet. Further, the provider architecture was written before the Generics features were checked into the source tree.

  • Well, thanks for such an informative inside-look at the Microsoft source tree (whichever way you use to stay in-sync with it to that level of detail...).

    Generics and providers are there since the PDC bits. Changing from a loosely typed collection to a generics based one is the job of 1 day. Don't tell me that's the reason, I just don't buy it. We're near beta1 and they're still generic collections.

    As for languages that don't implement generics, I wonder if having a generic method AND the non-generic one would be enough...

    Next, I said &quot;While the first two are a matter of taste in the end, the last one should be fixed promptly'. The first two include the generics stuff.

    It's clear to me that it's of little importance, unlike the last one on the provider interface. That's the one that worries me. The rest is syntactic sugar.

  • Currently Microsoft have a development guideline that all publicly available classes and methods should be CLS compliant. Since generics are not CLS compliant (yet). Microsoft made the decision to not provide dual generic/non-generic classes and methods in the ASP.NET APIs. Since generics will probably become CLS compliant in Orcas, they will be re-visiting all of the provider APIs for generics in Orcas.

  • I don't believe that the ASP team has violated Brad's class naming guidelines... please examine his post a little closer. If Provider is a type, then ProviderBase is necessary to disambiguate.

  • Well, it just so happens that there's no Provider type. It's just the namespace System.Configuration.Provider. And it's a namespace with only 3 classes: ProviderBase, ProviderCollection and NotSupportedByProviderException. I wonder why is a separate namespace needed at all for them, specially since the word Provider is already present in the three of them.

    IMO, it would be better to just have the three classes (renaming ProviderBase to just Provider) directly on System.Configuration and that's it.

Comments have been disabled for this content.