Should you push or pull data?

The other day, and interesting discussion came up with co-worker Jamie. The question is within a given system, is it better to push or pull data. Put another way, should I poll and go get the data I need – or should I ask objects to report back to me when they have new data for me.

Depending on the situation, they both have merit – but usually, “push” tends to be the answer. But, I wanted to explore that further. So, I spent a little time proving out an example. First, I created an interface for monitoring “something”:

public interface IMonitor
{
event EventHandler MonitoredEventOccurred;
}

Polling:
So next, I created a polling version of a class that monitors the weather.

public class PollableWeatherMonitor : IMonitor
{
public String GetWeather(String postalCode)
{
String result = WeatherProvider.GetWeatherFromInternetService(postalCode);

if (MonitoredEventOccurred != null)
MonitoredEventOccurred(this, new EventArgs());

return result;
}

public event EventHandler MonitoredEventOccurred;
}

The thinking here is that we leave the “responsibility” of retrieving the data to the consumer. In other words, this just provides a mechanism which allows consumer to manually poll.

Pushing:
I then created an event-driven class that gets weather conditions. This is markedly more complex, as it has more “responsibility”:

public class EventDrivenWeatherMonitor : IMonitor
{
public EventDrivenWeatherMonitor()
{
monitorTimer.Elapsed += monitorTimer_Elapsed;
}

void monitorTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!cancel && !isRunning)
{
try
{
isRunning = true;
this.LatestWeather = GetWeather(PostalCode);
}
finally
{
isRunning = false;
}
}
}

public TimeSpan PollInterval
{
get { return new TimeSpan(((Int32)monitorTimer.Interval / 1000)); }
set { monitorTimer.Interval = value.TotalMilliseconds; }
}

public void StartMonitoring()
{
cancel = false;
monitorTimer.Start();
}

public void StopMonitoring()
{
cancel = true;
monitorTimer.Stop();
}

public String LatestWeather { get; set; }
public String PostalCode { get; set; }
public event EventHandler MonitoredEventOccurred;

protected Boolean cancel = true;
protected Boolean isRunning = false;
protected Timer monitorTimer = new Timer();

protected String GetWeather(String postalCode)
{
String result = WeatherProvider.GetWeatherFromInternetService(postalCode);

if (MonitoredEventOccurred != null)
MonitoredEventOccurred(this, new EventArgs());

return result;
}

}

 

At this point, it seemed that the polling approach might be the way to go – since it is less code. However, when I started to figure out what the consumer would look like, I realized I would need a LOT more code on any consumer that used the polling technique.

Put another way, there is a fixed amount of work/logic to be done – the question is, where do you want to do it? Whose “responsibility” is it to poll for new data and report to subscribers that there is an update?

I argue that it is the provider of the data.

When we use the polling approach, every consumer of that class must write their own logic for starting, stopping (pausing?) monitoring. Whereas the push approach leaves all of that responsibility to the provider class. All we need to do is call .StartMonitoring(), .StopMonitoring() – and wait for the event to fire.

public MonitorManager()
{
EventDrivenWeatherMonitor monitor2 = new EventDrivenWeatherMonitor();
monitor2.PollInterval = new TimeSpan(0, 15, 0); // Run every :15 minutes
monitor2.PostalCode = "06103";
monitor2.MonitoredEventOccurred += monitor_MonitoredEventOccurred;
monitor2.StartMonitoring();
}

void monitor_MonitoredEventOccurred(object sender, EventArgs e)
{
throw new NotImplementedException();
}

Although every situation is different, the conclusion I come to is that from Single Responsibility Principle sort of way, and from a loose-coupling sort of way – in a case like this, you should probably have the providers of data “push” data at their discretion rather than the consumers doing all that heavy-lifting.

Posted in Best-practices, Uncategorized

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

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 5 other followers

%d bloggers like this: