22 June 2015

[Arhived] Timeouts and TimeSpans: Huh? We're waiting how long?

Update 4 Feb 2016 There is a more up to date version of this article here

You don't have to work for a long time in software development to come across code similar to the following:

void DoSomething()
{
   var data = GetDataWithTimeout(5000);
   //... continued
}
Data GetDataWithTimeout(int timeout)
{
   //...
   Thread.Sleep(timeout);
   //...
}

There is one major issue with this code that specifically relates to its readability and consequently its long term maintainability:

  1. The unit of the timeout value is unclear at the point of use!

This has caused me to loose countless minutes to drilling to extreme depths to figure out exactly what unit is being implied on the timeout.

How to avoid this loss of productivity and immediate code rot?

Here are two simple alternatives that can help you avoid making this kind of a mistake and significantly improve your and your colleagues life's in the long run.

1. Explicitly mentioning the timeout unit

By simply tagging the relative function and parameter names with the unit a lot of uncertainty has been removed. If changing the function name is impossible due to legacy constraints, just changing the parameter name will help immensely and can usually be done without sacrificing any backwards compatibility.

void DoSomething()
{
   var data = GetDataWithTimeoutMSec(5000);
   //... continued
}
Data GetDataWithTimeoutMSec(int timeoutInMilliseconds)
{
   //...
   Thread.Sleep(timeoutInMilliseconds);
   //...
}


2. Relying on TimeSpan and helpful extension methods

In the case where you're able to modify the parameter type no renaming is necessary as the code can be modified to use the System.TimeSpan struct instead. Actually I would advise against also using the renaming tactic if this approach is used as combining them will introduce more ambiguity than before (calling GetDataWithTimeoutMsec(TimeSpan.FromMinutes(10)) would be confusing.

void DoSomething()
{
   var data = GetDataWithTimeout(5000.MilliSeconds());
   //... continued

   // Other examples
   var data = GetDataWithTimeout(20.Seconds());
   var data = GetDataWithTimeout(3.Minutes());
}
Data GetDataWithTimeout(TimeSpan timeout)
{
   //...
   Thread.Sleep(timeout);
   //...
}

The skeleton code for the Seconds()/Minutes() extension methods can be downloaded from my OneDrive here.

This entry is also available on LinkedIn:
https://www.linkedin.com/pulse/timeouts-c-timespans-huh-were-waiting-how-long-sverrir-sigmundarson

2 Feb 2016 An updated version of this entry can now be found on Medium:
https://medium.com/@sverrirs/timeouts-and-timespans-ca05ae5c2d15#.usxppi1h8