Less code matters: don’t repeat yourself

June 27, 2011 at 9:24 am | Posted in C#, GIMP, Programming, Uncategorized | Leave a comment

I got quite a few reactions on my previous blog post both positive and negative. The message of the negative comments was mostly that short code shouldn’t be a goal since it tends to result in unmaintainable code. Next some people accused me of writing ‘clever code’ like using lambda functions which they reasoned are not going to be understood by those who will maintain my code. Despite of the tone of some of these comments, they are all very interesting and surely hold some value. At least they gave me a couple of new ideas for future blogs.

In this post I’ll show how I removed another 4 lines from the GIMP# AverageBlur plug-in. The following lines of code have been bothering me for a long time but I never took the time for fixing them:

using System;

namespace Gimp.AverageBlur
{
  class AverageBlur : Plugin
  {
    static void Main(string[] args)
    {
      new AverageBlur(args);
    }

    AverageBlur(string[] args) : base(args, "AverageBlur")
    {
    }

    // Remaining code omitted
}

There are 2 things I didn’t like about this code:

  1. The Main function creates an object which is apparently unused. The reason is that in the constructor all kind of magic happens, include a call to gimp_main which starts the actual GIMP plug-in. This is hard to understand: constructors should be straightforward. Just create the object and make sure it is in a defined state. Nothing more than that.
  2. Every GIMP# plug-in is derived from the Plugin class but still seems to need it’s own constructor. The only reason for this is that I have to parse a couple of parameters like the arguments (args) and the package name that is used for translation. However this package name is always the same as the plug-in name.

While it is easy to get rid of the first disadvantage by introducing an explicit function call with the object as parameter, that would still leave me with a constructor for every plug-in I write. However, that was my first attempt to clean up this code:

using System;

namespace Gimp.AverageBlur
{
  class AverageBlur : Plugin
  {
    static void Main(string[] args)
    {
      // Do all magic stuff in GimpMain instead of in constructor
      GimpMain(new AverageBlur(args));
    }

    AverageBlur(string[] args) : base(args, "AverageBlur")
    {
    }

    // Remaining code omitted
}

Now if I just remove the parameters from the constructor and pass them to GimpMain I can use the default constructor so I don’t have to define it anymore:

using System;

namespace Gimp.AverageBlur
{
  class AverageBlur : Plugin
  {
    static void Main(string[] args)
    {
      // Do all magic stuff in GimpMain instead of in the constructor
      GimpMain(new AverageBlur(), args, "AverageBlur");
    }

    // Remaining code omitted
}

We just removed 4 lines of code while at the same time improving readability. We are left with one single line that calls GimpMain where all the magic happens. Still this line looks a bit like boilerplate code since it will be exactly the same for every plug-in. The final code I used looks like:

using System;

namespace Gimp.AverageBlur
{
  class AverageBlur : Plugin
  {
    static void Main(string[] args)
    {
      // Do all magic stuff in GimpMain instead of in the constructor
      GimpMain<AverageBlur>(args);
    }

    // Remaining code omitted
}

The Plugin base class instantiates the object as follows:


abstract public class Plugin
{
   protected static void GimpMain(string[] args) where T : Plugin, new()
   {
      var plugin = new T();
      Catalog.Init(typeof(T).Name, Gimp.LocaleDirectory);

      // Remaining code omitted
   }
}

I introduced a generic method. The type parameter T has the constraints that it should be derived from the Plugin class and that it should have a default constructor. In line 5 an object of this type is created. Line 6 now gets the class name (typeof(T).Name) which I use as catalog name for the locale.

Over time the size history for the AverageBlur plug-in now looks like this:

Current code size is now 54 % of what it once was, down from 60 % in the previous revision.

Some people might wonder if this code isn’t ‘too clever’. Generic methods in C# is not something every programmer might be 100 % comfortable with. In a next blog post I am going to write about clever code and try to quantify this a bit more. Until then, enjoy reading this post and I’m looking forward to any comments and/or improvements!

Leave a Comment »

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.
Entries and comments feeds.

%d bloggers like this: