Balancing working hours toward better productivity

I’ll start by saying – I don’t know what the best balance is. Then, what can I tell?

The obvious

  1. The ratio between our working hours and productivity is not linear. We all know that, nothing new here. If we work 12 hours a day instead of 10 we won’t produce 20% more features.
  2. When we need to get more work done, we work more hours.

The almost obvious

What does our productivity looks like during the day?
image
Everybody agrees about this graph until the productivity gets closer to zero. But is possible to have negative productivity ?

Negative productivity

This is the counter intuitive part, we had encountered it so many times but it’s still hard to accept it. Starting sometime during the day, we do more harm than good – we cause more bugs, produce fragile design and less readable code. Even though our feature might work just fine, we did more harm than good – next week, when we have to extend the feature, we’ll have to understand code of an inferior standard. We’ll fight the design and most likely, we’ll fight the bugs we missed before.
From my personal experience, during the last year I found myself fighting with features for very long hours. Most of the times when I gave up and left the office, the next morning was extremely productive. I could throw away all the mess I made during the previous evening and write nice code within an hour.

Conclusion

The conclusion is very straightforward – when you’re getting to the zone of overwork, Go Home! You’re wasting your time, you’re wasting your boss’s money and you’re planting seeds in code that’ll annoy your teammates in the near future. We all know this is counter intuitive, but working shorter hours makes us more productive.

More thoughts

We have concentrated on the productivity of a single day. A bit more interesting can be to analyze a whole week. Is it possible that working one day less a week will improve our productivity? If we find this to be true, will we act and shorten our work week? If we’d shorten our work week, should we get paid less or more? On one hand we’re more productive, so we should be paid more, but on the other hand, we work less, so we should be paid less. This leads to an interesting question – are we paid for our time or for our results?
There’s a lot to think about here, but we must find first the optimal balance of working hours and days.

Worker thread using parallel tasks

Worker thread is a known pattern – there’s work to do, it needs to be done asynchronously and we want to get all the work results when it’s ready. What we’re going to see is an implementation of it as an alternative to the common implementations. This implementation will take advantage of the new parallel tasks library.
To formalize the requirements:

  • The worker queues items to process
  • The items are processed asynchronously
  • Only one item can be processed at a time
  • The items are processed in the order they were queued
  • The worker will store the processed results in the order they were processed

The worker class

public class Worker
{
private readonly IItemsProcessor itemsProcessor;
private Task lastTask;

public IList ProcessedItems { get; private set; }

public Worker(IItemsProcessor itemsProcessor)
{
this.itemsProcessor = itemsProcessor;
ProcessedItems =
new List();
InitializeNullTask();
}

private void InitializeNullTask()
{
lastTask =
new Task(() => default(TResult));
lastTask.Start();
}

public void ProcessItem(TItem item)
{
var nextTask = lastTask
.ContinueWith(task =>
{
var processItem = itemsProcessor.ProcessItem(item);
ProcessedItems.Add(processItem);
});
lastTask = nextTask;
}

public void WaitForPendingItems()
{
using (var sync = new ManualResetEvent(false))
{
lastTask.ContinueWith(task => sync.Set());
sync.WaitOne();
}
}
}

The worker creates a task for each item which needs to be processed. Each task is executed in the thread pool, the point where we ensure that the tasks are run in the correct order is the ContinueWith call. ContinueWith takes care of the order of the tasks’ execution.

The InitializeNullTask creates a task that, surprisingly, does nothing but set a head to the tasks queue. This task helps us avoid in ProcessItem to check if this is the first item to process. The first task starts with call to Start while all the others start with ContinueWith.

WaitForPendingItems also enqueues a task. This time, the task is only waiting to be executed, which means all other items were already processed. When the task starts it releases the enqueuing thread.

Usage example

In this example we’ll download a list of web pages and check print their sizes. The downloader implements the IItemsProcessor we’ve seen the worker expects.

public class WebUrlsDownloader : IItemsProcessor<string, byte[]>
{
public byte[] ProcessItem(string url)
{
using (var webClient = new WebClient())
{
return webClient.DownloadData(url);
}
}
}

And the actual usage:

public void DownloadFiles()
{
var worker = new Worker<string, byte[]>(new WebUrlsDownloader());
worker.ProcessItem(
@"http://msdn.microsoft.com/en-us/library/dd537608.aspx");
worker.ProcessItem(
@"http://msdn.microsoft.com/en-us/library/dd537609.aspx");
worker.ProcessItem(
@"http://msdn.microsoft.com/en-us/library/dd997405.aspx");
worker.WaitForPendingItems();
Console.WriteLine("Finished downloading files:");
foreach (var processedItem in worker.ProcessedItems)
{
Console.WriteLine("Downloaded file with size: {0}", processedItem.Length);
}
}

Unit testing F#

F# is a cool and exciting language. It’s much more than an academic language; it can solve many real life (coding) problems in its functional manner. As to production code, it must be covered with unit tests. I’ll show a simple example of a unit test written in C# with moq against F# code.
The code under test is a simple lottery calculator: it takes a list of participants and says how much every participant won – 5 times the number of hits. Simple, isn’t it?
Let’s take a look at the code under test, it could probably be written better, but ignore this for now 🙂

type LotteryCalculator(winningNumbers:System.Collections.Generic.IList) = 
let calculatePrize(participatingNumbers) =
let numOfHits = participatingNumbers |>
Seq.filter (
fun participatingNumber -> winningNumbers.Contains participatingNumber) |>
Set.ofSeq |>
Set.count
numOfHits *
5

member this.CalculatePrizes(participants:System.Collections.Generic.IEnumerable) =
participants
|> Seq.map (
fun participant -> (participant, calculatePrize(participant.GetTicket())))

So, we have an API method, CalculatePrizes(), which take a collection of participants, look at their tickets and returns a tuples list of participant and prize. So we have something like this: CalculatePrizes: System.Collections.Generic.IEnumerable –> seq

After dealing with some issues, which I’ll write about in a future post, I wrote this test:

[Test]
public void CalculatePrizes_RecievesTwoParticipant_MatchCorrectPrizes()
{
var firstParticipantMock = new Moq.Mock<IParticipant>();
IParticipant firstParticipant = firstParticipantMock.Object;
firstParticipantMock.Setup(fake => fake.GetTicket()).Returns(
new List<int> {1, 4, 5});

var secondParticipantMock = new Moq.Mock<IParticipant>();
IParticipant secondParticipant = secondParticipantMock.Object;
secondParticipantMock.Setup(fake => fake.GetTicket()).Returns(
new List<int> { 1, 2, 4 });

var lotteryCalculator = new LotteryCalculator(new List<int> {1, 2, 3});
var participantPrizes = lotteryCalculator.CalculatePrizes(new[] { firstParticipant, secondParticipant });

var prizes = participantPrizes.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);

Assert.That(prizes[firstParticipant], Is.EqualTo(5));
Assert.That(prizes[secondParticipant], Is.EqualTo(10));
}

It’s nice that we can keep our unit tests written in C#, it’s also important in cases where the users of the code (most likely us in another module) will use it in C# as well.