ACM Turing Lecture 1972 EWD340
The Humble Programmer
by
Edsger W. Dijkstra
As a result of a long sequence of coincidences I entered the
programming profession officially on the first spring morning of 1952
and as far as I have been able to trace, I was the first Dutchman to do so
in my country. In retrospect the most amazing thing was the slowness
with which, at least in my part of the world, the programming profession
emerged, a slowness which is now hard to believe. But I am grateful for
two vivid recollections from that period that establish that slowness
beyond any doubt.
After having programmed for some three years, I had a discussion with
A. van Wijngaarden, who was then my boss at the Mathematical Centre
in Amsterdam, a discussion for which I shall remain grateful to him as
long as I live. The point was that I was supposed to study theoretical
physics at the University of Leiden simultaneously, and as I found the
two activities harder and harder to combine, I had to make up my mind,
either to stop programming and become a real, respectable theoretical
physicist, or to carry my study of physics to a formal completion only,
with a minimum of effort, and to become....., yes what? A programmer?
But was that a respectable profession? For after all, what was
programming? Where was the sound body of knowledge that could
support it as an intellectually respectable discipline? I remember quite
vividly how I envied my hardware colleagues, who, when asked about
their professional competence, could at least point out that they knew
everything about vacuum tubes, amplifiers and the rest, whereas I felt
that, when faced with that question, I would stand empty-handed. Full of
misgivings I knocked on van Wijngaarden’s office door, asking him
whether I could “speak to him for a moment”; when I left his office a
number of hours later, I was another person. For after having listened to
my problems patiently, he agreed that up till that moment there was not
much of a programming discipline, but then he went on to explain
quietly that automatic computers were here to stay, that we were just at
the beginning and could not I be one of the persons called to make
programming a respectable discipline in the years to come? This was a
turning point in my life and I completed my study of physics formally as
quickly as I could. One moral of the above story is, of course, that we
must be very careful when we give advice to younger people;
sometimes they follow it!
Another two years later, in 1957, I married and Dutch marriage rites
require you to state your profession and I stated that I was a
programmer. But the municipal authorities of the town of Amsterdam
did not accept it on the grounds that there was no such profession. And,
believe it or not, but under the heading “profession” my marriage act
shows the ridiculous entry “theoretical physicist”!
So much for the slowness with which I saw the programming profession
emerge in my own country. Since then I have seen more of the world,
and it is my general impression that in other countries, apart from a
possible shift of dates, the growth pattern has been very much the same.
Let me try to capture the situation in those old days in a little bit more
detail, in the hope of getting a better understanding of the situation
today. While we pursue our analysis, we shall see how many common
misunderstandings about the true nature of the programming task can be
traced back to that now distant past.
The first automatic electronic computers were all unique, single-copy
machines and they were all to be found in an environment with the
exciting flavour of an experimental laboratory. Once the vision of the
automatic computer was there, its realisation was a tremendous
challenge to the electronic technology then available, and one thing is
certain: we cannot deny the courage of the groups that decided to try
and build such a fantastic piece of equipment. For fantastic pieces of
equipment they were: in retrospect one can only wonder that those first
machines worked at all, at least sometimes. The overwhelming problem
was to get and keep the machine in working order. The preoccupation
with the physical aspects of automatic computing is still reflected in the
names of the older scientific societies in the field, such as the
Association for Computing Machinery or the British Computer Society,
names in which explicit reference is made to the physical equipment.
What about the poor programmer? Well, to tell the honest truth: he was
hardly noticed. For one thing, the first machines were so bulky that you
could hardly move them and besides that, they required such extensive
maintenance that it was quite natural that the place where people tried to
use the machine was the same laboratory where the machine had been
developed. Secondly, his somewhat invisible work was without any
glamour: you could show the machine to visitors and that was several
orders of magnitude more spectacular than some sheets of coding. But
most important of all, the programmer himself had a very modest view
of his own work: his work derived all its significance from the existence
of that wonderful machine. Because that was a unique machine, he
knew only too well that his programs had only local significance and
also, because it was patently obvious that this machine would have a
limited lifetime, he knew that very little of his work would have a
lasting value. Finally, there is yet another circumstance that had a
profound influence on the programmer’s attitude to his work: on the one
hand, besides being unreliable, his machine was usually too slow and its
memory was usually too small, i.e. he was faced with a pinching shoe,
while on the other hand its usually somewhat queer order code would
cater for the most unexpected constructions. And in those days many a
clever programmer derived an immense intellectual satisfaction from the
cunning tricks by means of which he contrived to squeeze the
impossible into the constraints of his equipment.
Two opinions about programming date from those days. I mention them
now, I shall return to them later. The one opinion was that a really
competent programmer should be puzzle-minded and very fond of
clever tricks; the other opinion was that programming was nothing more
than optimizing the efficiency of the computational process, in one
direction or the other.
The latter opinion was the result of the frequent circumstance that,
indeed, the available equipment was a painfully pinching shoe, and in
those days one often encountered the naive expectation that, once more
powerful machines were available, programming would no longer be a
problem, for then the struggle to push the machine to its limits would no
longer be necessary and that was all what programming was about,
wasn’t it? But in the next decades something completely different
happened: more powerful machines became available, not just an order
of magnitude more powerful, even several orders of magnitude more
powerful. But instead of finding ourselves in the state of eternal bliss of
all programming problems solved, we found ourselves up to our necks
in the software crisis! How come?
There is a minor cause: in one or two respects modern machinery is
basically more difficult to handle than the old machinery. Firstly, we
have got the I/O interrupts, occurring at unpredictable and
irreproducible moments; compared with the old sequential machine that
pretended to be a fully deterministic automaton, this has been a dramatic
change and many a systems programmer’s grey hair bears witness to the
fact that we should not talk lightly about the logical problems created by
that feature. Secondly, we have got machines equipped with multi-level
stores, presenting us problems of management strategy that, in spite of
the extensive literature on the subject, still remain rather elusive. So
much for the added complication due to structural changes of the actual
machines.
But I called this a minor cause; the major cause is... that the machines
have become several orders of magnitude more powerful! To put it quite
bluntly: as long as there were no machines, programming was no
problem at all; when we had a few weak computers, programming
became a mild problem, and now we have gigantic computers,
programming had become an equally gigantic problem. In this sense the
electronic industry has not solved a single problem, it has only created
them, it has created the problem of using its products. To put it in
another way: as the power of available machines grew by a factor of
more than a thousand, society’s ambition to apply these machines grew
in proportion, and it was the poor programmer who found his job in this
exploded field of tension between ends and means. The increased power
of the hardware, together with the perhaps even more dramatic increase
in its reliability, made solutions feasible that the programmer had not
dared to dream about a few years before. And now, a few years later, he
had to dream about them and, even worse, he had to transform such
dreams into reality! Is it a wonder that we found ourselves in a software
crisis? No, certainly not, and as you may guess, it was even predicted
well in advance; but the trouble with minor prophets, of course, is that it
is only five years later that you really know that they had been right.
Then, in the mid-sixties, something terrible happened: the computers of
the so-called third generation made their appearance. The official
literature tells us that their price/performance ratio has been one of the
major design objectives. But if you take as “performance” the duty cycle
of the machine’s various components, little will prevent you from
ending up with a design in which the major part of your performance
goal is reached by internal housekeeping activities of doubtful necessity.
And if your definition of price is the price to be paid for the hardware,
little will prevent you from ending up with a design that is terribly hard
to program for: for instance the order code might be such as to enforce,
either upon the programmer or upon the system, early binding decisions
presenting conflicts that really cannot be resolved. And to a large extent
these unpleasant possibilities seem to have become reality.
When these machines were announced and their functional
specifications became known, quite a few among us must have become
quite miserable; at least I was. It was only reasonable to expect that such
machines would flood the computing community, and it was therefore
all the more important that their design should be as sound as possible.
But the design embodied such serious flaws that I felt that with a single
stroke the progress of computing science had been retarded by at least
ten years: it was then that I had the blackest week in the whole of my
professional life. Perhaps the most saddening thing now is that, even
after all those years of frustrating experience, still so many people
honestly believe that some law of nature tells us that machines have to
be that way. They silence their doubts by observing how many of these
machines have been sold, and derive from that observation the false
sense of security that, after all, the design cannot have been that bad.
But upon closer inspection, that line of defense has the same convincing
strength as the argument that cigarette smoking must be healthy because
so many people do it.
It is in this connection that I regret that it is not customary for scientific
journals in the computing area to publish reviews of newly announced
computers in much the same way as we review scientific publications:
to review machines would be at least as important. And here I have a
confession to make: in the early sixties I wrote such a review with the
intention of submitting it to the CACM, but in spite of the fact that the
few colleagues to whom the text was sent for their advice, urged me all
to do so, I did not dare to do it, fearing that the difficulties either for
myself or for the editorial board would prove to be too great. This
suppression was an act of cowardice on my side for which I blame
myself more and more. The difficulties I foresaw were a consequence of
the absence of generally accepted criteria, and although I was convinced
of the validity of the criteria I had chosen to apply, I feared that my
review would be refused or discarded as “a matter of personal taste”. I
still think that such reviews would be extremely useful and I am longing
to see them appear, for their accepted appearance would be a sure sign
of maturity of the computing community.
The reason that I have paid the above attention to the hardware scene is
because I have the feeling that one of the most important aspects of any
computing tool is its influence on the thinking habits of those that try to
use it, and because I have reasons to believe that that influence is many
times stronger than is commonly assumed. Let us now switch our
attention to the software scene.
Here the diversity has been so large that I must confine myself to a few
stepping stones. I am painfully aware of the arbitrariness of my choice
and I beg you not to draw any conclusions with regard to my
appreciation of the many efforts that will remain unmentioned.
In the beginning there was the EDSAC in Cambridge, England, and I
think it quite impressive that right from the start the notion of a
subroutine library played a central role in the design of that machine and
of the way in which it should be used. It is now nearly 25 years later and
the computing scene has changed dramatically, but the notion of basic
software is still with us, and the notion of the closed subroutine is still
one of the key concepts in programming. We should recognise the
closed subroutines as one of the greatest software inventions; it has
survived three generations of computers and it will survive a few more,
because it caters for the implementation of one of our basic patterns of
abstraction. Regrettably enough, its importance has been underestimated
in the design of the third generation computers, in which the great
number of explicitly named registers of the arithmetic unit implies a
large overhead on the subroutine mechanism. But even that did not kill
the concept of the subroutine, and we can only pray that the mutation
won’t prove to be hereditary.
The second major development on the software scene that I would like
to mention is the birth of FORTRAN. At that time this was a project of
great temerity and the people responsible for it deserve our great
admiration. It would be absolutely unfair to blame them for
shortcomings that only became apparent after a decade or so of
extensive usage: groups with a successful look-ahead of ten years are
quite rare! In retrospect we must rate FORTRAN as a successful coding
technique, but with very few effective aids to conception, aids which are
now so urgently needed that time has come to consider it out of date.
The sooner we can forget that FORTRAN has ever existed, the better,
for as a vehicle of thought it is no longer adequate: it wastes our
brainpower, is too risky and therefore too expensive to use.
FORTRAN’s tragic fate has been its wide acceptance, mentally chaining
thousands and thousands of programmers to our past mistakes. I pray
daily that more of my fellow-programmers may find the means of
freeing themselves from the curse of compatibility.
The third project I would not like to leave unmentioned is LISP, a
fascinating enterprise of a completely different nature. With a few very
basic principles at its foundation, it has shown a remarkable stability.
Besides that, LISP has been the carrier for a considerable number of in a
sense our most sophisticated computer applications. LISP has jokingly
been described as “the most intelligent way to misuse a computer”. I
think that description a great compliment because it transmits the full
flavour of liberation: it has assisted a number of our most gifted fellow
humans in thinking previously impossible thoughts.
The fourth project to be mentioned is ALGOL 60. While up to the
present day FORTRAN programmers still tend to understand their
programming language in terms of the specific implementation they are
working with —hence the prevalence of octal and hexadecimal dumps
—, while the definition of LISP is still a curious mixture of what the
language means and how the mechanism works, the famous Report on
the Algorithmic Language ALGOL 60 is the fruit of a genuine effort to
carry abstraction a vital step further and to define a programming
language in an implementation-independent way. One could argue that
in this respect its authors have been so successful that they have created
serious doubts as to whether it could be implemented at all! The report
gloriously demonstrated the power of the formal method BNF, now
fairly known as Backus-Naur-Form, and the power of carefully phrased
English, at least when used by someone as brilliant as Peter Naur. I
think that it is fair to say that only very few documents as short as this
have had an equally profound influence on the computing community.
The ease with which in later years the names ALGOL and ALGOL-like
have been used, as an unprotected trade mark, to lend some of its glory
to a number of sometimes hardly related younger projects, is a
somewhat shocking compliment to its standing. The strength of BNF as
a defining device is responsible for what I regard as one of the
weaknesses of the language: an over-elaborate and not too systematic
syntax could now be crammed into the confines of very few pages. With
a device as powerful as BNF, the Report on the Algorithmic Language
ALGOL 60 should have been much shorter. Besides that I am getting
very doubtful about ALGOL 60’s parameter mechanism: it allows the
programmer so much combinatorial freedom, that its confident use
requires a strong discipline from the programmer. Besides expensive to
implement it seems dangerous to use.
Finally, although the subject is not a pleasant one, I must mention PL/1,
a programming language for which the defining documentation is of a
frightening size and complexity. Using PL/1 must be like flying a plane
with 7000 buttons, switches and handles to manipulate in the cockpit. I
absolutely fail to see how we can keep our growing programs firmly
within our intellectual grip when by its sheer baroqueness the
programming language —our basic tool, mind you!— already escapes
our intellectual control. And if I have to describe the influence PL/1 can
have on its users, the closest metaphor that comes to my mind is that of
a drug. I remember from a symposium on higher level programming
language a lecture given in defense of PL/1 by a man who described
himself as one of its devoted users. But within a one-hour lecture in
praise of PL/1. he managed to ask for the addition of about fifty new
“features”, little supposing that the main source of his problems could
very well be that it contained already far too many “features”. The
speaker displayed all the depressing symptoms of addiction, reduced as
he was to the state of mental stagnation in which he could only ask for
more, more, more... When FORTRAN has been called an infantile
disorder, full PL/1, with its growth characteristics of a dangerous tumor,
could turn out to be a fatal disease.
So much for the past. But there is no point in making mistakes unless
thereafter we are able to learn from them. As a matter of fact, I think that
we have learned so much, that within a few years programming can be
an activity vastly different from what it has been up till now, so different
that we had better prepare ourselves for the shock. Let me sketch for
you one of the possible futures. At first sight, this vision of
programming in perhaps already the near future may strike you as
utterly fantastic. Let me therefore also add the considerations that might
lead one to the conclusion that this vision could be a very real
possibility.
The vision is that, well before the seventies have run to completion, we
shall be able to design and implement the kind of systems that are now
straining our programming ability, at the expense of only a few percent
in man-years of what they cost us now, and that besides that, these
systems will be virtually free of bugs. These two improvements go hand
in hand. In the latter respect software seems to be different from many
other products, where as a rule a higher quality implies a higher price.
Those who want really reliable software will discover that they must
find means of avoiding the majority of bugs to start with, and as a result
the programming process will become cheaper. If you want more
effective programmers, you will discover that they should not waste
their time debugging, they should not introduce the bugs to start with. In
other words: both goals point to the same change.
Such a drastic change in such a short period of time would be a
revolution, and to all persons that base their expectations for the future
on smooth extrapolation of the recent past —appealing to some
unwritten laws of social and cultural inertia— the chance that this
drastic change will take place must seem negligible. But we all know
that sometimes revolutions do take place! And what are the chances for
this one?
There seem to be three major conditions that must be fulfilled. The
world at large must recognize the need for the change; secondly the
economic need for it must be sufficiently strong; and, thirdly, the change
must be technically feasible. Let me discuss these three conditions in the
above order.
With respect to the recognition of the need for greater reliability of
software, I expect no disagreement anymore. Only a few years ago this
was different: to talk about a software crisis was blasphemy. The turning
point was the Conference on Software Engineering in Garmisch,
October 1968, a conference that created a sensation as there occurred
the first open admission of the software crisis. And by now it is
generally recognized that the design of any large sophisticated system is
going to be a very difficult job, and whenever one meets people
responsible for such undertakings, one finds them very much concerned
about the reliability issue, and rightly so. In short, our first condition
seems to be satisfied.
Now for the economic need. Nowadays one often encounters the
opinion that in the sixties programming has been an overpaid
profession, and that in the coming years programmer salaries may be
expected to go down. Usually this opinion is expressed in connection
with the recession, but it could be a symptom of something different and
quite healthy, viz. that perhaps the programmers of the past decade have
not done so good a job as they should have done. Society is getting
dissatisfied with the performance of programmers and of their products.
But there is another factor of much greater weight. In the present
situation it is quite usual that for a specific system, the price to be paid
for the development of the software is of the same order of magnitude as
the price of the hardware needed, and society more or less accepts that.
But hardware manufacturers tell us that in the next decade hardware
prices can be expected to drop with a factor of ten. If software
development were to continue to be the same clumsy and expensive
process as it is now, things would get completely out of balance. You
cannot expect society to accept this, and therefore we must learn to
program an order of magnitude more effectively. To put it in another
way: as long as machines were the largest item on the budget, the
programming profession could get away with its clumsy techniques, but
that umbrella will fold rapidly. In short, also our second condition seems
to be satisfied.
And now the third condition: is it technically feasible? I think it might
and I shall give you six arguments in support of that opinion.
A study of program structure had revealed that programs —even
alternative programs for the same task and with the same mathematical
content— can differ tremendously in their intellectual manageability. A
number of rules have been discovered, violation of which will either
seriously impair or totally destroy the intellectual manageability of the
program. These rules are of two kinds. Those of the first kind are easily
imposed mechanically, viz. by a suitably chosen programming language.
Examples are the exclusion of goto-statements and of procedures with
more than one output parameter. For those of the second kind I at least
—but that may be due to lack of competence on my side— see no way
of imposing them mechanically, as it seems to need some sort of
automatic theorem prover for which I have no existence proof.
Therefore, for the time being and perhaps forever, the rules of the
second kind present themselves as elements of discipline required from
the programmer. Some of the rules I have in mind are so clear that they
can be taught and that there never needs to be an argument as to whether
a given program violates them or not. Examples are the requirements
that no loop should be written down without providing a proof for
termination nor without stating the relation whose invariance will not be
destroyed by the execution of the repeatable statement.
I now suggest that we confine ourselves to the design and
implementation of intellectually manageable programs. If someone fears
that this restriction is so severe that we cannot live with it, I can reassure
him: the class of intellectually manageable programs is still sufficiently
rich to contain many very realistic programs for any problem capable of
algorithmic solution. We must not forget that it is not our business to
make programs, it is our business to design classes of computations that
will display a desired behaviour. The suggestion of confining ourselves
to intellectually manageable programs is the basis for the first two of my
announced six arguments.
Argument one is that, as the programmer only needs to consider
intellectually manageable programs, the alternatives he is choosing
between are much, much easier to cope with.
Argument two is that, as soon as we have decided to restrict ourselves to
the subset of the intellectually manageable programs, we have achieved,
once and for all, a drastic reduction of the solution space to be
considered. And this argument is distinct from argument one.
Argument three is based on the constructive approach to the problem of
program correctness. Today a usual technique is to make a program and
then to test it. But: program testing can be a very effective way to show
the presence of bugs, but is hopelessly inadequate for showing their
absence. The only effective way to raise the confidence level of a
program significantly is to give a convincing proof of its correctness.
But one should not first make the program and then prove its
correctness, because then the requirement of providing the proof would
only increase the poor programmer’s burden. On the contrary: the
programmer should let correctness proof and program grow hand in
hand. Argument three is essentially based on the following observation.
If one first asks oneself what the structure of a convincing proof would
be and, having found this, then constructs a program satisfying this
proof’s requirements, then these correctness concerns turn out to be a
very effective heuristic guidance. By definition this approach is only
applicable when we restrict ourselves to intellectually manageable
programs, but it provides us with effective means for finding a
satisfactory one among these.
Argument four has to do with the way in which the amount of
intellectual effort needed to design a program depends on the program
length. It has been suggested that there is some kind of law of nature
telling us that the amount of intellectual effort needed grows with the
square of program length. But, thank goodness, no one has been able to
prove this law. And this is because it need not be true. We all know that
the only mental tool by means of which a very finite piece of reasoning
can cover a myriad cases is called “abstraction”; as a result the effective
exploitation of his powers of abstraction must be regarded as one of the
most vital activities of a competent programmer. In this connection it
might be worth-while to point out that the purpose of abstracting is not
to be vague, but to create a new semantic level in which one can be
absolutely precise. Of course I have tried to find a fundamental cause
that would prevent our abstraction mechanisms from being sufficiently
effective. But no matter how hard I tried, I did not find such a cause. As
a result I tend to the assumption —up till now not disproved by
experience— that by suitable application of our powers of abstraction,
the intellectual effort needed to conceive or to understand a program
need not grow more than proportional to program length. But a by-
product of these investigations may be of much greater practical
significance, and is, in fact, the basis of my fourth argument. The by-
product was the identification of a number of patterns of abstraction that
play a vital role in the whole process of composing programs. Enough is
now known about these patterns of abstraction that you could devote a
lecture to about each of them. What the familiarity and conscious
knowledge of these patterns of abstraction imply dawned upon me when
I realized that, had they been common knowledge fifteen years ago, the
step from BNF to syntax-directed compilers, for instance, could have
taken a few minutes instead of a few years. Therefore I present our
recent knowledge of vital abstraction patterns as the fourth argument.
Now for the fifth argument. It has to do with the influence of the tool we
are trying to use upon our own thinking habits. I observe a cultural
tradition, which in all probability has its roots in the Renaissance, to
ignore this influence, to regard the human mind as the supreme and
autonomous master of its artefacts. But if I start to analyse the thinking
habits of myself and of my fellow human beings, I come, whether I like
it or not, to a completely different conclusion, viz. that the tools we are
trying to use and the language or notation we are using to express or
record our thoughts, are the major factors determining what we can
think or express at all! The analysis of the influence that programming
languages have on the thinking habits of its users, and the recognition
that, by now, brainpower is by far our scarcest resource, they together
give us a new collection of yardsticks for comparing the relative merits
of various programming languages. The competent programmer is fully
aware of the strictly limited size of his own skull; therefore he
approaches the programming task in full humility, and among other
things he avoids clever tricks like the plague. In the case of a well-
known conversational programming language I have been told from
various sides that as soon as a programming community is equipped
with a terminal for it, a specific phenomenon occurs that even has a
well-established name: it is called “the one-liners”. It takes one of two
different forms: one programmer places a one-line program on the desk
of another and either he proudly tells what it does and adds the question
“Can you code this in less symbols?” —as if this were of any conceptual
relevance!— or he just asks “Guess what it does!”. From this
observation we must conclude that this language as a tool is an open
invitation for clever tricks; and while exactly this may be the
explanation for some of its appeal, viz. to those who like to show how
clever they are, I am sorry, but I must regard this as one of the most
damning things that can be said about a programming language. Another
lesson we should have learned from the recent past is that the
development of “richer” or “more powerful” programming languages
was a mistake in the sense that these baroque monstrosities, these
conglomerations of idiosyncrasies, are really unmanageable, both
mechanically and mentally. I see a great future for very systematic and
very modest programming languages. When I say “modest”, I mean
that, for instance, not only ALGOL 60’s “for clause”, but even
FORTRAN’s “DO loop” may find themselves thrown out as being too
baroque. I have run a little programming experiment with really
experienced volunteers, but something quite unintended and quite
unexpected turned up. None of my volunteers found the obvious and
most elegant solution. Upon closer analysis this turned out to have a
common source: their notion of repetition was so tightly connected to
the idea of an associated controlled variable to be stepped up, that they
were mentally blocked from seeing the obvious. Their solutions were
less efficient, needlessly hard to understand, and it took them a very
long time to find them. It was a revealing, but also shocking experience
for me. Finally, in one respect one hopes that tomorrow’s programming
languages will differ greatly from what we are used to now: to a much
greater extent than hitherto they should invite us to reflect in the
structure of what we write down all abstractions needed to cope
conceptually with the complexity of what we are designing. So much for
the greater adequacy of our future tools, which was the basis of the fifth
argument.
As an aside I would like to insert a warning to those who identify the
difficulty of the programming task with the struggle against the
inadequacies of our current tools, because they might conclude that,
once our tools will be much more adequate, programming will no longer
be a problem. Programming will remain very difficult, because once we
have freed ourselves from the circumstantial cumbersomeness, we will
find ourselves free to tackle the problems that are now well beyond our
programming capacity.
You can quarrel with my sixth argument, for it is not so easy to collect
experimental evidence for its support, a fact that will not prevent me
from believing in its validity. Up till now I have not mentioned the word
“hierarchy”, but I think that it is fair to say that this is a key concept for
all systems embodying a nicely factored solution. I could even go one
step further and make an article of faith out of it, viz. that the only
problems we can really solve in a satisfactory manner are those that
finally admit a nicely factored solution. At first sight this view of human
limitations may strike you as a rather depressing view of our
predicament, but I don’t feel it that way, on the contrary! The best way
to learn to live with our limitations is to know them. By the time that we
are sufficiently modest to try factored solutions only, because the other
efforts escape our intellectual grip, we shall do our utmost best to avoid
all those interfaces impairing our ability to factor the system in a helpful
way. And I cannot but expect that this will repeatedly lead to the
discovery that an initially untractable problem can be factored after all.
Anyone who has seen how the majority of the troubles of the compiling
phase called “code generation” can be tracked down to funny properties
of the order code, will know a simple example of the kind of things I
have in mind. The wider applicability of nicely factored solutions is my
sixth and last argument for the technical feasibility of the revolution that
might take place in the current decade.
In principle I leave it to you to decide for yourself how much weight
you are going to give to my considerations, knowing only too well that I
can force no one else to share my beliefs. As each serious revolution, it
will provoke violent opposition and one can ask oneself where to expect
the conservative forces trying to counteract such a development. I don’t
expect them primarily in big business, not even in the computer
business; I expect them rather in the educational institutions that provide
today’s training and in those conservative groups of computer users that
think their old programs so important that they don’t think it worth-
while to rewrite and improve them. In this connection it is sad to
observe that on many a university campus the choice of the central
computing facility has too often been determined by the demands of a
few established but expensive applications with a disregard of the
question how many thousands of “small users” that are willing to write
their own programs were going to suffer from this choice. Too often, for
instance, high-energy physics seems to have blackmailed the scientific
community with the price of its remaining experimental equipment. The
easiest answer, of course, is a flat denial of the technical feasibility, but I
am afraid that you need pretty strong arguments for that. No
reassurance, alas, can be obtained from the remark that the intellectual
ceiling of today’s average programmer will prevent the revolution from
taking place: with others programming so much more effectively, he is
liable to be edged out of the picture anyway.
There may also be political impediments. Even if we know how to
educate tomorrow’s professional programmer, it is not certain that the
society we are living in will allow us to do so. The first effect of
teaching a methodology —rather than disseminating knowledge— is
that of enhancing the capacities of the already capable, thus magnifying
the difference in intelligence. In a society in which the educational
system is used as an instrument for the establishment of a homogenized
culture, in which the cream is prevented from rising to the top, the
education of competent programmers could be politically impalatable.
Let me conclude. Automatic computers have now been with us for a
quarter of a century. They have had a great impact on our society in their
capacity of tools, but in that capacity their influence will be but a ripple
on the surface of our culture, compared with the much more profound
influence they will have in their capacity of intellectual challenge
without precedent in the cultural history of mankind. Hierarchical
systems seem to have the property that something considered as an
undivided entity on one level, is considered as a composite object on the
next lower level of greater detail; as a result the natural grain of space or
time that is applicable at each level decreases by an order of magnitude
when we shift our attention from one level to the next lower one. We
understand walls in terms of bricks, bricks in terms of crystals, crystals
in terms of molecules etc. As a result the number of levels that can be
distinguished meaningfully in a hierarchical system is kind of
proportional to the logarithm of the ratio between the largest and the
smallest grain, and therefore, unless this ratio is very large, we cannot
expect many levels. In computer programming our basic building block
has an associated time grain of less than a microsecond, but our program
may take hours of computation time. I do not know of any other
technology covering a ratio of 1010 or more: the computer, by virtue of
its fantastic speed, seems to be the first to provide us with an
environment where highly hierarchical artefacts are both possible and
necessary. This challenge, viz. the confrontation with the programming
task, is so unique that this novel experience can teach us a lot about
ourselves. It should deepen our understanding of the processes of design
and creation, it should give us better control over the task of organizing
our thoughts. If it did not do so, to my taste we should not deserve the
computer at all!
It has already taught us a few lessons, and the one I have chosen to
stress in this talk is the following. We shall do a much better
programming job, provided that we approach the task with a full
appreciation of its tremendous difficulty, provided that we stick to
modest and elegant programming languages, provided that we respect
the intrinsic limitations of the human mind and approach the task as
Very Humble Programmers.
transcribed by
revised 05-Feb-2013