As soon as we started programming, we found out to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.
A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little nor too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity.
A final essential difficulty arises from software's inherent invisibility. Software can't be visualized with 2-D or 3-D geometric models. Attempts to visually represent even simple logic quickly becomes absurdly complicated, as anyone who has ever tried to draw a flow chart for even a simple program will attest.