A few days ago, after browsing the Coffeescript docs and examples, I tweeted, “I will take your new language seriously when you have a symbolic debugger for it. For it, not for the C/JavaScript/whatever it compiles to.” So what exactly did I mean by that? Well, a debugger is a program that lets you watch and control another program. (If you’ve never used one, have a look at this 6-minute video.) Instead of staring at your code, trying to figure out why it’s broken, or adding ‘print’ statements left and right to display values, debuggers let you stop the program at any point and look at the values, or tell the program to execute one line at a time so that you can see which “if/else” branches it’s taking, what parameters are being passed to function calls, and so on.
Debuggers make programming much less painful and much more productive, but a lot of students never pick up the habit of using one. Personally, I think this is because teachers have never figured out how to put questions about using debuggers on mid-terms: most computer science programs don’t have an equivalent of the “lab exams” that are common in chemistry and biology, and if students are never examined on their ability to do things the right way, they never have to climb the learning curve. But that’s just a guess, and tangential to the main point of this post.
What I really want to talk about is languages like Coffeescript, and why I won’t use them. If I write a program in C, Java, Python, or Javascript, it is translated into instructions for some kind of machine (either real hardware, in the case of C, or a virtual machine in the case of the other three). When that program runs, the debugger can match up the source code of the program and the instructions that are being executed, so that when I say, “Go to the next line,” the debugger can do what I ask. These debuggers are WYSIWYG: the code I wrote (i.e., the code that’s in my mind) and the operations and data that I’m debugging, line up neatly.
But if I write a program in Coffeescript, it isn’t executed directly. Instead, it is translated into Javascript, and then that is what’s run. If I want to debug that Javascript, I can, but I didn’t write it: a computer program did. Yes, the bits and pieces of that Javascript correspond to my Coffeescript, but the match is not obvious, and may not even be one-to-one. It’s as if I wrote a contract in English in terms of Ontario law, then had to defend it in court in French under Quebec law. Without near-expert understanding of how the one translates to the other, it’s hard or impossible for people to reverse engineer what the debugger is showing them and figure out which bits of the code they actually wrote needs to change.
I first ran into this problem in the 1980s, when the C++ compiler I was working with translated my object-oriented programs into a tangle of strangely-named C functions for me to compile and run. After a while, I figured out that if the error was in XX_@_YY_@@_ZZ, I should look for a method called XX.YY taking a parameter of type ZZ, but the C that implemented overloaded operators was ugly enough that I never really wrapped my head around it. Debuggers eventually appeared that could handle C++ “in source”, and I’m sure that if Coffeescript proves popular, a native debugger for it will appear as well. ‘Til then, as much as I prefer its syntax to Javascript’s, I will (regretfully) turn away…
Yeah, it does look to me like a bunch of people use debuggers less these days, and I don’t really get it. It seems even more the case to me that nobody uses *profilers* anymore — that match your experience too?
On debuggers: my experience has been that debuggers are generally answering the wrong question for me. Usually I want to know ‘how did my code wind up in this problem?’, but debuggers seem to be mostly about finding out what happens next. Possibly this means that I am doing debugging wrong.
(As a result I wind up using print statements to give me a history trace, hopefully of the relevant bits of information.)
You’re right, a “rewind debugger” would be nice, and some now exist, but they haven’t gone mainstream yet… Once I’m at the point where the first symptom(s) appear, I usually look at the stack trace, or at which values are wrong, then start setting breakpoints there.
I’ve made this exact argument many times when talking to people about CoffeeScript.
I’m uncomfortable with CoffeeScript for the same reason I’m uncomfortable with all of those Java meta-frameworks that compiled XML into Java code. With or without a debugger, it’s always easier to work with code a human has written than it is to work with code generated by a compiler.
I have similar feelings about things like Less or Sass that are popping up in the CSS world, although I admittedly write too little CSS to have *that* strong an opinion
Debuggers seem to be a personality thing. I did have college professors who threatened to lower the grade of anybody they caught debugging with print statements (who were for troglodytes who didn’t know how to use a debugger).
I had others who said they thought debuggers are useless and for point-n-click programmers.
I myself, use the debugger sometimes, sometimes not. Mostly, I use them to inspect the status of the programme after a crash, but I have written a lot of code where it’s hard to get a debugger in without a lot of set up (where you are calling code in one language from another language, or have more than one process communicating back-n-forth).
I love coffeescript, btw; the translation is pretty direct, so you can always debug js if you want.