I am going to start this section with a discussion about doubt, or unknowing. This was not in the original talk since it would not fit within the time allocated, but the response I received when I included it in a subsequent version of the talk makes me realise that it is a key idea we need to consider.
If we take the Cartesian view that we cannot really know the ‘things in themselves’, then in terms of creating new knowledge we have two possibilities:
- Run Away
We can decide that since we cannot get to know the Things, then we should not even try. This is the path chosen by those that wish to shun everything technological and go back to the old pre-modern ways. But as Ken Wilber points out in The Marriage of Sense & Soul(p44), I don’t think many folk today would want to go back there if they really knew what it was like.
Here we decide that we can be ‘Aggressively Empirical’. Don’t waste too much time with observation, just come up with hypotheses and test these against reality. This approach has no consideration for the embeddedness of the perceiver within the system being perceived, the classic dualistic bind, and can lead to an experiment reinforcing your expectations about a phenomenon.
Note that both of these approaches attempt to push the unknowing away.
Unknowing does not feel comfortable so a typical human reaction is to move away from the discomfort. But in this area it is a mistake. So what can we do?
- We need to develop ourselves and stay with the unknowing. This is the Delicately Empirical approach. We should consciously stay with the doubt and keep observing, hold back assumptions until our ideas and thinking mature in line with our observations.
It is this latter approach that requires a stronger sense of self in order to stay longer with the unknowing and the ability to hold this state is a core skill when working in a technical environment.
The first point at which I got an inkling that the field of software development could benefit from the insights of Delicate Empiricism was during a workshop at the OT2001 conference when I attended a session called “Tracer Bullets” hosted by Paul Simmons and Tom Ayerst. They initially showed a short film about the difference between the Russian and American approaches during the space race of the 1960s. The Russians were much more trial-and-error based whereas the Americans had a very strong quality assurance programme. [I notice there was a re-imagining of the session at SPA2013]
The workshop part of the session involved splitting up into small teams of about 4 or 5 people. Each team had a range of materials they could use to try and identify what item was hidden within a tall kitchen bin placed on a stool so you could not look down into it. Each team had to create tools to find out what was at the bottom of the bin. There was a limitation in that each team only had 8 tokens which would allow them to go up to the bin for 1 minute per token. So they only had 8 minutes of ‘research’ time up at the bin.
Having already been familiar with Goethe’s approach of Delicate Empiricism, I argued in my team to use the tokens one at a time and only go forward slowly. Luckily the other folks agreed with the approach and we set off. What surprised me, and provided the impetus for this research into phenomenology, was seeing the approaches taken by the other teams. Whereas our team simply went up with some long balsa wood ‘pokers’ and spent our first minute just stabbing around to get an initial sense of what was at the bottom of the bin, I saw other teams creating elaborate measuring tools which already pre-supposed certain attributes about what they expected to find. A classic case of over-hypothesizing.
Before using each token our team decided to identify what it was that we wanted to learn next, i.e being clear about the boundary of our knowledge, and devising a tool to move that boundary forward. Then once we got the extra data, we would reflect on it and adjust the model of what we thought was at the bottom of the bin. Then we would discuss what it was we wanted to know next, making sure that our hypothesizing did not rush too far ahead of our current knowledge.
My observation of this contrast between our approach and that of the other teams gave me the impetus to delve further into this subject.
The primary question to ask here is just how aware we are about our boundaries of knowledge, and do we know how best we should proceed when at those boundaries? These questions are absolutely crucial when it comes to debugging a wayward software application.
From the workshop I identified the following steps in the process:
- Ask: What do we already know?
We need to be clear about the knowledge we already have and need to consciously check the limits of that knowledge. This knowledge then forms the foundation for expanding what we know. In certain cases we might decide that we need to move into learning about a completely different area.
- Ask: What raw data do we need next?
What is the next piece of raw data we need to help us expand our knowledge? Note that I differentiate here between raw data and knowledge. The raw data we collect relates to the percept. It will need our reflection to find what concept fits the data. Done properly this enables us to create a mental model that properly fits the phenomenon and is not abstract.
- Ask: What tool do we need to get this information without overly disturbing the phenomenon?
Here we need to focus on creating the best tool for the job of finding the next piece of information we need, but without disturbing the system. This latter consideration is particularly important when debugging real-time multi-threaded systems. I find I frequently fall back into the ‘old school’ tradition of printing out the data if I can because usually a debugger is too invasive. (see ‘Staying Free’ below)
- Research: Use the tool to run the experiment and collect the raw data.
So at last we get to do what feels like ‘real’ research. In actuality the ‘real’ research starts with our thinking. Frequently programmers love to get to the keyboard too early because they (and their managers) mistake typing for software development. It feels safer because one feels like one is making demonstrable progress. But this is an illusion and is at the core of Robert Glass’ fact about the ‘disconnect’ between management and programmers. In arguing this I have found David Bohm’s insight that the experiment is purely an external manifestation of the thought concept useful.
- Reflect: Expand my knowledge by reflecting on the collected data.
This is where we need to look at the data we have collected (the percept) and start developing concepts that match it. By using a disciplined imagination we can check our concepts against the data and when we match them (the Aha! experience) we have expanded our knowledge. So now we can go back to stage 1.
As mentioned above programmers will likely use debuggers for helping them investigate a problem. This can work well when you are trying to find a fault that is relatively easy to pin down. This is because a debugger will have to modify the running code in order for it to be able to function. For instance it may allow the program to stop at user specified points which it can only do if it modifies the running software. It may also completely modify the memory footprint by putting guard areas around the ‘real’ areas of data in order to catch ‘illegal’ memory accesses outside of what was expected.
Now that systems and debuggers have become more complicated, it is not a given that a programmer will know what the system is doing underneath the hood to provide this helpful functionality. This is where we touch on the nature of freedom. If you do not know what the system is doing – you cannot be free, i.e. you cannot know exactly what is going on, and so your assumptions can be faulty. I will come back to this concept in a later post since it relates to ANY technological use and should start some alarm bells ringing.
But back to the developer. As you can imagine, if you are working on a system that has real-time constraints (I work on video systems which need to play out faultlessly for hours) it just is not feasible to use a debugger to help find some of the nastier problems. Hence my comments above about the ‘old school’ techniques, i.e. printing out the data. With older systems it was not even possible to do this without disturbing the real-time operation because the process was too slow. Nowadays you can generally get away with it, but there will still be the occasional problem where printing out a single number could cause a change to the timing of the system and thus the fault will not manifest. Thus you need to know your system and then know what is the best ‘instrument’ – code modification – that can collect the data you need to find the fault.
Computer as Thought Mirror
Pity the novice or journeyman programmer who has not yet realised that his or her process of debugging is flawed. All too frequently I see less experienced programmers (a) jumping to an early conclusion about the cause of a fault and then (b) modifying the code to ‘fix’ the problem based on this conclusion. Jumping to the wrong conclusion too early happens time and time again and you will see it happening many times a day in most software companies.
It can cost them a lot of money because they may now ship this software proudly announcing the fix of this specific bug only to find that it has re-appeared in a slightly different guise. What has usually happened is that the timing of the system was changed so the original fault became hidden, but the actual cause, i.e. the bug, was still there. I have found from bitter experience that it can take many many years – a decade is usual – for a programmer to sufficiently hone their debugging skills to the point that they do not fall into the trap of making false assumptions. It truly requires a great deal of willpower and self-awareness. Of course, better processes can help but they will still rely upon discerning human judgement.
The developer is having to learn the boundaries of their knowledge the hard way and the computer is mirroring back the quality of their thought process. Hence my calling it a ‘Thought Mirror’. Generally the novice starts out having great faith in their ability to understand the effects of their software creation, possibly being surprised that it is going wrong. If they are truly growing through the course of their career this will change to assuming they are wrong and possibly not even trusting that the code is correct even though the system is functioning perfectly. You will also find that many seasoned programmers will not buy the latest and greatest software releases – unless they really really have to!
I hope that gives you some sense of how convinced I am that anyone good at debugging will be using the technique of Goethe’s Delicate Empiricism without even realizing it.
Have we unconsciously created a technology that pushes us to the limits of knowledge just so we can come to know ourselves better?
To paraphrase Jeff Carreira, in software development ‘philosophy is not a luxury’.
Next time I shall take a deeper look at the issue of disciplined imagination, Exact Sensorial Imagination to be precise, and how it relates to software development.