ETC/알고리즘 이론

Edgher W. Dijkstra - Go To Statement Considered Harmful 을 읽고.

지과쌤 2020. 5. 26.
반응형

https://web.archive.org/web/20070703050443/http://www.acm.org/classics/oct95/

 

Go To Statement Considered Harmful

380 captures 20 Dec 1996 - 05 May 2020

web.archive.org

Go To Statement Considered Harmful
Edsger W. Dijkstra


Reprinted from Communications of the ACM, Vol. 11, No. 3, March 1968, pp. 147-148. Copyright © 1968, Association for Computing Machinery, Inc.

This is a digitized copy derived from an ACM copyrighted work. It is not guaranteed to be an accurate copy of the author's original work.


Key Words and Phrases:go to statement, jump instruction, branch instruction, conditional clause, alternative clause, repetitive clause, program intelligibility, program sequencingCR Categories:4.22, 6.23, 5.24

Editor:

For a number of years I have been familiar with the observation that the quality of programmers is a decreasing function of the density of go to statements in the programs they produce. More recently I discovered why the use of the go to statement has such disastrous effects, and I became convinced that the go to statement should be abolished from all "higher level" programming languages (i.e. everything except, perhaps, plain machine code). At that time I did not attach too much importance to this discovery; I now submit my considerations for publication because in very recent discussions in which the subject turned up, I have been urged to do so.

My first remark is that, although the programmer's activity ends when he has constructed a correct program, the process taking place under control of his program is the true subject matter of his activity, for it is this process that has to accomplish the desired effect; it is this process that in its dynamic behavior has to satisfy the desired specifications. Yet, once the program has been made, the "making' of the corresponding process is delegated to the machine.

My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.

Let us now consider how we can characterize the progress of a process. (You may think about this question in a very concrete manner: suppose that a process, considered as a time succession of actions, is stopped after an arbitrary action, what data do we have to fix in order that we can redo the process until the very same point?) If the program text is a pure concatenation of, say, assignment statements (for the purpose of this discussion regarded as the descriptions of single actions) it is sufficient to point in the program text to a point between two successive action descriptions. (In the absence of go to statements I can permit myself the syntactic ambiguity in the last three words of the previous sentence: if we parse them as "successive (action descriptions)" we mean successive in text space; if we parse as "(successive action) descriptions" we mean successive in time.) Let us call such a pointer to a suitable place in the text a "textual index."

When we include conditional clauses (if B then A), alternative clauses (if B then A1 else A2), choice clauses as introduced by C. A. R. Hoare (case[i] of (A1, A2,···, An)),or conditional expressions as introduced by J. McCarthy (B1 -> E1, B2 -> E2, ···, Bn -> En), the fact remains that the progress of the process remains characterized by a single textual index.

As soon as we include in our language procedures we must admit that a single textual index is no longer sufficient. In the case that a textual index points to the interior of a procedure body the dynamic progress is only characterized when we also give to which call of the procedure we refer. With the inclusion of procedures we can characterize the progress of the process via a sequence of textual indices, the length of this sequence being equal to the dynamic depth of procedure calling.

Let us now consider repetition clauses (like, while B repeat A or repeat A until B). Logically speaking, such clauses are now superfluous, because we can express repetition with the aid of recursive procedures. For reasons of realism I don't wish to exclude them: on the one hand, repetition clauses can be implemented quite comfortably with present day finite equipment; on the other hand, the reasoning pattern known as "induction" makes us well equipped to retain our intellectual grasp on the processes generated by repetition clauses. With the inclusion of the repetition clauses textual indices are no longer sufficient to describe the dynamic progress of the process. With each entry into a repetition clause, however, we can associate a so-called "dynamic index," inexorably counting the ordinal number of the corresponding current repetition. As repetition clauses (just as procedure calls) may be applied nestedly, we find that now the progress of the process can always be uniquely characterized by a (mixed) sequence of textual and/or dynamic indices.

The main point is that the values of these indices are outside programmer's control; they are generated (either by the write-up of his program or by the dynamic evolution of the process) whether he wishes or not. They provide independent coordinates in which to describe the progress of the process.

Why do we need such independent coordinates? The reason is - and this seems to be inherent to sequential processes - that we can interpret the value of a variable only with respect to the progress of the process. If we wish to count the number, n say, of people in an initially empty room, we can achieve this by increasing n by one whenever we see someone entering the room. In the in-between moment that we have observed someone entering the room but have not yet performed the subsequent increase of n, its value equals the number of people in the room minus one!

The unbridled use of the go to statement has an immediate consequence that it becomes terribly hard to find a meaningful set of coordinates in which to describe the process progress. Usually, people take into account as well the values of some well chosen variables, but this is out of the question because it is relative to the progress that the meaning of these values is to be understood! With the go to statement one can, of course, still describe the progress uniquely by a counter counting the number of actions performed since program start (viz. a kind of normalized clock). The difficulty is that such a coordinate, although unique, is utterly unhelpful. In such a coordinate system it becomes an extremely complicated affair to define all those points of progress where, say, n equals the number of persons in the room minus one!

The go to statement as it stands is just too primitive; it is too much an invitation to make a mess of one's program. One can regard and appreciate the clauses considered as bridling its use. I do not claim that the clauses mentioned are exhaustive in the sense that they will satisfy all needs, but whatever clauses are suggested (e.g. abortion clauses) they should satisfy the requirement that a programmer independent coordinate system can be maintained to describe the process in a helpful and manageable way.

It is hard to end this with a fair acknowledgment. Am I to judge by whom my thinking has been influenced? It is fairly obvious that I am not uninfluenced by Peter Landin and Christopher Strachey. Finally I should like to record (as I remember it quite distinctly) how Heinz Zemanek at the pre-ALGOL meeting in early 1959 in Copenhagen quite explicitly expressed his doubts whether the go to statement should be treated on equal syntactic footing with the assignment statement. To a modest extent I blame myself for not having then drawn the consequences of his remark

The remark about the undesirability of the go to statement is far from new. I remember having read the explicit recommendation to restrict the use of the go to statement to alarm exits, but I have not been able to trace it; presumably, it has been made by C. A. R. Hoare. In [1, Sec. 3.2.1.] Wirth and Hoare together make a remark in the same direction in motivating the case construction: "Like the conditional, it mirrors the dynamic structure of a program more clearly than go to statements and switches, and it eliminates the need for introducing a large number of labels in the program."

In [2] Guiseppe Jacopini seems to have proved the (logical) superfluousness of the go to statement. The exercise to translate an arbitrary flow diagram more or less mechanically into a jump-less one, however, is not to be recommended. Then the resulting flow diagram cannot be expected to be more transparent than the original one.

References:

  1. Wirth, Niklaus, and Hoare C. A. R. A contribution to the development of ALGOL. Comm. ACM 9 (June 1966), 413-432.
  2. BÖhm, Corrado, and Jacopini Guiseppe. Flow diagrams, Turing machines and languages with only two formation rules. Comm. ACM 9 (May 1966), 366-371.

Edsger W. Dijkstra
Technological University
Eindhoven, The Netherlands

 

전공 수업인 프로그래밍 언어 과제로 읽게 된 논문이다.

 

보통 복잡하고 보기 어려운 코드를 거시적으로 본다면 “와 저사람 코딩좀 하는데? 멋있는데?” 이렇게 생각하기 마련이다. 하지만 복잡하고 긴 코드보다 간결하지만 굉장히 논리적이고 또 구조적으로도 한눈에 알아보기 쉬운 코드가 정말 좋은 코드 라고 할 수 있다.
프로그래밍을 구조적으로 한다는 것. 즉 구조적 프로그래밍은 프로그래머가 단순히 논리적이고 효율적인 프로그램을 작성하는 것 뿐만 아니라 그 논리와 효율을 납득 가능한 절차로 증명해야한다는것 이 두 가지가 한번에 시행되어야한다는 것이 아닐까 생각된다. 논문에 나왔던것처럼 정적 프로그램(프로그래머가 디자인하는 행위. 코딩)과 동적 프로세스(기계가 동작하는 것) 사이의 격차를 최대한 줄여 프로그래밍과 프로세싱 사이의 간극을 최소한으로 한다는 것 이것이 바로 구조적 프로그래밍인것같다.

Dijkstra는 고급 언어에서 Go-to문을 제거함으로써 코드의 질을 높여야한다고 주장하였다. 프로그래머가 잘 디자인(코딩)한 프로그램이여도 프로세싱 자체는 기계가 하기 때문에 인간의 사고방식과 기계의 프로세싱 방식에는 차이가 있을 수 밖에 없다 하였는데, 이 말은 위에서 언급한 구조적 프로그래밍의 당위성이 아닐까 싶다.
Dijkstra는 progress of a process – characterize 에 관해서도 언급하였다. text의 적당한 위치의 포인터를 가르켜 “texture index” 라고 부르자고 하였고, if문의 경우 프로세싱이 단일 texture index로 characterize 하였다. 그리고 while문 같은 경우엔 중첩하여 적용이 가능하므로 texture index + dynamic index 로 characterize 하였다. 
중요한 것은 이러한것들을 프로그래머가 통제하기 힘들다는것이다. 프로세싱은 원하던 원하지 않던 생성되고, 프로세스의 진행 상황을 나타내기 위해 독립적인 좌표를 제공하게 된다. 

Go-to문은 조건이 포함된 분기나 반복 등을 쉽고 간단하게 사용할 수 있다는 장점이 있지만, 프로그램을 전체적으로 복잡하게 만들어버린다는 단점이 있다. 다시말해, Go-to문은 프로세싱 중 작업을 카운팅하여 어느정도 직관적으로 작업을 볼 수 있지만, 무분별한 Go-to문은 모듈을 더 작은 단위로 나누는 과정에서 복잡하게 만들고 특정 데이터를 찾기 힘들어지게 한다. 즉 전체적인 프로그램 구조로 보았을 때, 복잡하고 어렵게 만드는 것이다.

본 논문을 읽고 Go-to문이 프로그래밍에 어떤 영향을 끼치는지 알 수 있었고, 구조적 프로그래밍을 통해 프로그래머가 더 규모가 큰 시스템을 구조적으로 나누어 결과적으로 더 좋은 효과를 준다는 것을 알 수 있었다. 다시말해 구조적 프로그래밍은 효율적으로 기능을 나누고 테스트를 하거나 특정 시점에서 특정 결과를 도출해낼 때 굉장히 쉽고 효율적으로 도출 가능하게 해준다는 점에서 굉장히 좋은 방식이라고 생각하게 되었다. 그리고 단순히 프로그래머의 입장에서만 코딩을 하는게 아닌, 기계의 입장에서 프로세싱도 고려해야 좀더 좋은 프로그램을 만들 수 있겠다는 생각을 하게 되었다.

 

 

반응형

댓글

💲 추천 글