We as humans are very bad at multitasking. Some think they are good at it, some think they could be if they work on it, but the reality is that we are incapable of it.
So what is multitasking? According to Wikipedia:
Multitasking is the ability to perform more than one task or activity at the same time.
For our brains it is impossible to multitask. Our brain can only work on one task at a time. So when we think we are multitasking, we are actually switching between tasks in a relatively short time, something called context switching. And context switching is a highly inefficient process. There are a lot of studies done on the subject, and they are all very conclusive: Context switching is bad for your productivity.
The time that it takes your brain to completely switch from one task to the other is time wasted. That’s why you are more efficient if you focus on one task — and one task only and avoid switching to a different task as long as possible.
Multitasking for your brain is like trying to clean two rooms at the same time that are on the opposite sides of your apartment.
What you would do in that case is clean a little bit in the first room — then walk over to the other room and clean a little bit it there — then walk back to the first room again, and so on.
This is a very inefficient way to clean the two rooms as the time you spend going across the apartment to get to the other room, you could just spend cleaning the room you are in at the moment. So the most efficient way to clean both rooms would be to first clean one room, then move on to the next one.
When you try to multitask, for your brain it’s exactly like that. It would be great if you could transport directly to the other room so that you can continue cleaning the second room right away with no time wasted on walking, but it just does not work like that. Your brain also does not “transport” from one task to another, rather it has to “walk the length of the apartment” to get to the other task. And you want to avoid doing that as much as possible.
So the next time you are working on some problem, and you see a new email notification, think of that email as being in a room on the other side of the apartment. You just don’t have the time to walk there and back again at the moment. You’ll read the email once you are done with what you are working on.
As software developers the biggest value we bring to the business is our efficiency: write valuable software in the minimum required time. What exactly is valuable software? There are many answers to that question, and one of them is: Software that does what is required to do, that is clean, and is written in a way that can be easily tested, extended and read in the future.
Once you have mastered the way to write valuable software, the next step is speed. How can you get there faster?
When the business has a new a task for the developer, the job of the developer can be divided into three different parts:
Part one: Understand what the software needs to do. The best way to do that is to treat the software that you are going to write like a black box: for every possible input, define what the expected output should be. Lets call this part ‘requirements’.
Part two: Write the code that will handle all the possible inputs defined in the first part, and give the correct outputs. This would be ‘functionality’.
Part three: Refactor the code to make it as valuable as you can. Let say ‘refactoring’.
Focusing on only one of those problems at a time, completely ignoring the other two is the best way to use your full cognitive power, and not fall into the trap of switching between them, and slowing down your efficiency.
Lets go trough each of these three parts in some more detail.
As the name suggests, in this part you only need to think about the requirements. After you have all the knowledge of what the requirements are — all the cases (inputs) that the code will need to handle and you are sure you have all the edge cases considered too — the next step is to write them down.
You can just write them down on a piece of paper, but there is no better documentation for the requirements of a piece of code, than tests. You can cover all the cases that your code will need to handle in the tests that you will write.
In this part you don’t have to write the complete and final tests that will fully test your finished code. At first you can just define the skeleton of the tests and use that as a road map to guide you on your way as you write the actual code. Then as you write your code, you can come back to the tests and finish them.
If you write your tests properly, they will also serve as documentation to be used by other developers (you included) in the future when they are trying to figure out what the code is suppose to do. Instead of looking at the actual code, they can look at the tests and quickly figure out what the functionality is.
In the second part you start writing the code that will do what the requirements specify it needs to do. But in this part you only care about functionality.
Your only care is that the code will do what it’s suppose to do, and nothing else. You don’t care about clean code, you don’t care about naming variables and methods properly. You write code like a “junior developer”, still learning their way around coding. You only care about making sure your code covers all the cases defined in the previous part: For every possible input, it provides the correct output.
You don’t have to shift your focus on the requirements of the task to make sure you didn’t forget a use case, or that you didn’t cover every possible edge case. Also you don’t think about what is the best name to use for the variables or for the methods — if a part of the code should go in a different method, or a different object. In this part your only focus is functionality.
After that, you finish your tests (or you start writing them if you did not start on them in the previous part), and you get them to pass. Then you are sure that your code works properly and you can move on to the next part.
You can write your tests in the first part or in the second part, or you can write them a little bit in both parts. But you will need your tests before you can go on. Otherwise the refactoring part will be very painful and slow for you.
After your tests pass, you are sure that the code you wrote will handle all the requirements. For every possible input, it will provide the correct output.
But as we said before, valuable software does not only do what it’s suppose to do. Valuable software has to have other traits as well. And in this last part, you only care about that. Here, you can use all the refactoring techniques in your arsenal to make sure that the code is as valuable as it can be.
You don’t think about requirements (tests got you covered there), you don’t think about functionality (the tests got you cover there as well), you only think about adding value to the code by refactoring it. That’s your focus in this part.
You change the name of the variables — you run the tests. If all is good you go on. You change the name of the methods — you run the tests. You extract a method or a new class — you run the tests.
Once you are done with this, you have written the most valuable software as fast as your cognitive abilities allow you too.
By being able to focus on one problem at a time, not going back and forth between requirements, functionality and refactoring, you made sure that each of those problems got your full attention and your full brain power.
Take note that this way of working does not work well for bigger tasks. If you have to solve a more complex problem you can’t do the steps like this. For a bigger problem you have to divide it into smaller tasks and do the steps then. You take a small part of the requirements, you write functionality about them and then you refactor. And you go over and over until you have the whole task completed.
Which brings as to TDD (test driven development). If you know TDD then you have probably made the connection by now about the three parts I talk about and the three parts of TDD ‘red, green, refactor’. And you are right! TDD is a practice that can be used to achieve the goals of this practice, but since you can do this practice without having to write the tests before you finish your code in part 2, you can do this without actually practicing TDD.
Our inability to multitask forces us to think carefully about the strategies we are going to undertake while developing software. We have to be very careful to avoid context switching as much as possible, so we need to come up with ways that force us to focus on just one task at a time. By doing so we make sure we write the best possible software in the shortest possible time, bringing more value to the business.
My biggest takeaway from this type of mindset is what happens when you separate parts 2 and 3. Every professional developer knows all the rules that you need to follow for your code to be clean, easy to read, testable and maintainable. And it’s often very difficult to have to think simultaneously about “what your code does” (functionality) and “how your code does it” (clean code). Being free from the burden of the how in part 2, you can allocate more brain power to solve what your code does. The same applies for part 3: When the “what your code does” is already taken care of, you are free to think about the how. A very useful book to help you do the work in part 3 is Refactoring By Martin Fowler.
This process can be used for a lot of other things. I used it when I wrote this article: In part 1 I just write down all the ideas I wanted to tell in very short sentences. In part 2 I explained those ideas by just writing down everything I wanted to say about them. And in part 3 I shaped the final product, re-wrote sentences so that they sound better, did a grammar check etc.
Post originally published on medium.