今天在《程序员》杂志2005年12期里看到了Charles Petzold 的《Visual Studio 会侵蚀我们的思想吗?》一文,觉得有一些道理。但是文章里有些东西翻译得不是很清楚,就到Google上查到了原文出处,在Charles Petzold 的网站上 http://charlespetzold.com/etc/DoesVisualStudioRotTheMind.html:
Does Visual Studio Rot the Mind?
Ruminations on the Psychology and Aesthetics of Coding
By Charles Petzold
A Talk Delivered at the NYC .NET Developer’s Group, October 20, 2005
Abstract: Visual Studio can be one of the programmer's best friends, but over the years it has become increasingly pushy, domineering, and suffering from unsettling control issues. Should we just surrender to Visual Studio's insistence on writing our code for us? Or is Visual Studio sapping our programming intelligence rather than augmenting it? This talk dissects the code generated by Visual Studio; analyzes the appalling programming practices it perpetuates; rhapsodizes about the joys, frustrations, and satisfactions of unassisted coding; and speculates about the radical changes that Avalon will bring.
I don’t speak to user groups or developer groups very often, partially because of a bad experience I had a number of years ago. In 1991, the Boston Computer Society invited me to speak on the subject of Windows programming. Since I had written a book on Windows programming — the 2nd edition of Programming Windows had been published just the previous year — I figured I didn’t really need to talk about that. Anybody who wanted to learn Windows programming could simply buy the book and read it in the privacy of their homes.
Instead, I decided to talk about something that people could not read about in my book. This was a subject that interested me at the time, which was how Microsoft first developed Windows, and how Microsoft and IBM then got involved in the development of OS/2, how Microsoft had convinced IBM to go graphical in the windowing environment, and how IBM decided they wanted to develop an entirely new API, and then how the success of Windows led to the eventual split between Microsoft and IBM.
Well, people went berserk. I suppose they had been expecting me to tell them everything they needed to know about Windows programming in the space of a few hours, and that’s certainly not what I was interested in doing.
That was a very traumatic experience for me, and since that time, I have been reticent about speaking before groups like this. This is a .NET developer’s group. I have written four books on .NET programming — the fourth is due out on November 2nd — and anybody who wants to read them is free to do so. I am now in the process of writing a book on the Windows Presentation Foundation (formerly code-named Avalon) but couldn’t at this time really tell you a whole lot that’s useful.
So when Bill and Andrew and Stephen asked me to speak here, I was initially reticent until I was told — and I quote from Andrew’s email — “we'd happily go to great lengths to accommodate you and your topic preference, even if your preference is no particular topic at all.” This evening I do have a topic, although it’s a rather odd one, and I hope nobody will go berserk.
Computers in the Movies
I recently re-watched what I believe to be the first Hollywood movie to deal with computers in a major way. This is the movie Desk Set. It’s 1957, and Katherine Hepburn supervises three other women in the research department of the Federal Broadcasting Company. Whenever somebody has a question requiring research, they call up on the phone, and Hepburn and her team get to work on the answer.
Enter Spencer Tracy, a self-described Methods Engineer and the inventor of an “electronic brain” called the Electro-Magnetic Memory and Research Arithmetical Calculator or EMERAC—“Emmy” for short.
Well, naturally, everybody in the research department assumes they’re going to be fired, just like what happened in payroll when an “electronic brain” was installed there. Although it’s expressed here as a nervous humor, this plot line reflected a real anxiety at the time. Of course, workers didn’t really think that an entire computer was necessary to do their job. No, people instead joked that they were going to be replaced by a single button.
Emmy the “electronic brain” turns out to be quite a sophisticated computer. It understands natural language questions typed from a keyboard, and prints the answers on a teletypewriter. Of course, the computer can’t match the cool professionalism of Katherine Hepburn and her staff, and when confronted with a tough question, it reacts in ways we’re all familiar with from subsequent movie computers: It makes funny noises, smoke starts pouring out, and it begins spitting Hollerith cards all over the office.
It must have been funny at the time, even for people who knew that computers don’t break down that way in real life. I have been programming pretty steadily for about 30 years now, and only once have I seen a computer fail in a way I’d classify as “interesting.”1
Meanwhile, the “electronic brain” installed in payroll starts printing pink slips for everybody in the company. As we all know, once computers take over, they no longer need humans. But, as you may anticipate, the human staff is then allowed to come to the rescue and display its superiority over the machine.
Because Desk Set is a Hollywood romantic comedy, and perhaps because IBM supplied all the hardware for the film, human and machine are reconciled at the end. The computer’s role is clarified. It exists merely to assist the humans in their research needs.
The idea of computers trying to “take over” their human creators has been replayed in dozens of movies ever since. Sometimes the computers take a leap into a level of intelligence and consciousness their designers had not anticipated, or perhaps they suffer the computer version of a “nervous breakdown,” or they’re simply too damn logical for their own good. Sometimes the computer goes so haywire that it does something that no sane human would ever dream of doing — such as starting a war.
Just a few examples2: 2001: A Space Odyssey (1968). Good computer; bad choices. Colossus: the Forbin Project (1970). American super-computer demands to be connected to Russian super-computer, with expected consequences. As the movie’s tag line put it, “We built a super computer with a mind of its own and now we must fight it for the world!”3
Ira Levin’s novel This Perfect Day from 1970 isn’t a movie of course, but it should be. A computer runs the world and a few brave souls conspire to defeat it, only to discover… well, this is an Ira Levin novel so it’s best that you be a little surprised. This Perfect Day. Check it out.
Many of the human vs. computer themes show up in WarGames (1983), and even this past summer, Hollywood squeezed out a little cinematic turd called Stealth, which my favorite newspaper The Onion hailed as “the most chilling look at artificial intelligence run amok since Short Circuit 2.”4
Of course, it’s easy today to see how ridiculous this stuff is. For example, we have erected a vast network of computers around the world, and it has yet to exhibit the slightest degree of intrinsic intelligence. It’s fairly easy to imagine the whole thing collapsing, or getting infected with some virus, but not so easy to imagine it deviously turning against us. What the Internet seems to do best is make commonly available enormously vast resources of mis-information that we never knew existed.
In thinking about how computers and people interact, I find some older, pre-computer, movies to be more relevant — the ones where people who work with machines and automated processes become subservient to the rhythm of the machine. I’m thinking of Fritz Lang’s Metropolis (1927), where an odd feedback system requires people to run the machines by responding to their commands. The opening scenes of Charlie Chaplin’s Modern Times (1936) are still very funny, and let’s not forget the famous episode of I Love Lucy called “Job Switching” (1952), the one where Lucy gets a job at the candy factory.
Although these scenes are often played for laughs, they seem to reflect our fear of being forced into a dehumanizing relationship with a machine that imposes its jerky digital rhythm on our normally analogue souls. These encounters leave an imprint on both minds and our bodies. In I Am a Fugitive from a Slave Gang (1932), a convict who is set free from the chain gang walks away still shuffling his feet as if his ankles are still bound with the chains. Similarly, four years later in Modern Times, Chaplin walks home from work with his arms still twitching in the rhythm of the machine.
Technological Addictions
When using our computers, something a little different happens. Of course, we may get repetitive stress disorders from the keyboard or mouse, but software doesn’t affect our bodies as much as our minds, and even then in subtle ways.
Some observers of our digital lives have noticed the way in which certain applications cause a user to think in very rigid prescribed ways, and these are not good. One of the biggest offenders, of course, is PowerPoint. Start putting what you want to communicate in PowerPoint slides, and everything you want to say is ordered into half a dozen bullet items.
The critiques of technology we see in the movies seem to use metaphors of power or slavery. I think there’s a more proper metaphor for our relationships with much of modern consumer technology, however, and that metaphor is addiction.
It is very common for us to say about a piece of consumer technology that “we didn’t know how much we needed it until we had it,” and much of this technology seems targeted not to satisfy a particular need, but to get us hooked on something else we never knew we needed; not to make our lives better, but to tempt us with another designer drug. “I can’t live without my ___________” and you can fill in the blank. This week, I think, it’s the video iPod.
Even useful items like cell phones seem to fit this model. Was the cell phone wasn’t invented to fill a particular need? I’m not sure. It probably wasn’t the case of someone sitting on M14 bus thinking “I’m bored. I wish I could call up my friends from this bus.” It was partially invented because it was possible to do it, and there was a trust that people eventually would not be able to live without them. Once we get the taste, we’re hooked.
I often wish that email had never been invented, but there’s just no way I can get rid of it. So, day after day, several times a day, I dutifully delete 99% of the emails I receive, and when I’m not able to get at my email for a few days, I’ll leave the machine at home running to pick it up every 10 minutes so I don’t overflow some capacity somewhere, and just the other day I caught myself wondering who will clean out my Inbox after I’m dead.
We see computer technologies going through a life cycle where they turn from beneficial to evil. I recently installed something from a Microsoft site that dutifully gave me instructions about clicking the yellow bar at the top of Internet Explorer — the yellow bar that is now protecting us from popups and other bad stuff coming through — so I could bypass the normal protection against the installation of Active X controls. The instructions go on to tell you to ignore all the warnings Windows will then provide about installing this Active X control, because this particular one, unlike all the others, actually does a good thing.
The Nuisance of Information at Your Fingertips
Sometime in the early 1990s, Microsoft came up with the slogan “Information at your Fingertips.” It sounds pretty good in theory, and today we basically have a whole lot of information at our fingertips, what with Google and Wikipedia and the Internet Movie Database and other useful sites.
But information too has become an addiction. I don’t know what it’s like at your house, but we can’t even watch a simple rerun of Friends without one of us saying “Who’s that actress playing Joey’s girlfriend? She looks familiar.” We then click the Info button on the remote to get the title of the particular episode, and then go to tvtome.com or epguides.com to learn the identity of the actress, and then perhaps to Internet Movie Database to see a list of the movies, TV shows, and guest appearances she’s done, and perhaps for one of the movies we’ll say “I always wanted to see that movie” and so we add it to our NetFlix queue.
Of course, we can do all this without actually leaving the couch. Why else would we need WiFi in a 400 square foot studio apartment?
Now I know that five or ten years from now we’ll be able to perform this entire operation entirely from the cable remote, which may actually be a computer remote, including pausing the episode of Friends to download the movie in which the actress playing Joey’s girlfriend appears, and watch it on demand, and then go back to the episode of Friends we were watching if we so desire. And I might be more thrilled at this prospect if I thought it would make us better, happier, nicer human beings. But that’s not immediately obvious to me.
And I sincerely hope that in five or ten years from now, we’re not still watching reruns of Friends.
Although we here in this room are computer users and we are thus stuck with the same annoyances, distractions, and addictions as all computer users, we are also developers and programmers, and for us, the computing experience should be intrinsically different. Programming is the most empowering thing we can do on a computer, and that’s what we do. We write the code that makes the whole world sing.
And yet, if all of us in this room are .NET developers, then we are also undoubtedly Visual Studio users. I suspect some of us have been playing around with betas of Visual Studio 2005, and awaiting its official release at DevConnections in Las Vegas in a few weeks.
Life without Visual Studio is unimaginable, and yet, no less than PowerPoint, Visual Studio causes us to do our jobs in various predefined ways, and I, for one, would be much happier if Visual Studio did much less than what it does. Certain features in Visual Studio are supposed to make us more productive, and yet for me, they seem to denigrate and degrade the programming experience.
API Proliferation
Twenty years ago, in November 1985, Windows 1.0 debuted with approximately 400 documented function calls.5 Ten years later, Windows 95 had well over a thousand.6
Today we are ready for the official release of the .NET Framework 2.0. Tabulating only MSCORLIB.DLL and those assemblies that begin with word System, we have over 5,000 public classes that include over 45,000 public methods and 15,000 public properties, not counting those methods and properties that are inherited and not overridden. A book that simply listed the names, return values, and arguments of these methods and properties, one per line, would be about a thousand pages long.
If you wrote each of those 60,000 properties and methods on a 3-by-5 index card with a little description of what it did, you’d have a stack that totaled 40 feet.7 These 60,000 cards, laid out end to end — the five inch end, not the three inch end — can encircle Central Park (almost), and I hear this will actually be a public art project next summer.
Can any one programmer master 60,000 methods and properties? I think not. One solution, of course, is specialization. I myself have specialized. This evening I hope no one will ask me questions about web forms or ASP .NET or SQL Server because those aren’t my specialty. I do Windows Forms, and my language is C#.
IntelliSense
Visual Studio has attempted to alleviate the problem of class, method, and property proliferation with a feature called IntelliSense. IntelliSense indeed puts information at our fingertips, if you think of your fingertips figuratively as that place on the screen where the keyboard caret is.
Like other addictive technologies, I have a love/hate relationship with IntelliSense, and the more I despise it, the more I use it, and the more I use it, the more disgusted I am at how addicted I’ve gotten, and the more addicted I get, the more I wish it had never been invented.
Just in case you’ve been out of the trenches for awhile, IntelliSense is a culmination of some past attempts at code completion technologies. If you type an object name and a period, for example, you’ll get a little scrollable dropdown menu with a list of all the public methods, properties, and events for that class, and when you choose a method name and type a left parenthesis, you’ll get the various overloads with arguments, and a little tooltip describing what the method does.
IntelliSense is considered by some to be the most important programming innovation since caffeine. It works especially well with .NET because Visual Studio can use reflection to obtain all the information it needs from the actual DLLs you’ve specified as references.
In fact, IntelliSense has become the first warning sign that you haven’t properly included a DLL reference or a using directive at the top of your code. You start typing and IntelliSense comes up with nothing. You know immediately something is wrong.
And yet, IntelliSense is also dictating the way we program.
For example, for many years programmers have debated whether it’s best to code in a top-down manner, where you basically start with the overall structure of the program and then eventually code the more detailed routines at the bottom; or, alternatively, the bottom-up approach, where you start with the low-level functions and then proceed upwards. Some languages, such as classical Pascal, basically impose a bottom-up approach, but other languages do not.
Well, the debate is now over. In order to get IntelliSense to work correctly, bottom-up programming is best. IntelliSense wants every class, every method, every property, every field, every method parameter, every local variable properly defined before you refer to it. If that’s not the case, then IntelliSense will try to correct what you’re typing by using something that has been defined, and which is probably just plain wrong.
For example, suppose you’re typing some code and you decide you need a variable named id, and instead of defining it first, you start typing a statement that begins with id and a space. I always type a space between my variable and the equals sign. Because id is not defined anywhere, IntelliSense will find something that begins with those two letters that is syntactically correct in accordance with the references, namespaces, and context of your code. In my particular case, IntelliSense decided that I really wanted to define a variable of interface type IDataGridColumnStyleEditingNotificationService, an interface I’ve never had occasion to use.
On the plus side, if you really need to define an object of type IDataGridColumnStyleEditingNotificationService, all you need do is type id and a space.
If that’s wrong, you can eliminate IntelliSense’s proposed code and go back to what you originally typed with the Undo key combination Ctrl-Z. I wish I could slap its hand and say “No,” but Ctrl-Z is the only thing that works. Who could ever have guess that Ctrl-Z would become one of the most important keystrokes in using modern Windows applications? Ctrl-Z works in Microsoft Word as well, when Word is overly aggressive about fixing your typing.
But the implication here is staggering. To get IntelliSense to work right, not only must you code in a bottom-up structure, but within each method or property, you must also write you code linearly from beginning to end — just as if you were using that old DOS line editor, EDLIN. You must define all variables before you use them. No more skipping around in your code.
It’s not that IntelliSense is teaching us to program like a machine; it’s just that IntelliSense would be much happier if we did.
And I think it’s making us dumber. Instead of finding out exactly the method I need, or instead of trying to remember an elusive property name, I find myself scrolling through the possibilities that IntelliSense provides, looking for a familiar name, or at least something that seems like it might do the job.
I don’t need to remember anything any more. IntelliSense will remember it for me. Besides, I justify to myself, I may not want those 60,000 methods and properties cluttering up my mind. My overall mental health will undoubtedly be better without them, but at the same time I’m prevented from ever achieving a fluid coding style because the coding is not coming entirely from my head. My coding has become a constant dialog with IntelliSense.
So I don’t think IntelliSense is helping us become better programmers. The real objective is for us to become faster programmers, which also means that it’s cheapening our labor.
Of course, I could always just turn it off.
And go cold turkey? I don’t think so!
IntelliSense is a technology that is inevitable. If Microsoft hadn’t done it, somebody else would have. Human beings have never been inclined to refrain from pursuing certain technologies because they may have unfortunate repercussions.
Generated Code
Not only does Visual Studio try to complete code we’re typing, but for many years now, Visual Studio has wanted to generate code for us. If we select a new project type of Windows Application, for example, and give it a name and location on a local drive, Visual Studio generates sufficient code so that this project is immediately compilable and runable.
Somehow, we have been persuaded that this is the proper way to program. I don’t know why. Personally, I find starting a program with an empty source code file to be very enjoyable. I like typing the preliminaries and then the main function or the Main method. The time when I can really use some help is not when I’m starting a program, but when I’m trying to finish it. Where is Visual Studio then?
Let’s go into Visual Studio 2005 in our imaginations and create a C# Windows Forms program — a project of type Windows Application — and let’s examine the code.
First, we see that Visual Studio has hooked up our program to a bunch of dynamic link libraries it thinks we will need. It has created references not only to the System, System.Drawing, and System.Windows.Forms assemblies that are required of any non-trivial Windows Forms application, but also System.Data, System.Deployment, and System.Xml, regardless whether your program needs these DLLs or not. These extra references don’t do any real harm except if someone else examines the program — perhaps to make some changes after the original programmer has moved on — and assumes that the application requires these references. Now there’s confusion, because references to DLLs exist that the program really doesn’t need.
Among other files, Visual Studio creates a file named Form1.cs that it graciously allows you the programmer to modify. This is the source code file where the event handlers go for controls on the main form. We see a bunch of using directives at the top with the namespaces the program needs. The normal namespaces for Windows Forms programs are System, System.Drawing, and System.Windows.Forms, but Visual Studio also includes System.Collections.Generic, System.ComponentModel, System.Data, and System.Text, some of which are useful to be sure, but if the program doesn’t actually use any of the classes in these namespaces, they’re just distracting noise.
Visual Studio also encloses all the code it generates in a namespace that is given the same name as the project name. Of course, I understand entirely the value of having a namespace for DLLs, but why have a namespace for applications? I have given this much thought, and I can’t figure it out.
I’ve been talking about code, but when you create a new Windows Forms project, Visual Studio doesn’t put any of the source code files in front of your face. Instead, it puts a design view of a form which you are then expected to start interactively populating with controls.
Visual Studio also creates a file named Form1.Designer.cs, and in some beta versions of Visual Studio 2005, this file wasn’t even listed among the project files by default. This is the file in which Visual Studio inserts generated code when you design your form. Visual Studio really doesn’t want you messing around with this file, and for good reason. Visual Studio is expecting this generated code to be in a certain format, and if you mess with it, it may not be able to read it back in the next time you open the project.
The Origins of the Designer
Of course, the interactive design of forms is one of the major features of Visual Studio. It may help to contrast the Visual Studio designer with the way Windows programming was done 20 years ago when Windows 1.0 was first released — 20 years ago next month, to be precise.
I don’t want to bore everybody with war stories about Windows 1.0 programming, but basically you did most of your programming outside of Windows on the DOS command line. You edited your source code with your favorite editor — mine was a word processor of the era called WordStar — and then you’d compile and link on the command line, and run your application in Windows by typing Win followed by the name of your EXE file. You’d test out your program in Windows and then exit Windows back to DOS and reload the source code in your editor.
It was not possible to do much program development inside Windows except to run the Windows-based Icon Editor that helped you make icons, cursors, and small bitmaps.
To define the layout of menus and dialog boxes, you created a text resource script. In this file you’d type templates for the menus and dialog boxes in a particular defined format. For dialog boxes, you’d basically list the controls you wanted in the dialog box. The syntax wasn’t too bad, for example, the keyword BUTTON followed by the text that appeared in the button, the button’s location in the dialog box, and its width and height. Because Windows could run under systems of different display resolutions, these sizes and locations were in a special dialog box coordinate system, where horizontal units were equivalent to ¼ the width of the default system font, and vertical units were 1/8 the height of the font.
These resource scripts were actually considered an enormous time saver. If you didn’t have the resource script, you’d have to create the menu and dialog boxes in code, and that was a particularly onerous job. And the syntax of the resource script was so clean and simple that it remains to this day the most concise way of defining menus and dialog boxes that I have ever seen.
There was only one little problem: All those controls in your dialog boxes had to be positioned and sized correctly with numbers you had to figure out. Sometimes it would help to start with a piece of graph paper and do a hand mockup of the dialog box. Otherwise, it was pretty much a matter of trial and error, back and forth, load up Windows, invoke the dialog box, see how crappy it looked, exit Windows, reload the resource script, and eventually you’d fine tune those sizes and locations until it looked right.
Sometime in 1986 or so, beta versions of a Dialog Editor emerged from Microsoft. I found out about it by lurking on a bulletin board called the Windows Developers Roundtable on the information service GEnie, the General Electric Network for Information Exchange. The Dialog Editor was a Windows program that let you interactively design your dialog boxes by moving controls around, and would then output the dialog template in the correct format. I eventually wrote an article about it for the very first issue of Microsoft Systems Journal in October 1986. The article had the title “Latest Dialog Editor Speeds Windows Application Development”.
But for the Windows programs that I later wrote for MSJ, and for those in the first edition of Programming Windows, I couldn’t use this Dialog Editor. I couldn’t use it for the simple reason that the output of the Dialog Editor was ugly.
Let me explain what I mean by that, and why it’s a problem.
People who write code for publication have some extra burdens that most programmers need not worry about. The code we write has to be concise but not to the point where it’s obscure. It should be nicely formatted and easy to read. There should be plenty of white space. It should be airy. It can’t have superfluous variables or unused functions. It has to compile without warning messages.
Moreover, code published in books is limited to line lengths of about 80 characters, sometimes a little more, sometimes less. Magazines sometimes impose even more severe limits, depending how much power the art department has in the political structure of the magazine staff. Microsoft Systems Journal was an interesting case. Although M SJ was originally supposed to be strictly a Windows-programming magazine — they later chickened out and made it for DOS programming as well — it was laid out entirely on Macs and the art department ruled. Art people love very narrow text columns, and I remember MSJ going to extra-narrow columns at about the same time that the OS/2 Presentation Manager was introducing function calls like GpiQueryModelTransformMatrix.
Under these criteria, the Dialog Editor generated ugly and unusable output. It didn’t even generate BUTTON, LABEL, and LISTBOX statements like a normal human being. Instead, it spit out everything as general-purpose CONTROL statements followed by class names. These lines had lots of superfluous information. All the parameters were included, although many of them were default values. These lines were way over 80 characters.
People have to read this stuff, and the Dialog Editor output was unreadable. Moreover, if somebody is trying to reproduce the dialog box on their own, it doesn’t make any sense to show the output from the Dialog Editor.
When I was working on the first edition of Programming Windows in 1987, sometimes I’d use the Dialog Editor and then manually convert the output to something a human being might write. But mostly I just got skilled at designing dialog boxes by hand.
Of course, a Dialog Editor is certainly a piece of “inevitable technology.” It’s so obvious that it must be created, and in principle, I can’t summon up any arguments against it. It’s what it evolved into that really bothers me.
|