Computer Programming

is in a state of crisis (or, more optimistically, a state of creative ferment). There is a growing recognition that the available programming languages are not adequate for building computer systems. Of course, as any first year student of computation theory knows, they are logically sufficient. But they do not deal adequately with the problems we face in the day-to-daywork of programming. We become swamped by the complexity of large systems, lost in code written by others, and mystified by the behavior of our almost debugged systems. When we look to the integrated multiprocessor systems that will soon dominate computing, the situation is even worse.

This crisis in software production is far greater (in overall magnitude at least) than the situation of the early 50's that led to the development of high level languages to relieve the burden of coding. The problems are harder to solve, and the costs of not solving them are in the hundreds of millions. "The symptoms appear in the form of software that is nonresponsive to user needs, unreliable, excessively expensive, untimely, inflexible, difficult to maintain, and not reusable." [3, p. 26.] There are many ways to improve things a little, and they are being tried. But to achieve a fundamental jump in our programming capacity, we need to rethink what we are doing from the beginning.

# The Problem

Winograd (1979) believes that the problem lies in an obsolete view of programming and programming languages. A widely accepted view can be paraphrased: The programmer's job is to design an algorithm (or a class of computations) for carrying out a task, and to write it down as a complete and precise set of instructions for a computer to follow. High level programming languages simplify the writing of these instructions by providing basic building blocks for stating instructions (both control and data structures) that are at a higher level of the logical structure of the algorithm than those of the basic machine.

This view has guided the development of many programming languages and systems. It served well in the early days of computing, but in today's computational environment, it is misleading and stultifying. It focuses attention on the wrong issues and gives the most important aspects of programming a second-class status. It is irrelevant in the same sense that binary arithmetic is irrelevant – the things it deals with are a necessary part of computing, but should play a subsidiary rather than central role in our understanding.

As computer technology (for both software and hardware) matures, our growing ability to create complex systems has led to three basic changes in the nature of programming:

*1. Computers are not primarily used for solving well-structured mathematical problems or data processing, but instead are components in complex systems.*

[…]