Friday, August 21, 2009

The Bug from Hell

Executive Summary

One full week lost. Zero output units. It was the bug from hell. If you have any faith in your software schedules, read on.

I am writing a SketchUp Ruby. Stuff that worked Friday stopped working Saturday morning. I got to the bottom of the problem Thursday morning. In a lifetime of coding I've never been stopped for five days by one bug. It was subtle.

The trickiest bit about Rubies is that your UI runs in a browser. That means that the Ruby code that manipulates the model has to communicate with the JavaScript in the browser. (Note: this is another case where you have two languages to use and zero choices about which you use.)

JavaScript on the Front Line:

The general idea is that since the user is in charge, JavaScript notes what buttons are clicked or whatever. JS can then call a Ruby function that will dig up whatever data is needed or manipulate the model in the manner requested. If it needs to send data, Ruby prepares a bit of JavaScript, like this:


script = 'name_of_javascript_function( whatever, facts, are, required )'


Ruby hands this script to a webdialog object (prepared by the web dialog and passed to the Ruby callback). The webdialog executes the script, presumably calling JS functions that make use of the data. The whole communication thing is at best inelegant. This is NOT pythonic.

"No, no, Monty! I didn't mean you. You are totally pythonic."

Monty, my pet python, has been crabby since I turned him into a vegetarian. Sorry for the interruption.

Ruby in the Trenches

Saturday morning I moved the JavaScript out of the HTML file and into a separate JavaScript file so I could validate the HTML. I've got validated HTML, but the code no longer worked. It seems that JavaScript correctly calls Ruby. Ruby correctly gathers the data wanted and correctly forms the script needed. But Ruby is definitely not succeeding in getting back to JavaScript. The final step, executing the JavaScript script, is not happening. At one point the JavaScript function that I wanted called by the script was reduced to launching an alert box that said, "Hooray! Finally!". It never said "Hooray! Finally!".

Note that the tool set is completely primitive. There is no NetBeans, no Eclipse, no debugger. On Windows, we can choose any browser we like, provided we choose MSIE. At one point it reported that I had an error in my JavaScript at line 51 million and something. Ugh. The tiniest little bit of error checking and it's too buggy to be helpful.

For debugging, you stick print statements into the Ruby and pop up alert boxes in JavaScript. Before Saturday ended I knew that my JS was correctly calling Ruby, that Ruby was preparing a valid script passing correct data and was calling the correct method of the webdialog (the webdialog that JS had passed to Ruby). And that was the end of the road.

Swapping Code

By Tuesday I knew that the same code that worked also failed. I started with a successful, small test package and the unsuccessful, larger actual package. I began removing parts of the larger package deleting bits one a a time until I could find the guilty party. I ended with a still-failing package no larger than the test package.

Wednesday found me copying Ruby source functions from the test to the failing routine. Still fails. Copy from the failing to the test? Still succeeds. So repeat this with the JavaScript functions. Same result.

Early Thursday I am convinced that it is a timing issue. How else could two copies of the exact same code fail and succeed?

"Martin, what are you talking about? It's single-user, single-threaded code! Timing issue?"

"OK, Monty. You explain it."

That got me back to Saturday morning. I had taken the JavaScript out of the HTML, where it had been at the end of the body of the page, and put it into a JavaScript file. I linked to the JavaScript file from the <head> section of the HTML, a common practice that I will never again practice.

Moving the "load the JavaScript file" command from the <head> of the HTML to the end of the <body> of the HTML turned the failing code to successful code. Bug in the SketchUp linkage: if your HTML is not completely processed, the webdialog that it passes to Ruby cannot execute the JavaScript script.

Moral?

(In Ruby convention, getters for booleans are suffixed with a "?". This section should return a boolean.) Moral? Maybe.

I let my ego get in the way. Hot shot programmers fix their own bugs, right? Instead of punching ahead on my own, I should have recruited an associate. Wise old programmers get help when they need it. I'll try to remember that.

Monday, August 17, 2009

Scroll Down! Blogger's to Blame.

In the previous (following this one if you are reading chronologically) there is a giant bunch of empty space above the table. Scroll down, the table's there.

I don't know why. The HTML doesn't have any problem if you view it in a browser. This is a Blogger issue. And so it goes.

Broadband for Everyone

Broadband in America:

From Business Week, stimulus package broadband expansion funds are not going to cities.

Broadband Stimulus and the Underserved

I was curious about the situation around the world, so I asked Google. He showed me Internet World Stats. They showed me a table of broadband penetration, but, unfortunately, it was ranked by total broadband subscribers. U.S. has the most. China is second. That is pointless.

How do we compare, penetration per capita. U.S.: 21.9%. China: 3.7%.

Open Office:

Internet World Stats does not, unfortunately, provide a spreadsheet version of its data for download. I needed their data sorted by penetration. Briefly considered retyping into a spreadsheet, but decided to try for an easy alternative.

I swept my mouse over Internet World Stats whole table. Pressed ^C. Went to my text editor and pressed ^V. Scrambled data eggs.

I opened an OO spreadsheet. Pressed ^V in cell A1. Absolutely amazing! A very nice spreadsheet appeared. Even the report and column headers were sensibly laid out.

I selected column D and asked for a descending sort. Ooops. That sorted column D. Selected all the data and asked for a sort. It asked, "What column(s) and up or down, please?" Click, click, done. Just what I wanted to know. U.S. is seventh in the world behind some countries you might have guessed (Sweden) and some you might not (France).

I'd show you the whole table, but that might be hard. I'll try, anyway.

Whole Table:

Back to OO. Save as HTML. Open HTML in text editor, copy the parts from "<TABLE>" through "</TABLE>" tags. (Sorry to see that OO still uses capital letters.)

Pasted the HTML into the Blogger "Edit HTML" tab. Here's the result:













































































































































































































TOP COUNTRIES WITH THE HIGHEST NUMBER OF WORLD INTERNET BROADBAND SUBSCRIBERS IN 2007
# Country or Region Broadband Subscribers Broadband Penetration (%) Population ( 2007 Est. ) Source and Date of Usage Data
12 Netherlands 5388000 32.80% 16447682 ECTA - Mar./07
5 Korea, South 14042728 27.40% 51300989 OECD - Dec./06
20 Sweden 2478003 27.20% 9107795 ECTA - March/07
9 Canada 7675533 23.70% 32440970 OECD - Dec/06
6 United Kingdom 13957111 23.10% 60363602 ECTA - Mar./07
7 France 13677000 22.30% 61350009 Teleco - Mar/07
1 United States 66213257 21.90% 301967681 OECD - June/07
4 Germany 17472000 21.20% 82509367 OECD - June/07
3 Japan 27152349 21.10% 128646345 OEDC - June/07
13 Taiwan 4505800 19.60% 23001442 ITU - Sept/07
14 Australia 3939288 18.80% 20984595 OECD - Sept/06
10 Spain 7505456 16.70% 45003663 CMT - July/07
8 Italy 9427300 15.80% 59546696 ECTA - Mar/07
18 Poland 2640000 6.90% 38109499 OECD - Dec./06
16 Turkey 3632700 4.80% 75863600 ECTA - Mar/07
2 China 48500000 3.70% 1317431495 MII - Sept./06
15 Mexico 3728150 3.50% 106457446 OECD - Sept/06
11 Brazil 6417000 3.40% 186771161 Teleco - June/07
17 Russia 2900000 2.00% 143406042 ITU - Sept./07
19 India 2520000 0.20% 1129667528 TRAI - June/07






TOP 20 Countries 268150077 6.90% 3890377607 IWS - Nov.14/07
Rest of the World 36321302 1.40% 2684288810 IWS - Nov.14/07
Total World Subscribers 304471379 4.60% 6574666417 IWS - Nov.14/07

Saturday, August 15, 2009

JSON in Practice

Writing JSON:

I wrote a specific-purpose JSON writer, in Ruby, to encode the data I needed. It wasn't too tough:


# JSON to send to webdialog
def makeJson( layer_names, scene_names, vis )
ret = '{ '
ret += 'layers:' + makeJsonArr( layer_names )
ret += ', scenes:' + makeJsonArr( scene_names )
ret += ', vis:\"' + vis + '\"'
ret += ' }'
return ret
end

# convert array of names to JSON array
def makeJsonArr( names )
ret = '[ '
start = true
names.each do |n|
unless start
ret += ', '
else
start = false
end
ret += '\"' + n + '\"'
end
ret += ' ]'
return ret
end


Reading JSON:

Since JSON is syntactically correct JavaScript, this is the reader that decodes it in JavaScript:


function rubySays( data ) {
eval( 'obj = ' + data );


The rubySays() method then goes on to make use of the object it creates in its first line. I like code that weighs in at just tens of bytes.

Summary:

Writing JSON is easy. Reading JSON in JavaScript is effortless. Highly recommended!

Friday, August 14, 2009

Multiple Desktops

Today's Views:

Not news, views. AAPL Undervalued?

I know a couple things about stock prices. One is that rising EPS is a good thing. The other is that today's price of X is the price at which exactly half the people on Wall Street think X is overvalued while the other half believes X is undervalued. This is good to remember when you read an analyst who is in the undervalued camp. Half the people on Wall Street, and there are some very smart people on Wall Street, disagree.

Multiple Desktops:

I have a nice big desk and I keep it organized. This is good. Having several nice big desks would be better. Each project I am working on would have its own desk. Books, papers, 3D models, whatever would be on its own desk. Changing from project A to project B wouldn't require putting A's stuff away and opening B's stuff. I'd just move from desk A to desk B.

This is exactly what I have in Linux. I press Ctrl+F3 for this blog. Ctrl+F4 gets to my personal website. Ctrl+F11 gets to my Decaf language project. Almost all my desktops have a browser open, but none have the same tabs open. Most have a text editor, but each editor has different files open. I use 12 desktops (max: 20, but even 12 may be too many). Some have spreadsheets; some have pictures.

Multiple Desktops in Windows:

Windows sucks you back in like a black hole. Google SketchUp, for instance, runs in Windows and OS X, but not Linux. You want SketchUp Rubies? Any language you want, provided you want Ruby and any OS you want, provided you don't want Linux. Windows does not have multiple desktops.

Hold on. Windows has multiple users. Each user has a single desktop. Many users times one desktop each looks a lot like multiple desktops!

In Linux, Ctrl+Fx switches to desktop x. There's also a little display of an array of desktops where one mouse click switches. In Windows that's Start, Logoff, Switch User and then click on user. But if you hold down that special key with the windows logo and press L, you've got Start, Logoff, Switch User all at once. It's only a single click more difficult than Linux.

So go ahead and create a "User" for each of your projects. You will be very happily surprised at how nice it is to return to a browser with a handful of tabs open related to the project. And at how convenient it is to not have to put one project away to work on another.

You do have 2GB of RAM, don't you?

Thursday, August 13, 2009

Today's News:

Let's get to the really critical issue of the day: Will Windows 7 or Snow Leopard have better wallpaper? They're really on top of things at Fortune.


Snow Leopard vs. Windows 7: The War of the Wallpapers

The article's link to MSFT's wallpapers got you to its financial results, not its wallpaper. Use this one, instead.

I recommend that you get a camera and make some of your own. Here are a couple of mine: Catskills in Winter, Fall Scene from Kayak. (Big, fat files. Sorry.) The secret to good amateur photos? Take lots and lots. Then throw most of them, almost all of them, out.

Linux Desktops

Linux has two graphical front ends, GNOME and KDE. Free software champion Richard Stallman created a Unix workalike, naming it GNU (GNU is Not Unix). GNOME, (originally GNU Object Model Environment), and KDE (originally Kool Desktop Environment) are both excellent desktops. Both disavow their original acronyms.

I started with, and still use, KDE for the simple reason that it came preinstalled, as Windows typically comes. The computer was so cheap that I bought it just to satisfy my curiousity about Linux. Was it really as reliable as people said? Would the learning curve be steep?

Yes, it works for months at a time and no, there was almost no learning curve. I turned it on and started using it. A big button labelled "Launch" looked like it would be similar to MSFT's "Start" and it was. I was soon in familiar software: Firefox and Open Office. Then I found the Konqueror browser/explorer replacement. Firefox is maybe five years behind and Windows Explorer is utterly primitive by comparison.

I have learned to open a command window and use a handful of the original Unix commands, but this is no more necessary than using the DOS window in Windows.

What I have learned to love most, and even sort of simulate when I have to go back to Windows, is the multiple desktop feature. More on that, soon.

Open Office

Are you still paying Microsoft for its Office software? Why? It will not be long before you are asked this question by one of your directors whose own organization has switched successfully. The only acceptable answer is, "We're in transition right now. We'll be fully converted before the current licenses expire."

Wednesday, August 12, 2009

JSON: JavaScript Object Notation

Todays news:

Business Week tells us Why Apple Is More Valuable Than Google

Executive summary: Google makes money on search. Loses money elsewhere. Apple makes money on everything.

JSON: JavaScript Object Notation:

I'm working on Rubies, plug-ins for Google SketchUp written in Ruby. More exactly, since the UI takes place in a browser, written in JavaScript and Ruby. Google has provided a mechanism for Ruby to pass a string to JavaScript and for JavaScript to pass a string to Ruby. I need to share lists of strings and an array of booleans for my Ruby. Enter JSON.

Like XML, JSON stores stuff in human-readable strings. Specifically, it stores objects, arrays, strings, numbers, and constants 'true', 'false' and 'null'. Strings and numbers are very much like strings and numbers in C (and from C, C++, Java and many others).

Arrays are a comma-separated list of values enclosed in square brackets. Array values may be anything that JSON supports: objects, arrays, ... (list above). Arrays may be all of a single type, or any mix of types. Arrays are one dimensional, but as arrays may be members of arrays, this is not a restriction.

Objects are zero or more comma-separated name:value pairs, enclosed in curly braces.

Add whitespace between values, if you like.

And that's it! Very light but no less capable than XML. If you want to write a JSON reader/writer, the exact details (such as the short list of escaped characters) are at www.json.org. A JSON reader/writer is already written for all the languages I know.

Doug Crockford invented JSON, sort of. JSON copies the notation Brendan Eich invented for JavaScript. Crockford noticed that this notation made a simple but full-powered version of XML. Here's an example:


pet={type:python, diet:vegetarian, TimToady:opposed}
pets = [ python, kitten ]


Those are valid JavaScript statements. To the right of the "=" signs you see valid JSON. I love things like this. We backpackers say, "When in doubt, leave it out."

JSON can get just about anything talking to anything else. Highly recommended.