Good morning its Monday this is your calendar speaking: you’re not going to code this week |
There was a time where my calendar was mocking me every monday morning, and gave me a silent “told you so” every friday. I´m a software developer. I love to write code, to design architectures, implement complicated algorithms and I refused to give up my passion to a schedule dictated by my environment.
So I started to fight. I pulled out every task organising tool that promised to increase my focus. “Getting things done” and “Pomodoro” are just two to name. I started to decline meetings, combine meetings and organise meetings – so they are all aligned and no longer fragmented.
And it worked!
Good morning its Monday this is your calendar speaking: you can code undistracted on two days |
… for some weeks. After introducing a new technique my calendar needed some weeks to recover from the loss. In the end reality always hit and I was back to square one.
If you cant beat them – join them
Adding up the meeting times in the first illustrated work week results in roughly 10 hours. In a 40-hour week there should be a productive coding time of 30 hours. Which sounds good. Due to the fragmentation of my meetings, my available time is also fragmented and I cannot use a larger part of this time efficiently. It usually takes me too long to get into the right mind set to code, and build up the mental stack. If I have a half an hour gap – I wont start coding at all. In a one hour area I might start some smaller issues – but definitely not thinking about a new feature.
Most of the time management techniques focus on prevailing and prolong your focus time. This means constantly fighting reality. Instead I decided to accept how my week is structured and to reduce the time that it takes me to start and stop a coding task.
Ever had a meeting about “how to reduce the meetings”?
Run for the hills – a case study
Lets take the following user Story as an example:
“As a player I would like to move my units on the battlefield by tapping at the target position on screen”
For this I need to implement a pathfinding algorithm. In this case I choose Dijkstra
Implementing Pathfinding
We can start diving into the Problem by remembering the basic of the algorithm. So lets take a minute to recap:
function Dijkstra(Graph, source): create vertex set Q for each vertex v in Graph: dist[v] ← INFINITY prev[v] ← UNDEFINED add v to Q dist[source] ← 0 while Q is not empty: u ← vertex in Q with min dist[u] remove u from Q for each neighbor v of u: // only v that are still in Q alt ← dist[u] + length(u, v)
… and while you’re thinking about it – how do you feel about me disturbing you ?
if alt < dist[v]: dist[v] ← alt prev[v] ← u return dist[], prev[]
Yes. Thats how I felt when I was interrupted while processing the logic to permeate and understand the topic. Which Illustrates another challenge that is not visible in my calendar but still part of my daily business.
Even smaller implementation task demand quite a big mental stack to understand an implementation. If this concentration is interrupted the mental work is gone and needs to be done again.
You are not alone
Given all above: The mental memory, the concentration loss, the mental blockage by upcoming meetings etc. Is not a single phenomena. It’s actually a well studied field. The key numbers are not really surprising and mirror my experience.
- An average programmer has not more than one uninterrupted 2h session per day
- It takes 10-15 minutes in average before the first line is written again
- Time can be reduced when programmer is allowed to properly close the current task
- To properly change from a high mental memory state to a free mental memory takes 7 minutes in average
Programmer Interrupt – Ninelabs research with 10.000 coding sessions of 500 developers.
You don’t programm yourself ? – this comic will help you to understand the issue.
Produce valuable production code in a 5 minute meeting break
With all the numbers and the current understanding – this sounds like an impossible task.
So let’s go one step back and start over.
How much time will you need for each of the following tasks. If done in order, and with your preferred language and toolset. ( in the expand you will find my solution and times )
- Create a data structure (Node) that can hold a string, a float, and a bool : 25 sec
- Create a data structure for the connections: 40 sec
- Compare two Node elements by comparing the float : 156 sec
- Create a Map that can store Node objects: 23 sec
- Loop through the List of Nodes and return the one with the lowest float: 112 sec
All of those tasks are easiest day-to-day programmer work. You can do them while sleeping – all in less than two minutes. So this demonstrates that there are tasks that you can write without any trouble in less than 5 minutes. Those tasks need to be my goal.
The crucial issue is our daily tasks are not matching those simple code demonstrations. The first step in my new workflow is therefore to breakdown the task in as many tiny bits as possible.
his is how the list looks for the above task of path finding. The start is actually the tasks I showed above:
- Create a data structure (named Node) that can hold a string:name, a float:distanceToStart, and a bool: visited
- Create a list of that data structure
- Compare two Node elements by comparing the distanceToStart
- Create a Map that can store Node objects
- Loop through the List of Nodes and return the one with the lowest float
- … to be continued
The Plan
I continued to create the list and end up with roughly 18 steps that I need to do. The further steps are not relevant for this example.
This list is a step by step guide to implement Dijkstra. Each step should take in average 2 minutes. No task should take longer than 5. It’s 18 steps so we could say this can be implemented in roughly 40 minutes to an hour.
1 hour is a big chunk – but I no longer need it as one piece. It would be actually enough to have three 15 minute breaks between meetings to get this thing done. So on a busy meeting day with only three small gaps in between I could implement this. All I need is this checklist.
It took me roughly an hour to compile that list – and that hour had to be undistracted. As soon as I have my list all is good – but until then – I still have the same problem as above.
Another issue of this list is that I can’t see whether my implementation is actually working. So I have to trust my list 100% and only see if all is working in the last three steps. If I made one tiny mistake – I need to debug the whole code – which means a lengthy concentration session.
YOLO – everything is better without a plan
So lets recap:
- We can code small tasks in way less then 5 minutes
- We can plan and break down our user stories in those tiny bits
- Planning needs concentration and is therefore bad
- We don’t know if our bits work together until the end – this is bad
Let’s remove everything that still blocks us. What if we just pretend that there is no other issue than the first one of our list.
- Create a data structure (named Node) that can hold a string:name, a float:distanceToStart, and a bool: visited
That list was created in some seconds. How ? I looked at the animated gif on wikipedia and noticed:
- There is circles → object → needs a name
- they have numbers → float
- they get marked red on some point → bool
Thats all. Without understanding how the algorithm works – just did the first step.
Now I go yolo – don’t care about the rest and just implement that knowledge. Since this is the last step on my to-do list I add some log outputs and a test function that creates different nodes – just to see if all runs fine.
Task achieved in less than 5 minutes – without any preparation overhead.
Now I can go to the next meeting – and when I will come back I will do the same loop again:
- Check next thing I need
- Implement that
- Write some code to use the new function
- Check that all works
Im back from my meeting.
- Open up the wiki page, remember that I already have created the circles – next thing that jumps to eye is the lines – which results in the tasks description:
- Create a data structure connection that contains a float:distance and a Node:target
- So I started implementing
The holy grail! Found it!
Now I used that technique. Jump to a meeting, every break open my laptop and implement the next step and it felt really good. Until I started to slow down somewhere around the 5th step. That step took me longer than 5 minutes. Why ?
- Loop through the List of Nodes and return the one with the lowest float
Seems like the same since as all the other ones – when I did this in Isolation above it took me less then 30 seconds. What changed ?
With every step I finished – I needed to recap what is already there – so my mental memory that I needed to fill looked like that:
- I have circles
- I have connections
- I have a list of circles
- I can compare two circles
- I have a Map that stores the list of circles
- → in the gif the numbers gets added and always the lowest is taken next
- this means I need to be able to find the node with lowest distance
- Loop through the List of Nodes and return the one with the lowest float
Remember the first 5 steps in my head took concentration and time. I noticed that every time I finished implementing – I had this stack in my head – so why not write down the next step before I leave to the next meeting – so when I come back I directly find an instruction on my desk.
The Ninelabs study made an interesting discovery: Some programmers added intentional compiler errors when they where interrupted.
So I literally write the next action plain text into the code. Next time I open my project I just tap on the compiler error and have the next task right on my screen. The error works like a bookmark for me.
This helped a lot to reduce the time to get started.
There is always one more devil to fight
Again I was able to run for some more points – but after a while I again slowed down. Reason: testing all the steps that I had before, by looking at all the logs in the console took more and more time.
Shouldn´t I be able to automate that ? Write code – that reads the console – to see if all logs are in there?
Something like:
task1.Print(); if(readConsole.text.Contains( "Node1") success = true; if(!success ) printError("something is wrong")
This way I only need to look out for the error.
So here is my final workflow:
- Implement first obvious step of the Problem
- Add some extra code that enables me to validate the function ( like a Console.Log() )
- Use some framework to check output automatically
- Write down the next obvious task and produce compiler error
- Take a break – or a meeting – or what ever kind of distraction
Resume Task:
- Jump to compiler error
- read the described action
- Start at point 1
Congratulations! You invented the wheel!
As you might have already noticed – all of this is not new. The workflow described in the end is exactly the one describe in the technique:
Test Driven Development!
TDD is a workflow technique.
While I had discovered TDD before, I used it for the obvious testing purpose, and sometimes as a design technique. But until this point I never considered it a workflow technique. Turns out that this is the most useful aspect of it.
Summary
In this article I showed step by step which aspects can help to reduce the time it takes to start and stop a task. In the end well documented, small tasks that are automatically evaluated did the trick and allow me to be productive in very short work packages. By using Test Driven Development as a workflow technique, I’m able to achieve those well documented, self-evaluating tasks, while also getting the other benefits of TDD basically for free.
Of course I still encounter legacy code, that needs bug fixing or refactoring, for which I still need long focus times and a free schedule. There are still big architecture decisions for new systems to make, where I would love to work on top of a lonely mountain. So this technique does not solve all problems I encounter day by day, but it allows me to fit the tasks that can be solved with this workflow in the small open slots, and keep the focus time for the task that actually need it.
InnoGames is hiring! Check out open positions and join our awesome international team in Hamburg at the certified Great Place to Work®.