Saturday, August 15, 2009

Debugging the Kitchen Sink

In this post, I explain the debugging process, difficulties novice developers have with it, and present a practical non-computer-programming example of applying it to debug a problem with my kitchen sink's faucet.

The Debugging Process

"Debugging" is a vital skill in the software development world that a is used quite often to solve programming problems, ranging from simple logic mistakes to difficult-to-repeat concurrency race conditions or deadlocks.

However the process of debugging is an implementation of a generic, logical, and scientific problem-solving process which is applicable well beyond computer programming. That process is simplified as:
  1. Establish an observable problem.
  2. Test to determine all of the specific scenarios where the problem is observed.
  3. Understand the major components involved.
  4. Hypothesize what could be causing the problem.
  5. Locate the problem.
  6. Make changes to resolve the problem.
  7. Test all specific scenarios where the problem happened to confirm the problem is solved.

Difficulties with the Debugging Process

I have often observed that novice developers encounter difficulties in applying this process, by halting as soon as actual results are not the same as expected results. When they come asking "What do I do?" my answer, if not "Check the Reference" will always be, "Debug it".

The difficulty of understanding this process seems to be with Step 5 - Locate the problem, which rightfully may be a time-consuming process. With a "syntax error", the compiler/interpreter usually tells you exactly where the problem lies, so it is an easy fix. But with a "semantic error", meaning it's a programming or design mistake has caused unintended results, you must gradually narrow down the source of the problem over many iterative tests starting from the general range of what works, and gradually running more specific tests, ending at the actual source of the problem.


To illustrate the debugging process in a practical non-computer-programming, example -- just this morning I applied it to a household problem that has been nagging me for quite some time.

Application: The Kitchen Sink's Faucet

A few years ago when I moved into my house, I replaced the kitchen sink's faucet, an old two-knob fixed-faucet type, with a new single-handle pull-out model. However when I was finished there was a problem: the cold water pressure was significantly lower than the hot water pressure. I finally got around to working on this, and applied the same debugging process, as follows.
  1. Establish an observable problem.
    The problem is that when the handle is pushed all the way to the cold side, the water is very slow, but when all the way to the hot side, the water is very fast.

  2. Test to determine all of the specific scenarios where the problem is observed.
    In this case, the above is the only observable scenario.

  3. Understand the major components involved.
    The major components are:
    1. the faucet's output
    2. the faucet's hot and cold water intakes
    3. the 2 tubes connecting the wall outlets to the faucet intakes
    4. the hot and cold wall outlets

    This diagram illustrates how the components are connected and the direction of water-flow.

    Activity Model of Faucet Components
  4. Hypothesize what could be causing the problem.
    My two bathroom sinks have no problem with the water pressure from either hot or cold lines. Based on that I will rule out the wall outlets. Also, since the hot water pressure from the faucet output is just fine, I will rule that out.

    That narrows down the range of the problem to one of the two remaining components:
    1. the faucet's output
    2. the faucet's hot and cold intakes
    3. the 2 tubes connecting the wall outlets to the faucet intakes
    4. the hot and cold wall outlets

  5. Locate the problem.
    1. First I want to see if the problem exists in the faucet's hot and cold intakes. I know that hot is fine, but cold is low, so my test was to switch the connections between the intakes and the tubes, causing hot water to come out when the faucet is turned to cold, and vice versa. If the cold water pressure becomes good but hot becomes poor, then the problem exists in the intakes:


      The results of this test however are that the pressure is unchanged - hot is still good and cold is still poor. So the intakes are not the problem. I scratch that off the list:
      1. the faucet's output
      2. the faucet's hot and cold intakes
      3. the 2 tubes connecting the wall outlets to the faucet intakes
      4. the hot and cold wall outlets

    2. If my hypothesis is correct, the problem must exist in the tubes. To test this, I undo the tube switch from the previous test, and now swap the tube connections with the wall outlets. Now, if the cold water pressure becomes good but hot becomes poor, then the problem exists in the tubes:


      The results of this test are that the cold water pressure is now good, but the hot water pressure is poor. Thus, this test proves that the problem exists in the Cold Water Tube.

  6. Make changes to resolve the problem.
    Since I cannot get into the cold water tube to find out what is wrong with it, my next step is to replace the defective tube with a new one from the store.

  7. Test all specific scenarios where the problem happened to confirm the problem is solved.
    Once I buy my new tube, I will install it and test to make sure that the cold water pressure is now the same as the hot water pressure.

As you can see, the process of debugging can be applied to any problem, computer-programming or otherwise, as long as you have a general understanding of the components involved, how they interact, and if you can follow and logical and scientific thought-process.

No comments:

Post a Comment

Was this post helpful? Do you have questions about it? Do you want to share your own programming blog? I'd love to read your feedback.

Note: Only a member of this blog may post a comment.