I never think about this:
Software is remarkable stuff. Sometimes, perhaps because we work with it all the time, we forget just how remarkable it is.
Very little else in human experience is as malleable, allowing us free rein to exercise our ingenuity and inventiveness almost without limits. Also, with a very few exceptions that we’ll cover later, software is deterministic—the next state is completely determined by the current state, and (crucially) we have com- plete access to all of that state whenever we want it.
Compared to traditional engineering, we are spoiled. What do you think a Formula One engineer would give to be able to instantaneously stop an engine when it’s rotating at 19,000 revolutions per minute and examine every aspect of it in minute detail? To see the precise state of each component while under pressure and stress, for example, or to dynamically record the shape and position of the flame front within the combustion chambers during ignition?
It is exactly this kind of trick that we are able to perform with our software, which is why the empirical approach is particularly powerful when debugging. [from book Debug It!]