C# Software Architecture: Delegates

There are times, and I hope more often than not, that you have to write code which will be reused for multiple projects. Writing code in a reusable style is probably the most useful approach which leads to faster project development and reduced maintenance time. As your “reusable” code becomes more commonly implemented by you and your colleagues, it will change, morph and hopefully become faster and more reliable. There are multiple ways to approach reusable code; the most common ways are to create a library or an architecture. Both approaches are very powerful and almost always used together. In today’s blog post I am going to approach reusable code from a library stand point and then discuss how delegates make architectures powerful.

What is an architecture? To be more clear, in the case that the term is a bit vague, I am going to take a moment to explain what I define an “Architecture” as. An architecture is a set of libraries and classes which force the programmer to conform to a specific structure and implementation. Hence the word “architecture”, which is unlike a  “library” that supports your own code structure. For instance in XNA, your scene must inherit from the Game class. This is unlike a library which leaves the implementation up to you and acts more of a “tool kit” to your own code structure.

Ok good, now that I have all boring terminology clarifications out of the way, I can get into the fun stuff! In C# and many other languages, we are provided with a very powerful tool called the Delegate. This is included in some form in almost any language that supports reflection, though the implementation might not be so straight forward (has to be done through an interface in Java). If I was to describe this off the top of my head, a Delegate is a type which holds the definition (more accurately the signature) of a function. As a result it is used to hold a reference to a function which allows you to invoke it as a variable. To refer to the MSDN documentation:

delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value[…]

This means that using this, I can pass in a function as a variable into another function. For instance, if I have a function that computes the rotation of a car wheel in relation to speed, we are met with a problem; do we use miles or kilometers? A customer in the US would need this to be done in miles while a customer in Russia will need this to be done in kilometers. You are now faced with a software architecture problem; do you simply create two functions for each case? What happens if for instance, if someone needs to take my code three years from now and implement some third type of measurement? As stupidly simple as this architecture problem maybe, there are issues very similar to this that require this kind of attention. You don’t want someone ripping your code apart in the future because that fragments code versions. You don’t want every implementer to make changes to your “reusable” stuff because that well, defeats the purpose of writing reusable code.

Lets pick up the pace a little bit with some examples. I’m going to take the example I just threw at you above and show you how to implement it. Lets define the delegate first:


/// <summary>
 /// Used to compute the distance traveled per rotation of the wheel
 /// </summary>
 /// <param name="wheelSize">Size of the wheel is in inches, it is the length of one rotation</param>
 /// <returns></returns>
delegate float ComputeRotation(float wheelSize);

So in the above code, we define the “blueprint” for the function that is used in our architecture for computing the distance per rotation of the wheel. The architecture will feed the size of the wheel into your function and let you decide what the proportion is to your mile or kilometer. I made it easier where our architecture already knows the length of the wheel rather than the radius; lets not do too much math here! So now that we have the “model” for our function we can now create it. In using the delegate, we “agree” that our function will take a float for the wheel size and return a float. Everything else is up to us. Lets define a new function!


protected float computeInKM(float wheelSize)
 {
float wheelSizeInCM = wheelSize * 2.54f; //Lets convert this to cm to make it easier
return wheelSizeInCM / 100; //Return the KM value since we are still in CM
 }

I could of just returned the entire thing in the return statement but I decided break it down a little bit. So, this is our function for computing the distance a wheel has traveled in a single rotation in kilometers. Our architecture, which needs to compute the distance a car has traveled based on how many times the wheel has rotated (I would assume this is how cars do this computation). We are all set to provide our architecture a computing function! To link the code all together, since right now we just have a function and a delegate that do nothing, we can do the following:


namespace blogExamples
{
      /// <summary>
      /// Used to compute the distance traveled per rotation of the wheel
      /// </summary>
      /// <param name="wheelSize">Size of the wheel is in inches, it is the length of one rotation</param>
      /// <returns></returns>
      delegate float ComputeRotation(float wheelSize);
      class delegateExample
      {
           protected ComputeRotation rotationCompFunction;
           public delegateExample()
           {
                rotationCompFunction = computeInKM;
           }

           protected float computeInKM(float wheelSize)
           {
                float wheelSizeInCM = wheelSize * 2.54f; //Lets convert this to cm to make it easier
                return wheelSizeInCM / 100; //Return the KM value since we are still in CM
           }
     }
}

Apologies for the ever growing code. The above code you can just copy paste; it is a stand alone class that we can just create a new instance of for the sake of the example. So far this does not resemble anything “architecture” like, but it works very well for an example. I have taken the delegate out of the class and into the name space. I have found in my own experience this makes more sense since you want to reuse your delegates! Now we have literally in a way a “pointer” to our function. Now the class knows which function it can use to compute distance, we are all setup and ready to go! I am going to morph this class a few times to show you how this would look like if I just wrote the code inline in the class and then I am going to take the computeInKM out of the class, put it into my main and show you, just how powerful delegates are!  Lets get the ball rolling!


namespace blogExamples
{
       /// <summary>
       /// Used to compute the distance traveled per rotation of the wheel
       /// </summary>
       /// <param name="wheelSize">Size of the wheel is in inches, it is the length of one rotation</param>
       /// <returns></returns>
       delegate float ComputeRotation(float wheelSize);
       class delegateExample
       {
            const float sizeOfWheel = 20; //I have no idea what an actual length of a wheel is
            protected ComputeRotation rotationCompFunction; //Lets create a delegate reference
            public delegateExample()
            {
                 rotationCompFunction = computeInKM;
            }

            protected float computeInKM(float wheelSize)
            {
                 float wheelSizeInCM = wheelSize * 2.54f; //Lets convert this to cm to make it easier
                 return wheelSizeInCM / 1000; //Return the KM value since we are still in CM
            }

            public float totalDistanceTraveled(float wheelRotations)
            {
                  return wheelRotations * rotationCompFunction(sizeOfWheel);
        }
 }

This is now our class that uses an internal delegate to make our computation in KM. To call it from your main, you can simply:


class Program
 {
      static void Main(string[] args)
      {
           delegateExample exampleClass = new delegateExample();
           Console.WriteLine(exampleClass.totalDistanceTraveled(100));
           Console.ReadLine();//Stop it from closing
      }
 }

Seems simple right? But why in the world would we use a delegate? Can’t we just call the KM function and even better, just pass in what computation we want into the constructor as an enum? Well those are the better options if we setup our code this way; a delegate here, nested inside a class, inaccessible from the outside is useless. But I had to start demonstrating the idea somehow right? Now let me show you the REAL potential of a delegate. I am going to take function we loaded into our delegate OUT of the class and put it into our main “program” class. Then I am going to have my class obtain the function through it constructor. Get ready! Here we go!


namespace blogExamples
{
         /// <summary>
         /// Used to compute the distance traveled per rotation of the wheel
         /// </summary>
         /// <param name="wheelSize">Size of the wheel is in inches, it is the length of one rotation</param>
         /// <returns></returns>
         delegate float ComputeRotation(float wheelSize);
         class delegateExample
         {
               const float sizeOfWheel = 20; //I have no idea what an actual length of a wheel is
               protected ComputeRotation rotationCompFunction; //Lets create a delegate reference
               public delegateExample(ComputeRotation computationDelegate)
               {
                     rotationCompFunction = computationDelegate;
               }

               public float totalDistanceTraveled(float wheelRotations)
               {
                     return wheelRotations * rotationCompFunction(sizeOfWheel);
        }
    }
}

To the programmers reading this who are not as experienced ill run through the changes really quick (yea, I had to read stuff like this starting out too, I know the AND THEN MAGIC HAPPENS is really frustrating!). I took my function, the computeInKM and moved it (look at the up coming code, I put it into the Program class). I then modified the constructor to take a ComputeRotation delegate and assigned it to the default computation function (rotationCompFunction) variable. Lets take a look at the “Program” class now:


namespace blogExamples
{
       class Program
       {
             static void Main(string[] args)
             {
                  delegateExample exampleClass = new delegateExample(new ComputeRotation(computeInKM));
                  Console.WriteLine(exampleClass.totalDistanceTraveled(100));
                  Console.ReadLine();//Stop it from closing
             }
             protected static float computeInKM(float wheelSize)
             {
                  float wheelSizeInCM = wheelSize * 2.54f; //Lets convert this to cm to make it easier
                  return wheelSizeInCM / 1000; //Return the KM value since we are still in CM
             }
      }
}

As you can see now, my function is now in a completely difference scope and yet it is being used to compute! I hope at this point you are a starting to see the potential of this approach! In order to pass in a delegate, you you need to create a new instance of one and assign your function into it, hens why I am passing in:


       new ComputeRotation(computeInKM)

into the constructor. Exciting isn’t it?

What in the world does this have to do with software architecture?

In another blog post, I will describe how to take this concept even further with events, but delegates are still extremely important for software architecture. The examples I used represent a library more than an architecture. However, lets discuss an example (I promise, no more code!)

The big downside of using some kind of architecture is that you can’t do much about the internal workings of the architecture. This means a few things:

  • Architectures that are not flexible end up being less reusable and more specific to a certain project
  • When you want to do something your own way, well… you can’t change the internal working

Lets go back to our distance measuring example. Cars models are often built for more than one country and very often different countries have different standards. I am not an expert at car regulations but I can say for sure that in the US they use miles and in Russia they use kilometers. This creates an issue for software developers (now that we are in the modern age) because the entire digital dashboard, including GPS is affected by this. A mile is over one and a half times the distance of a kilometer and when I am in Russia, I really wouldn’t like that my GPS computes everything wrong. But this is a serious problem for developers because well, what if I wrote the architecture for the car displays ONLY in miles (well, lets assume its in C# which it most definitely isn’t)? Then that software has to be redone or they have to pay me oodles of money (Yay?) to go in and create SEPARATE version for them that does everything in kilometers. As rich as I want to be, it means I didn’t do my job right and I did not allow them to just go in and with a few lines of code change the behavior of my amazing architecture. So what do I do?

A little detour into architecture approaches; an architecture often requires that you create a class that inherits one that the engine provides (usually you can choose from multiple on what your creating). This way my architecture can take care of a lot of functionality and setup that you don’t have to. Back to the implantation world;  this means that I can define a function looped through a delegate which you can then overwrite with your own function! This is also often done through overriding, but in our case we might have a user that wants to switch between measurement types; simply changing our the delegate function will do the trick where overriding would make this more difficult.

Closing Notes

One question that you might ask, is why not simply at least for this example convert miles/km directly? Why do I need this complex setup? Well, the purpose of this article is not how to handle converting measurements, but why delegates are powerful tools. But this question raises a good point, why not simply compute in one measuring system and convert into another? Wouldn’t that be easier? Well, it’s more straight forward, but from an software standpoint it is very wasteful. On a standard computer, we really don’t care about those things because it takes so little processing power. In a car this is a big deal because well, the tech inside is simply not very powerful. As you design more and more advanced systems for a car, you have to keep in mind that your software is constantly running the calculations of distance traveled, current speed and even how far is the car behind you. The faster the refresh rate the more reliable the reading are and in many cases, the safer your car is. If someone is getting too close to me from behind, it might be too late to notify me at a refresh rate of 3 times a second that “Hey, that car is dangerously close”. This means that you really need to tighten your computation to make it finish one loop through and start the next. What do we do about this? Simple, don’t do redundant computation if you can do it right away.

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