bertrand@eiffel.UUCP (Bertrand Meyer) (06/05/89)
On the evolution of programming languages, with particular attention to the evolution of Eiffel Bertrand Meyer, June 4-5, 1989 This draft note is based on ideas presented at the International Eiffel Conference in Paris on April 21. From the initial design to the asymptote The programming literature contains quite a few references on the subject of programming language design. A seminal article, more quoted than heeded, is Hoare's ``Hints on Programming Language Design'' (POPL 1973). The subject of evolution after initial design has received less attention. Here are a few thoughts and their application to Eiffel. A key criterion in language design is simplicity of the result. Even if initially satisfied, this property is difficult to maintain in light of increased usage of the language by diverse groups tackling varied applications. The standard counter-example - target of the most frequent cheap shots - is PL/I, commonly blasted for its complexity. If you want to get an easy laugh out of an audience of computer scientists, or to williehorton someone else's design, evoking PL/I is a sure win. Abusing this not-too-young language is not wholly unfair but rather facile. I see much worse horror stories in languages that initially were reasonably small but then started to develop carcinomatous cells in all directions. How can we reconcile the demands of large-scale software development, and the myriad practical problems which they raise, with the constant concern for maintained simplicity and consistency? To compound the difficulty, the topic of programming languages and their design seems to provoke an inordinate number of suggestions from a group - software engineers - of inordinately opinionated people. It is striking to see how many of these ideas are in fact excellent; but this does not mean that they should all be included! First they may raise subtle or major incompatibilities with other language features; but even if this is not the case they most often will make the language more complex. In each case the designer must weigh the evidence: is the purported benefit really worth the increase in complexity? I have found that in nine out of ten cases the answer is no. Again this usually is no reflection on the quality of the idea. But the designer's primary responsibility is to keep in mind the elegance of the overall picture. In the current state of Eiffel (and I assume this applies to any recent language that is now at a similar stage of its development), there is one other and totally new element, incredibly exciting and at the same time somewhat frightening: the net. Electronic mail and forums such as this one mean that hundreds of people can react in a few hours to the latest announcements, ideas, proposals, opinions and suggestions. For Eiffel this has been a tremendous benefit. The number of people who have sent public or (more often) private comments is incomparably greater than what it would have been just a few years ago. Even Ada, undoubtedly the language most widely and thoroughly debated before its final design, was born before network access became available on a grand scale, and did not benefit from the unique combination of breadth, depth and timeliness made possible by the technology of the late nineteen-eighties. The contribution of the net has been considerable. (To add a personal note, let me use this opportunity to apologize to all the people who wrote to me recently and got no answers. I simply cannot keep up with my mail these days, and I am not too good at sending polite ``pro forma'' answers. I do read carefully everything that gets to me, however.) Add to that co-workers, users, course participants, colleagues in panels at conferences, and you get a constant influx of new ideas. What can one do in such a context? The best tactics I know is to say ``no'', bury one's head in the sand and emerge some time later to see if there is still anyone around. This is not arrogance but preservation of one's mental sanity. For Eiffel, the basic policy is utmost conservatism. Do not change anything unless you cannot find any more arguments for the status quo. Because of this, Eiffel is still extremely close to the language which was designed in early September of 1985. But saying ``no'' most of the time is not an excuse for not listening. *Almost any single criticism or suggestion contains something useful for the language designer*. This includes comments by novices as well as expert users. But most of the time you must go beyond what the comment says. In particular you must usually see through a ``solution'' that is suggested to you, and understand what it obscures: the real problem. Finding the solution is your responsibility, the one you cannot abdicate. Integrity of the entire design can only be achieved and maintained by one person or a small group, for whom the language is not just a means but also an end. The users and critics see many things that you don't; they (the users at least) are the ones who have to live with the language day in and day out. But you can't expect them to do your job. (Sometimes, of course, they do: someone will come up with just the right suggestion. Then you can be really grateful.) So there are deep and shallow comments but almost no useless ones. Sometimes the solution simply resides in better documentation. Often it lies in a tool, not in any language change. Extensions through the library In a language supporting libraries, it is often possible and desirable to provide a new feature through a library facility rather than through a language change. For example, Eiffel 2.2 facilities such as the ``out'' function (which produces a printable image of any value or object) or the ``copy'' and ``deep_copy'' procedures (which copy any object), although initially envisioned as language additions, were in fact implemented as normal features in a standard library class, ANY, now inherited by every class. A cynic might question the benefit of extending the library to keep the language simple. Indeed, tough problems of consistency and simplicity (discussed in previous messages) do arise for the library. There is an important difference, however: one of level. The library as well as any user application are defined with respect to the basis provided by the language. Because everything else relies on it, this basis must be kept simple at all costs. Undue complexity in the library should be avoided, but the consequences are less grave. Mathematical theories provide the appropriate comparison. Adding a language construct is like adding an axiom, certainly not a decision to be taken lightly. Adding a library class or routine is simply like adding another theorem, inferred from the current axioms. Changing the language When everything else fails, the language is really under fire. Something must be done. When this happens - and only as a last resort - the tough conservative temporarily softens his stance. There are two cases, which are really different: extending the language and (supreme horror) invalidating an existing part. They will be addressed separately. Extensions Extensions are the language designer's secret vice, the dieter's chocolate mousse on the evening of his birthday, the key that is available for just one night to open the chastity belt. After much remonstrance and lobbying you finally realize what many users of the language had known for a long time: that some useful type of computation is harder to express than it should be. You know it's extension season. There is one and only one kind of acceptable language extension, and that is the extension that dawns on you with the sudden self-evidence of morning mist. You may get the idea yourself (and that is good for your ego) while brushing your teeth and thinking of something else; or (more often) it may be suggested out of the blue by someone else at the end of a three-hour meetings - one among a seemingly endless series of such meetings. All were bored and tired and thinking about home, but suddenly everyone knows that the solution is there and everyone asks: ``But why didn't we think of it before?'' For most often the simplest idea is the last one to suggest itself. But when it is indeed *the* solution, then no doubt remains. It must be simple, elegant, explainable to any competent user of the language in a minute or two. It must provide a complete solution to a real problem. It must fit perfectly within the spirit and letter of the rest of the language; almost always, in fact, it will unexpectedly solve one or more other problems. It must not have any dark sides or raise any unanswerable questions. And because software engineering is engineering, and unimplemented ideas are worth little more than the whiteboard marker with serves to sketch them, you must see the implementation technique. The implementors' group in the corner of the room is grumbling, of course - how good would a nongrumbling implementor be? - but you and they see that they can do it. When this happens, then there is only one thing to do: go home and forget about it all until the next morning. For in most cases it will be a false alarm. It it still looks good after a whole night, then the current month may not have been lost altogether. Introducing incompatibilities What happens if you realize that some existing language feature, that may be used by thousands of applications out in the field could have been designed better? Obviously, unless this occurs extremely rarely, the language and its designer are in trouble. We have been fortunate in the history of Eiffel to have mostly been preserved from such unpleasant situations. Yet sooner or later one is bound to occur. Recently, for example, we have come to realize that the syntax for object creation in Eiffel could be made more elegant, with a clear if small semantic benefit. This is an interesting case because (fortunately!) the change is not essential. A decision either way will have no major impact on the language's progress and on the users' ability to tackle any particular problem. The change would just make their lives somewhat easier in some specific cases, and the overall language design more clean. (The particular language issue alluded here will be described in a message to be posted by mid-July, and there will be ample time for discussion before anything is cast in concrete. Although design by vote is clearly an absurd idea, no change to existing constructs should ever be implemented without a broad airing of educated opinions.) What do you do in such a case? The accepted wisdom is to forget about it. This is also the path of least resistance. A previous message (about the libraries) talked about the GAIB (Guardian Angel of the Installed Base) and the DECHOP (Devil of Eternal Compatibility with the Horrors of the Past), whose constant advice is to preserve the tranquillity of current users. The long-term price, however, is languages that carry forever the ugly remnants of another age. I tend to go for the other policy, which says: if really you have made a mistake, then admit it and correct it; and the sooner the better. A number of stringent conditions must be satisfied: + There must be wide agreement that the new solution is significantly better than the original one. It must not entail any negative consequence other than its incompatibility. + The implementors MUST provide an automatic conversion mechanism for existing software. This is an essential requirement, for which the only acceptable exception seems to be the introduction of a new keyword. (Here the incompatibility is for programs that used the keyword as identifier. Unless the keyword is one that is known to be commonly chosen as identifier, it seems acceptable to rely on programmers to perform any needed changes in their software.) + Everything must be synchronized: software with the new feature, documentation, etc. If these conditions are met, then I believe one should cut one's losses and go ahead with the change. The Eiffel perspective Where does Eiffel stand in the language design and evolution cycle, and where is it going? The general feeling of the participants at the recent Paris Conference seemed to be that the language is basically all right as it is. It was particularly interesting that this opinion was expressed by the presenter of a paper that described a 2,000-class, 350,000-line application (who otherwise criticized several aspects of the current implementation). Criticisms and suggestions pertaining to the language were expressed, of course, by various presenters; but it was comforting to see that most of them were appropriately addressed by the 2.2 extensions. My biased view is that the basic language will not change much from now. Especially with 2.2, it is hard to see what important facility might still be lacking. (The question of parallelism is not covered in this analysis. There will be a posting on this soon.) Version 3.0, scheduled for the end of this year, should provide an opportunity to clean up a few points, as mentioned above. No significant extension is planned at present. [Incidentally, some people reading these lines might be surprised at the lack of reference so far to alleged problems with type safety in Eiffel, mentioned in postings to this group and even in a paper at the forthcoming ECOOP conference. But contrary to what has been asserted there is no type consistency problem in the language. Two problems are: (1) Rare but real errors that are not caught by the current implementation. (2) Insufficient explanations in my OOSC book, and delays in the paper I announced on the subject. There was no time to fix these problems for 2.2, but they will be corrected for the next release.] My hope is that with 3.0 the base language will be close to the asymptote. This, incidentally, means that if you really feel strongly about some aspects of Eiffel the summer and early Fall of 1989 are the right time to make your voice heard. What happens next? In the software field, predictions beyond six months tend to be wishful thinking at best. What I would hope to see is a stable language not directly under Interactive's sole technical control. (This, by the way, is strictly a discussion of technical issues and does not address any proprietary, trademark or other non-technical concerns.) Until the end of this year it seems appropriate that Interactive, and more specifically I, should remain ``in charge'' technically. But after that a measure of success will be our ability to transfer control over the language's evolution to some other body. What this body will be I do not know; perhaps a standardizing committee, or some implementors' council. My colleagues and I would undoubtedly play an active role but would by no means be the only members. To end with a personal note, let me thank all those who corresponded with us during the past few months and helped shape version 2.2. The quality of the interaction has been tremendous and I learned a lot. I take all the blame for the deficiencies, of course, but it is appropriate to express my gratitude to, among many others (and not counting employees of Interactive), John Anderson, David Butler, Paul Dubois, Serge Granik, Jim Gish, Roger Rousseau, Andreas Schramm, Norman Shelley, Erland Sommarskog. I have that unescapable feeling that as soon as I have posted this I will remember the key names that I forgot. Please accept my apologies in advance and blame the omissions on the author's incurable absent-mindedness. -- -- Bertrand Meyer bertrand@eiffel.com