This post originated from an RSS feed registered with .NET Buzz
by Udi Dahan.
Original Post: NSynch goes Asynch
Feed Title: Udi Dahan - The Software Simplist
Feed URL: http://feeds.feedburner.com/UdiDahan-TheSoftwareSimplist
Feed Description: I am a software simplist. I make this beast of architecting, analysing, designing, developing, testing, managing, deploying software systems simple.
This blog is about how I do it.
As you can tell, my quest for the somewhat related grab-your-attention title continues. Anyway, as the title suggests, I'm going async today. What I mean is how to expose functionality in an asynchronous manner. I'm not talking about the usual method often found where the library user makes the decision to make the call in an asynchronous manner and writes all the code to do so. Rather, here the library author does all this work instead.
"But, wait a minute ! Isn't it the library user's decision how to make the call ?" I hear this quite a lot whenever I propose a different way of working. Most of the time it comes from the library authors themselves. I'm not sure if it's just a ploy to get out of doing the extra work or if they really believe it.
So, let's get into the evangalizing bit first, since if your not convinced, you won't really care about the technical details of how its done.
Most library users ( other developers ) are, on average, less skilled than those that write the libraries. Wait a minute, don't shoot me just yet. Think about it. I'm the first to admit that the authors of the .Net framework are more skilled in .Net development than I. The same goes for databases like SQL Server. These are all, in essence, just libraries as far as I'm concerned - some external code that I can use according to the interface exposed to me.
So, if the author of a library exposes as a part of the interface asynchronous methods as well as synchronous ones, I would start thinking ( and probably reading the docs for ) when I should use which method. If the asynch methods weren't already there, I probably wouldn't have thought about the possiblity/need to make a given synch call in an asynch manner. I know a fair amount of developers that aren't familiar with how to do this anyway. So, if the library author provides the asynch capability built-in, all the developers who don't know how to make synch calls in an asynch manner would benefit.
Lets look at an example. We have a library with a given API:
Lib.Functionality.DoSomething(string s)
This is a plain synch call. Should I want to call this in an asynch manner I would have to do something like this:
namespace MyNamespace
{
public delegate void DoSomethingAsynchDelegate(string s);
public class MyClass
{
public MyClass() {}
public void DoSomething() {
string s = "123";
DoSomethingAsynchDelegate del = new DoSomethingAsynchDelegate(Lib.DoSomething);
del.BeginInvoke(s,null,null);
}
}
}
*
I forgot to mention that this works best for one-way calls. Calls where you require to be notified when processing is completed can be done similarly, but typically involve more complex processing with state involved.
I'll just be showing one-way calls here. In a future post I'll show how to do this with callbacks. The thing is, while it is quite clear that one-way asynch calls belong in the library, and including callbacks from the library is technically easy, the scenarios where callbacks are needed usually preclude the notion of the library being in charge. I'll discuss this further in the future.
Anyway, the above code could easily be moved into the library itself and exposed as follows:
namespace Lib
{
internal delegate void DoSomethingAsynchDelegate(string s);
public class Functionality
{
public void DoSomething(string s)
{
// do something with s
}
public void AsynchDoSomething(string s)
{
DoSomethingAsynchDelegate del = new DoSomethingAsynchDelegate(DoSomething);
del.BeginInvoke(s,null,null);
}
}
}
In this way, the library user can call Lib.Functionality.AsynchDoSomething without really knowing what code needs to be written. Note that the delegate is internal in this case. There is no reason that anyone outside the library concern themselves with the technicalities of the call ( in the one-way scenario ).
To reiterate, the goal of any library is to make its use as easy as possible. Moving code allowing asynchronous (oneway) calls into the library does just that. More importantly, the library user is more certain that the library can/should be used in this manner.
To tell you the truth, when I write the first section of code to make calls to a library in an asynchronous manner, I'm not really sure that I should be doing so, or if I'll somehow screw up how the library works internally. When the library author presents me the asynch call on a silver platter, I'm quite positive that I won't be introducing subtle bugs by my shenanigans ( however that word is spelled ).
Any thoughts about other things that belong in libraries but aren't there, let me know ! I'm always looking for ways to ensure that code is run the way it should be, so that fewer bugs are encountered. If you think that my thinking is wrong, and that libraries should keep a bare-minimum API, convince me ! I'm always interested in hearing things from a different perspective ( I'm usually not very good at playing my own devil's advocate ). Who knows, maybe I'll convince you in the end :)