Type object code smells

I have been playing around with the Enyim Memcached client for .NET over the past few days. It has a lot of really cool functionality, but one big smell that has been bugging me. Extensibility is used through the Type class, not through dependency injection. Here is the interface for the configuration object.

public class MemcachedClientConfiguration : IMemcachedClientConfiguration
{
   public MemcachedClientConfiguration();
 
   public Type NodeLocator { get; set; }
   public Type KeyTransformer { get; set; }
   public IList<IPEndPoint> Servers { get; }
   public ISocketPoolConfiguration SocketPool { get; }
   public Type Transcoder { get; set; }
}

Note that KeyTransformer, NodeLocator, and Transcoder are extension points for the library (really cool extension points at that). What sucks is they are Type objects, not the real implementation classes. Here is an example of how you configure the NodeLocator.

config.NodeLocator = typeof(MyNodeLocator);

Try to implement the decorator pattern in a scenario like this. You can’t, because the library is in complete control of the life-cycle of the object. There are two solutions.

public class MemcachedClientConfiguration : IMemcachedClientConfiguration
{
   public MemcachedClientConfiguration();
 
   //Notice the change to an interface
   public IMemcachedNodeLocator NodeLocator { get; set; }
   public Type KeyTransformer { get; set; }
   public IList<IPEndPoint> Servers { get; }
   public ISocketPoolConfiguration SocketPool { get; }
   public Type Transcoder { get; set; }
}
 
//And then configure like follows.
config.NodeLocator = new MyNodeLocator();

But what if controlling the life-cycle is important to the library? Well, that’s why the factory pattern exists.

public class MyNodeLocatorFactory : IMemcachedNodeLocatorFactory
{
    IMemcachedNodeLocator Create();
}

So try to avoid referencing Type objects. As you can see, it smells of an inflexible design. Not to mention leaves the possibility open to runtime errors for no good reason.

Code your Documents

Every developer has heard the phrase document your code. The reason this is important is the functionality is now coupled with a description of how it works. Now a future developer can load up a single source of information and understand the functionality. But, more importantly, the odds of the documentation staying updated are higher because of this coupling. The same can’t be said for a standalone document.

Well, shouldn’t the same be true for documents, specifically those that describe some sort of process? For example, a document describing the steps to setup an IIS web server for a particular application is perfect to convert to an automated script. So, today, I started on a simple script to setup IIS compression using MSBuild.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
  <!-- Types -->
  <PropertyGroup>
    <adsutilPath>C:\inetpub\AdminScripts\adsutil.vbs</adsutilPath>
    <cscriptPath>cscript</cscriptPath>
    <StaticFilesToCompress>html htm js txt</StaticFilesToCompress>
    <DynamicFilesToCompress>aspx asp dll exe axd</DynamicFilesToCompress>
  </PropertyGroup>
 
  <Target Name="IisCompression">
 
    <Message Text="Turn on static and dynamic compression for all of IIS." Importance="high" />
    <!-- http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true -->
    <Exec Command="$(cscriptPath) $(adsutilPath) set w3svc/filters/compression/parameters/HcDoStaticCompression true" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set w3svc/filters/compression/parameters/HcDoDynamicCompression true " />
 
    <Message Text="Select files to compress for static and dyanamic compression." Importance="high" />
    <!-- http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/d52ff289-94d3-4085-bc4e-24eb4f312e0e.mspx?mfr=true -->
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/Deflate/HcFileExtensions $(StaticFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/gzip/HcFileExtensions $(StaticFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/Deflate/HcScriptFileExtensions $(DynamicFilesToCompress)" />
    <Exec Command="$(cscriptPath) $(adsutilPath) set W3SVC/Filters/Compression/gzip/HcScriptFileExtensions $(DynamicFilesToCompress)"/>
 
  </Target>
</Project>

Not only does this script automate the process, but it serves as a living document for the process. By doing this, the documented process is now coupled to the task itself.

The next step to coding processes is coding tasks that can’t be automated. For example, during a deployment, if some sort of fatal error occurs, the next task might be to call your boss and clean up your resume. Why not code a message in the deploy script to give you the list of people and phone numbers to call in case of an emergency, then load up your resume in Word? Again, the documented process is now coupled with the task itself.

Obviously, this article grows out of my dislike of documentation. I dislike it, not because it isn’t useful, but because it takes a lot of time and, in my personal experience, isn’t used very often. By integrating the documentation with the task itself, I think we gain more value from it.