[中英對照] Dijkstra 圖靈獎演講：謙遜的程式設計師 The Humble Programmer by Edsger W. Dijkstra 1972
Dijkstra 是我非常喜歡的一位計算機科學巨擘，雖然他在計算機領域外不是很有名，業內的知名度可能也不及 Turing 和 Knuth，但他對於程式的品味與堅持讓我非常景仰，因此寫了這篇文章，希望有更多人認識他呀。
迪科斯徹 (Edsgar Wybe Dijkstra) 是世界上第一批計算機科學家，荷蘭人，畢業就職於荷蘭 Leiden 大學，早年鑽研物理及數學，而後轉為計算機科學。曾在 1972 年獲得過素有計算機科學界的諾貝爾獎之稱的圖靈獎。
- 發表「goto 有害論」，並提出結構化程式設計，因此稱為結構程式之父。
- 提出號誌 (Semaphore)，號誌其中的用語 P 和 V 來源於荷蘭單詞測試 (Proberen) 和增加 (Verhogen)。
- 迪科斯徹最短路徑演算法 (Dijkstra’s algorithm) 的作者，是利用貪心法 (greedy method) 設計運動路徑規劃演算法的一個成功案例。
- 銀行家演算法 (Banker’s Algorithm) 的作者。
- Algol 60 編譯器的設計者和實作者，以高級語言實現遞迴 (Recursive Programming)。
- THE 操作系統的設計者和開發者。
- 與 D. E. Knuth 並稱為我們這個時代最偉大的計算機科學家。
- 實際上如果一個程式設計師先學了 BASIC，那就很難教會他好的程式設計技術了：作為一個程式設計師，他們的神經已經錯亂了，而且無法康復。
1972 年 Dijkstra 的圖靈獎演講：謙遜的程式設計師 – Youtube 演講音源
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!
在有了三年編程經驗後，我和當時我在阿姆斯特丹數學中心的老板 A. Van Wijngaarden（譯注：荷蘭數學家和計算機科學家），進行了一場討論，關於這場討論我在有生之年都會感激他。討論的焦點在於，我本來是要在編程的同時，在萊頓大學學習理論物理，但是當發現魚和熊掌不可兼得時，我不得不做出選擇，要麼停止編程，成為一個名符其實的可敬的理論物理學家；或者把我的物理學研究敷衍了事，而成為一個…那個叫什麼？程序員？但那是個受人尊敬的職業麼？什麼又是編程呢？它作為一門學科所需要的完備知識體系又在哪裡呢？我非常清晰得記得自己有多嫉妒我從事硬件的同僚們，因為當被問到專業技能時，他們至少可以談自己所知道關於真空管，放大器，和其他一些硬件的一切；而被問到這個問題時，我只能茫然無措。滿心焦慮，我敲開了 Van Wijngaarden 的辦公室大門，問道：「是否能佔用他一點時間」；而在幾個小時後離開他辦公室時，我整個人煥然一新。在耐心聽完我的問題後，他同意當時並沒有學科是關於編程的，但是他接下來解釋說，自動化電腦會繼續發展，而我們正處於摸索階段，那我能不能成為先驅者之一，使編程在未來成為一個受人認可的學科呢？這成了我人生中的一個轉折點，促使我盡快完成了我的物理學研究。上述故事的寓意是，我們必須謹慎地向年輕人提供意見，因為有時他們真的會聽的！
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”!
荷蘭婚禮儀式上有要求新人陳述職業的傳統，而兩年後的 1957 年，當我結婚時我宣告自己是一名程序員。但是阿姆斯特丹的市政當局沒有接受，理由是並不存在程序員這樣一種職業。不管你信不信，在我婚姻證書上「職業」這一欄裡，可笑的寫著「理論物理學家」！
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.
一個小小的原因是：現代計算機在一個或兩個方面比老式的計算機更難以操作。首先，現代計算機有 I/O 中斷，中斷的發生不可預知也不可重現，這個特性與能完全掌控運行過程的舊式計算機相比，是一個巨大的變化，但是這個特性會產生難以預料的邏輯錯誤，很多程序員花白的頭發見證了這一點。第二，現在的計算機配置了多級存儲設備，關於設備管理的策略，雖然已經有大量的文獻，但是對我們來說仍然相當難以捉摸。關於計算機結構的變化所增加的復雜性就講這麼多了。
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.
剛開始的時候，EDSAC 在英國的劍橋興起，我對其起初讓子程序庫在機器設計和使用方法中發揮主要作業的觀點印象深刻。接近 25 年後的今天，計算領域徹底的變化了，但是軟件的基本觀念還伴隨著我們，閉合子程序的觀念也還是我們編程的核心概念之一。我們應該認可閉合子程序作為最偉大的軟件發明之一，它經歷了三代計算機的發展並且仍將繼續存活幾代，因為它迎合了我們基本抽象模式的接口思想。遺憾的是，在第三代計算機的設計中，它的重要性被低估了，而這個設計中，大量明確命名為寄存器的算術計算單位揭示了子程序機制的廣泛使用。盡管如此，也沒有讓子程序的概念就此消失，我們只能祈禱這種變化不會在下一代的計算機中被遺傳。
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.
我要講的第二個軟件業的主要發展是 FORTRAN 的誕生。在當時這是一個偉大而冒失的計劃，負責這個計劃的人們值得我們大聲地贊美。因為大約 10 年後才日漸明顯的外延錯誤用法而去責備他們是顯然不公平的：能夠成功預測十年後的團隊相當罕見。當我們回顧過去時，必須把 FORTRAN 看做一項成功但是對其產生概念基本沒啥幫助的編碼技術，在需求如此迫切的現在，這項技術已經過時了。我們應該盡快忘記 FORTRAN，對於思想的馬車而言，它不再勝任：它浪費了我們的腦力，使用它過於冒險，因此也太過奢侈。FORTRAN 的悲慘命運已經因為它廣泛的接受度，影響了數以千計的程序員為我們過去的錯誤買單。我每天都祈禱，會有更多程序員小伙伴找到從通用性的禍害中解脫出來的方法。
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.
第三個不能忽略的就是 LISP，一個完全與眾不同的迷人設計。基於 LISP 的幾個基本原則使得 LISP 展示出了非凡的健壯性。除此以外，LISP 成為了相當多的復雜計算機載體。LISP 曾經被調侃為濫用電腦的最智能方法。我想這種描述是一種很高的贊美，因為它傳遞了解放的氣息——它已經幫助我們之中最有天賦的人思考了之前不可能思考的東西。
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, a 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.
第四個要提到的就是 ALGOL 60。到目前為止，FORTRAN 程序員仍然傾向於從他們的開發中了解他們的編程語言——八進制的興起和十六進制的衰落；而 LISP 的定義依然是一種令人好奇的混合體，其中包括這門語言意味著什麼和這門機制是怎麼工作的，《算法語言》那篇著名的報告中說道，ALGOL 60 是真正努力去承載抽象概念至關重要的一步，再加上通過獨立於語言之外的方法定義一門編程語言的成果。有人會說，ALGOL 60 的作者們已經如此的成功，以至於他們自己引出這門語言是否可以實現產生的嚴肅疑問！那篇報告冠冕堂皇地展示了 BNF 范式（即現在人盡皆知的 Backs-Naur-Form）的作用，和英語謹慎措辭的力量，至少是像 Peter Naur 一樣聰明的人使用時。我覺得可以負責任地說，基本沒有像它這麼短而在計算機界有相同影響力的文檔存在。人們習慣於使用用「ALGOL」或者是「類 ALGOL」這樣未經保護的標簽，向大量基本不相關的年輕語言分享 ALGOL 的榮耀，這本身某種程度上就是對 ALGOL 驚人生命力的極大致敬。BNF 作為一種嚴格定義的語言，它的長處導致了我個人認為是這門語言的缺點——過分精心制作並且語法定義不規則，很難在幾頁紙中完全說明。如果有個 BNF 般強大的設備，《算術語言》中那篇關於 ALGOL60 的報告可以變得更短很多。除此以外，我對 ALGOL60 的參數機制表示懷疑，它賦予程序員如此多的組合自由，以至於要求程序員更自律。除了開發成本外，它使用起來似乎也很危險。
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.
最後，盡管令人不太愉快，但我必須提及——PL/1，一門描述文檔非常龐大而且復雜的編程語言。使用 PL/1 就像開著一架有著 7000 個按鈕，使用開關和扳手操作的飛機。我完全不能理解怎麼靠智力來把握這種完全怪異的編程語言（我們的基本工具），使之保持穩定的發展，提醒你，這已經脫離我們智力的掌控了。還有如果非要描述 PL/1 對其用戶的影響，我腦海中最為形象的隱喻就是毒品。我記得這個出自一個自稱是 PL/1 的忠實用戶在一個高級語言的專題討論會上做的一個演講。但是，在這個為期一小時充滿對 PL/1 贊美的演講中，他希望大家添加 50 種新特性，卻沒有想過他問題的源頭是這門語言已經包含了太多的特性。演講者展示了所有令人沮喪大的症狀，他陷入內心停滯，但是渴求更多。當 FORTRAN 被稱為嬰兒期的凌亂時，完整的 PL/1 卻是危險的腫瘤，最後成長為了一種致命病毒。
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.
這種想象就是，在七十年代結束之前，我們有可能設計和實現那種盡量利用編程能力，開支是許多年前百分之幾的系統。此外，這些系統可以幾乎擺脫 bug。這兩項提升相輔相成。在後一個方面，軟件看上去和許多其他產品不同，很多產品質量和價格是成正比的。那些想要真正有效的軟件的人將會發現他們必須從找到避免大多數 bug 的方法開始，最後，編程過程將變得便宜。如果你想要一些有能力的程序員，你將發現他們不會浪費時間在調試上，他們不應該以調試 bug 作為開始。換句話說，兩種目標指向同樣的變化。
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.
談到對軟件更為可靠的需求，我表示完全同意。在幾年前，就不一樣了——討論軟件危機是對上帝的褻瀆。轉折點是 1968年十月在 Garmisch 舉行的軟件工程的學術會議，一次萌生了知覺承認軟件危機的回憶。到目前為止，普遍認為任何大型系統的設計都是一項十分困難的工作，無論何時，人們遇到負責這樣工作的人，都會發現他們非常關心可靠性問題。簡而言之，我們第一個條件似乎滿足了。
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.
一份程序結構的研究表明程序，即便是同一個任務的替補程序和有著相同的數學內容，在程序管理方面都有著巨大的差異。研究發現許多規律，違反任何一條規律要麼局部或者整體的破壞程序的人為管理。這些規律不外乎兩種。第一種容易在物理上加以利用，即選用合適的編程語言。Goto 語句的和多輸出參數的程序的剔除是很好的佐證。對於第二種，我至少看不到物理上使之暴露的方法（可能是我能力不足），好像需要一些我沒有證明存在的自動化的定理證明程序。因此，第二種規律時不時作為程序員訓練的要素之一出現。有些規律我清楚的知道以至於可以教給他人和不需要判斷一段給定的程序是否違反了。 我們給出必要的例子——任何循環需要給出終止條件或者聲明不變量之間的關系保證不變量不會被程序的循環語句執行而破壞。
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.
論據三是建立在程序正確性問題的建設性方法上的。今天，一項普通的技術就是寫一個程序，然後去測試。 盡管，程序測試是一種非常有效的方法去暴露 bugs，但對證明不存在 bugs 幾乎是完全沒用的。顯著提高程序可信度唯一有效的方法是給出一個令人信服的關於正確性的證據。但是我們不應該首先寫出程序，然後去證明它的正確性，因為要求證明只會增加苦逼程序員的負擔。相反，程序員應該讓正確性證明和程序相互驗證，發展。論據三本質上是從以下的觀察得來的。如果一個人問自己一個令人信服的證據應該具備什麼，他了解後，寫了一個很好的滿足了證明要求的程序，然後這些關於正確性的擔心變成一種有效的啟發式的指導。當我們把自己限制在智能可控程序時，按照定義，只有這種方法是可行，但這種方法也提供許多有效的方法，讓我們從中挑選一個滿意的。
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.
設計一個程序需要多少人力根據程序的長度判斷，論據四與此相關。曾經有人指出存在一種自然法則告訴我們耗費人力是程序長度的平方。但是謝天謝地，還沒有人能夠證明這種法則。這是因為它需要是假的。我們都知道能夠解決很多問題的推理論證工具稱之為抽象，抽象能力的有效開發可以被認為一個有能力的程序員至關重要的敏捷之一。關於這一點，值得指出抽象的意圖並不是為了模糊本身，而是去創造新的准確語義水平。當然，我曾經嘗試去找到能夠阻止我們抽象機制起作用的基礎原因。但不管我多麼努力，我都找不到任何一個原因。最後，我傾向於假設（直到現在未通過經驗證明）我恰當的抽象化能力，也就是人力需要想象或者理解一個程序的耗費不會根據程序長度按照超過正比例的速度增長。但是這些調查的一個衍生品更有實際意義，實際上，它是我論據四的基礎。衍生品是許多在整個編程過程中扮演重要角色的抽象模式的識別。你了解這些抽象模式足夠多，你就可以就每個模式作報告。這些抽象模式的熟悉和了解讓我幡然醒悟，例如從 BNF 到方向句法編譯，可以用幾分鐘代替幾年的花費。 因此，我把我們最近對重要抽象模式的理解作為論據四。
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 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.
現在說到論據五，它和我們建立在我們思考習慣上的工具的影響有關。我觀察到一種十有八九來源於文藝復興的文化傳統，為了忽略這種影響，需要把人心視為肉體最高自主的主人。 但我一開始分析我和同類的思考習慣時，我得到一個完全不同的結論，不管我喜歡與否，即我們使用的工具和我們用來表達或者記錄我們想法的語言或記號，是決定我們能夠想到什麼的主要因素。對編程影響程序員的思考習慣的分析和腦力是我們幾乎不曾使用的資源的認識，它們給出了從多方面給出不同編程語言優缺點的尺度。一個有能力的程序員能夠意識到他自己腦容量的嚴格尺寸，因此，他謙遜的完成編程任務，牽涉到其他事情時，他避免小聰明像躲避瘟疫一樣。說到一種著名的會話式程序設計技術，我從不同渠道被告知說如果一個計算社區一旦裝備終端，一種特殊的現象就會發生，這種現象甚至有了一個被廣泛接受的名稱——打趣的人。它有一到兩種不同的形式，一個程序員在別人桌面放了一個調侃的程序，他要麼驕傲的展示它的用途並問別人你能用更少的字符寫完嗎（好像有任何概念的相關性一樣），要麼就問說猜猜這是用來干嘛的。通過這個觀察，我們必須總結說這門語言是一種宣揚奇技淫巧的工具，同時這會是它的一些訴求的解釋，例如說那些喜歡展示他們有多聰明的人，對不起，但是我必須把它視作關於編程語言最令人惡心的地方。我們必須從過去學到的另外一課是所謂功能強大，豐富的編程語言的發展是一種錯誤，就像這些奇怪龐然大物，某人特有的氣質的聚集，都是心靈上，肉體上不可控的。我從系統的謙遜的編程語言上看到很美好的未來。 當我說謙遜時，我的意思是，例如，不僅是 ALGOL60 的 for 分支語句，還有 FORTRAN 的 DO 循環語句發現因為變得過於怪異而被淘汰。我曾經和一些有經驗的志願者做過一點編程實驗，但有些不期望發生和預料不到的事情發生了。我的志願者沒有一個找到明顯而漂亮的解決方法。通過更為細致的觀察，我們找到相同的源頭：他們對與重復的概念與用於加速的聯合控制變量的聯系過於緊密，以至於他們被蒙蔽了完全看不到明顯的方法。他們的方法低效，晦澀難懂，並且耗費了大量時間。這是一段對我來說具有啟示作用，和令人震驚的經歷。最後，從某個方面上來講，如果一個人希望明天的編程語言和現在的大為不同，很大程度的優於現在的，他們應該邀請我們在我們寫下的所有需要用來應付概念上我們如今設計的抽象結構中思考。關於我們未來工具的優越性，也就是我們第五個論據的基礎，就講到這裡。
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!
讓我總結一下。計算機已經伴隨我們走過一個世紀的四分之一了。它們以工具的身份對我們社會產生了深遠的影響，但是和在人類歷史上史無前例的以智力挑戰的形式產生深遠的影響相比，它們只能以波浪的形式影響我們文化的表面。似乎擁有決定在某種程度上將物體視作一個不可分割整體的權利的分層系統，被視作一個級別更低，細節更多的混合物，最後，當我們將注意力從一級轉向更低一級時，時空的天然粒面會以合適的數量級減少。 我們知道牆以磚為單位，磚以結晶體為單位，結晶體以分子為單位，等等。在分層系統中，許多級別可以有意義的區分出來，這和最大與最小粒度的比率的對數成正比，因此，除非比率很大，我們不能指望能夠分很多層。在計算機編程中，我們基本的編程語句有低於一微秒的時間粒度，但我們的程序卻可能花費幾小時的計算時間。我不知道任何一種超過 10 的 10 次方的比率的技術，以它超凡速度為優點的計算機，似乎是第一個給我們提供需要分層粒度大和實現它的環境的。這樣的挑戰，即面對編程任務，是獨一無二的，因此這樣小說一般的經歷可以教會我們很多關於自己的知識。它加深了我們對設計和創造程序的理解，它幫助我們更好的完成想法條理化的任務。如果它沒有這樣做，對我來說，我們根本不值得擁有計算機。
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.
ACM Turing Lecture 1972 EWD340 The Humble Programmer by Edsger W. Dijkstra
1972 年 Dijkstra 的圖靈獎演講：謙遜的程序員
計算機科學名人堂：Edsger Wybe Dijkstra
Dijkstra, ALGOL 60, 與 van Wijngaarden