Yesterday I needed an improved version of the JavaScript textarea widget. Ah! I'll write my own text editor.
That's not a trivial task, but it's the core of my C++ book (an excellent tutorial, but sadly it dates back to DOS). I had already done the design and the step-by-step, how to build it thinking. That's probably half the battle. I thought that I could have a working, if minimal, text editor in about a day.
Nope. Was into the project for about an hour when it came time to program the Insert key to toggle insert/overstrike modes. Brick wall. There was no way to distinguish Insert from the minus sign. None. And this in Opera, which is the best of the PC browsers.
Redesigned the project to work with the unimproved JavaScript textarea widget.
As I write this, Obama is pardoning the turkey at the White House. I am not pardoning this turkey.
Wednesday, November 25, 2009
Wednesday, November 11, 2009
Storage under Technological Deflation
Around 1980 I worked for a small time-sharing company. We held a little party to celebrate the day we added one more disk drive, reaching a full gigabyte. (The drives each held 80MB. They were about 18 inches square, 40 inches tall. They filled a room about 15x20 feet.)
Yesterday I flipped through a BH Photo catalog. (Good company, great catalog, good but not great prices.) A terabyte drive is now $100.
What does it mean for software that disk storage is now nearly free? I'm thinking about it.
What does it mean for software managers that 24 inch, 1920x1200 LCD monitors are down to $200? It means your programmers should have them! They will love you fand productivity will rise. (This from personal experience. I upgraded when the price broke through the $500 barrier, replacing my 2x2 array of 19" CRTs with one flatscreen. It now serves two PCs, Windows and Linux, via a KVM switch.)
Back to writing SketchUp Rubies. WebDialog front-ends in JavaScript, SketchUp API in Ruby. Monty spends his days with Kitten, not with me.
Yesterday I flipped through a BH Photo catalog. (Good company, great catalog, good but not great prices.) A terabyte drive is now $100.
What does it mean for software that disk storage is now nearly free? I'm thinking about it.
What does it mean for software managers that 24 inch, 1920x1200 LCD monitors are down to $200? It means your programmers should have them! They will love you fand productivity will rise. (This from personal experience. I upgraded when the price broke through the $500 barrier, replacing my 2x2 array of 19" CRTs with one flatscreen. It now serves two PCs, Windows and Linux, via a KVM switch.)
Back to writing SketchUp Rubies. WebDialog front-ends in JavaScript, SketchUp API in Ruby. Monty spends his days with Kitten, not with me.
Wednesday, September 23, 2009
JavaScript Objects, Opera's Error Console
The News:
Saw Steve Forbes on CNBC yesterday. He's still spouting the supply-side nonsense that Reagan abandoned after a single-year trial. Well, his reporters are still out there reporting, and they do a good job. Wonder what Oracle is up to? Here's Ellison's game plan.
Yet another attempt to mount a frontal assault on IBM. This stupidity seems to be contagious.
JavaScript Objects
Let's create a JavaScript object.
That's right. No class; no constructor; just create an object.
Today I've got to figure out how to do a hash in JavaScript. Let's add that:
That's right, too. Need an attribute? Assign to it. Python works this way, too. Ruby requires more Java-like planning.
Sometimes a constructor is a good thing. A regular function, first letter capitalized by convention, serves as a constructor:
Let's use that constructor to create an array of Persons.
If you are used to Java, that probably seems more organized. You UML fans are probably breathing a sigh of relief. Forget it.
Harry and I share an additional characteristic. Note that Harry is a Person; I am not. Dick, and no one else, has a hobby. (Did you notice that I did that google? JavaScript arrays are associative.) JavaScript objects are also associative arrays:
Actually, all the characteristic names here are strings. If you have names (no spaces or funny characters), you don't need to type the quotes. This is a convenience. Is it a good practice?
Now, is this very free-form object model conducive to good code? I don't know. JavaScript is, traditionally, bug-ridden. (Not yours, of course? I doubt it. Open the Opera browser. Click Tools/Advanced/Error Console. Now visit one of your own sites. IBM's JavaScript is a mess. Why should yours be different?)
But study that Error Console dump. Are any of the errors caused by attempts to access non-existing characteristics? I've never seen that. Your own JavaScript will get cleaned up when your developers find out that you'll be running your own sites in Opera with the Error Console turned on.
Saw Steve Forbes on CNBC yesterday. He's still spouting the supply-side nonsense that Reagan abandoned after a single-year trial. Well, his reporters are still out there reporting, and they do a good job. Wonder what Oracle is up to? Here's Ellison's game plan.
Yet another attempt to mount a frontal assault on IBM. This stupidity seems to be contagious.
JavaScript Objects
Let's create a JavaScript object.
var martin = { name: "Martin Rinehart", current_activity: "blogging" };
That's right. No class; no constructor; just create an object.
Today I've got to figure out how to do a hash in JavaScript. Let's add that:
martin.next_google = "javascript associative array";
That's right, too. Need an attribute? Assign to it. Python works this way, too. Ruby requires more Java-like planning.
Sometimes a constructor is a good thing. A regular function, first letter capitalized by convention, serves as a constructor:
function Person( name ) { this.name = name; }
Let's use that constructor to create an array of Persons.
var names = [ 'Tom', 'Dick', 'Harry' ];
var people = [];
for (name in names) { people.push( new Person(name) ); }
If you are used to Java, that probably seems more organized. You UML fans are probably breathing a sigh of relief. Forget it.
martin.kayak = 'flatwater';
people['Harry'].kayak = 'whitewater';
people['Dick'].hobby = 'gourmet chef';
Harry and I share an additional characteristic. Note that Harry is a Person; I am not. Dick, and no one else, has a hobby. (Did you notice that I did that google? JavaScript arrays are associative.) JavaScript objects are also associative arrays:
people['Tom']."rock climbs" = "Half Moon";
Actually, all the characteristic names here are strings. If you have names (no spaces or funny characters), you don't need to type the quotes. This is a convenience. Is it a good practice?
Now, is this very free-form object model conducive to good code? I don't know. JavaScript is, traditionally, bug-ridden. (Not yours, of course? I doubt it. Open the Opera browser. Click Tools/Advanced/Error Console. Now visit one of your own sites. IBM's JavaScript is a mess. Why should yours be different?)
But study that Error Console dump. Are any of the errors caused by attempts to access non-existing characteristics? I've never seen that. Your own JavaScript will get cleaned up when your developers find out that you'll be running your own sites in Opera with the Error Console turned on.
Tuesday, September 22, 2009
Mid-Twentieth Century Languages
In the News:
Dell to buy Perot. Having trouble competing with HP? Here's an idea: go head-to-head with IBM.
Mid-Twentieth Century Languages
Ruby's powerful and full of Tim Toady. Python's powerful and pythonic. In one area, however, both are bad reminders of the 1960s.
I refer to the fact that both are strictly interpreted, according to the lamest definition of the term. They begin processing at the top of the file. Declarative code? Processed. Imperative statements? Processed.
The intelligent way, of course, is to read the file handling all the declarative code first. Functions, for example, are defined and ready for use when the imperative code is processed. Functions may be declared where they make sense. The structure of the source code is not dictated by the processor; it's decided by the programmer.
Ruby and Python? Nope. Don't place your imperative code at the top of the file; library functions at the bottom. You cannot call a function from statements above the function's definition; you cannot instantiate an object ... This is stupid.
JavaScript eats your source code's declarations first, then goes on to process your imperative code. JavaScript is not the world's most advanced language. That Ruby and Python are less advanced than JavaScript should be an embarassment to both.
If you remember Pascal from the early days of microcomputers you remember being forced to write your main program at the bottom of your file. This was, and is, a tragedy if you valued readability. This is how you must structure your Ruby and Python.
JavaScript gets this right. Java lets you put "main()" where you choose. This should be completely standard in this century.
Dell to buy Perot. Having trouble competing with HP? Here's an idea: go head-to-head with IBM.
Mid-Twentieth Century Languages
Ruby's powerful and full of Tim Toady. Python's powerful and pythonic. In one area, however, both are bad reminders of the 1960s.
I refer to the fact that both are strictly interpreted, according to the lamest definition of the term. They begin processing at the top of the file. Declarative code? Processed. Imperative statements? Processed.
The intelligent way, of course, is to read the file handling all the declarative code first. Functions, for example, are defined and ready for use when the imperative code is processed. Functions may be declared where they make sense. The structure of the source code is not dictated by the processor; it's decided by the programmer.
Ruby and Python? Nope. Don't place your imperative code at the top of the file; library functions at the bottom. You cannot call a function from statements above the function's definition; you cannot instantiate an object ... This is stupid.
JavaScript eats your source code's declarations first, then goes on to process your imperative code. JavaScript is not the world's most advanced language. That Ruby and Python are less advanced than JavaScript should be an embarassment to both.
If you remember Pascal from the early days of microcomputers you remember being forced to write your main program at the bottom of your file. This was, and is, a tragedy if you valued readability. This is how you must structure your Ruby and Python.
JavaScript gets this right. Java lets you put "main()" where you choose. This should be completely standard in this century.
Friday, September 11, 2009
Error Handling
Today is 9/11/09. John and I played an hour of tennis once a week from 7:30 to 8:30 in the morning. We played eight years ago on this day, quite happily ignorant of the events unfolding in Manhattan. By 9:00 we were a half-hour apart, at our respective offices, watching TV. We haven't played since. And so it goes.
Error Handling Overview
Some processes can generate errors despite the most skillful coding. Disk I/O is one example. (User enters name of a file that doesn't exist. Data cannot be written because the disk is full.) I first met try/catch logic in the mid '90s in Java as a way to handle these sorts of errors. This is now a feature of most mainstream languages.
The basic idea is to surround a block of code (such as disk I/O code) with a "try this" instruction. Following the block to try there is an "if an error occurred" block. Some languages, Java included have an optional "whether or not there was an error do this" block. Code in the "try this" block (including, importantly, subroutines called in that block) can "throw" an error, often an Error or Exception object for use in the "if an error occurred" block.
Error Handling in Java
This is the basic Java syntax:
Java has both
If I were redesigning the language I would eliminate the
I would then use only a single
That said, let's look at the ways some other languages address the issue.
Error Handling in JavaScript
JavaScript follows Java's
In JavaScript: The Good Parts, Doug Crockford eliminates the
Error Handling in Python
Very like Java, but the
Error Handling in Ruby
Similar to Java, but Ruby stubbornly goes its own way. You don't
Ruby also features a
"Martin, don't forget that stupid Tim Toady! You can use
"Thanks, Monty. I'll put that in."
Monty, my pet python, knows just enough Ruby to criticize it.
Error Handling in C++
Like Java you have
Error Handling Overview
Some processes can generate errors despite the most skillful coding. Disk I/O is one example. (User enters name of a file that doesn't exist. Data cannot be written because the disk is full.) I first met try/catch logic in the mid '90s in Java as a way to handle these sorts of errors. This is now a feature of most mainstream languages.
The basic idea is to surround a block of code (such as disk I/O code) with a "try this" instruction. Following the block to try there is an "if an error occurred" block. Some languages, Java included have an optional "whether or not there was an error do this" block. Code in the "try this" block (including, importantly, subroutines called in that block) can "throw" an error, often an Error or Exception object for use in the "if an error occurred" block.
Error Handling in Java
This is the basic Java syntax:
try {
}
catch (Type1ExceptionOrError var1) {
}
[catch (Type2ExceptionOrError var2) {
}]...
[finally {
}]
Java has both
XxxException
and XxxError
classes. The builtin classes can be extended by the programmers to create more Exception
s and Error
s. Multiple catch
clauses allow code to be written to handle particular Exception
or Error
types. Importantly, catch (Exception e ) {}
will catch all exceptions, though it loses the ability to use any added information in extending classes. Errors can be handled similarly, but are generally not handled. A Java Error
would be something like a hardware failure that the program probably cannot deal with successfully.If I were redesigning the language I would eliminate the
finally
block entirely. The catch
blocks should simply branch to the code that follows the last catch block.I would then use only a single
catch
block. If needed, the programmer can put a switch inside that block which calls code appropriate to the exception type.That said, let's look at the ways some other languages address the issue.
Error Handling in JavaScript
JavaScript follows Java's
try catch finally
lead, with two important differences. First, there is only a single catch
block. Second, the thing caught may be anything: object, string, number, ... In JavaScript: The Good Parts, Doug Crockford eliminates the
finally
block, leaving exactly what I recommend for Java.Error Handling in Python
Very like Java, but the
catch
block is known as an except
block.Error Handling in Ruby
Similar to Java, but Ruby stubbornly goes its own way. You don't
try
, you begin
. You don't catch
, you rescue
. You don't finally
, you ensure
.Ruby also features a
retry
keyword that repeats execution of the try
block."Martin, don't forget that stupid Tim Toady! You can use
catch
blocks, too.""Thanks, Monty. I'll put that in."
Monty, my pet python, knows just enough Ruby to criticize it.
Error Handling in C++
Like Java you have
try
and catch
blocks. Unlike Java there is no finally
block. Also unlike Java, there is no restriction on the type of thing caught. Strings and integers, for examples, can be caught. There is also a generic "catch anything" variant, though there is no way to hand the thing caught to the code in this catch block, a disadvantage of strongly-typed languages.
Thursday, September 10, 2009
Google Books and the Three-Fold Path
News:
This NY Times article contains an excellent set of links to the pro and con positions re the settlement of authors and publishers v. Google. (The settlement will a: liberate books, or b: obliterate books say those who support or oppose it. I'm betting on c: boost books' Google search rankings.)
The Three-Fold Path to HTML Documents.
I have just released my first serious Ruby plugin for Google SketchUp. It is useful for creating multi-scene animations of a 3D model. Any non-trivial SketchUp Ruby UI is shown as a page in a browser, an HTML document. Here are the alternatives for creating an HTML document.
HTML
First, there is HTML, a simple set of markup commands that are the cyberspace equivalent of typesetting instructions. Let's look at a sample:
The basics are a set of tags that come in
If you decide to learn basic HTML, to improve your blog posts, for just one example, my easyHTMLtutorial.com will get you up and running quickly. HTML is simple. It's also the underpinning of the second path to HTML documents.
JavaScript: document.write()
There are times when you leave the simplicity of HTML and use JavaScript programming to create your HTML customized to your viewer's data. My Ruby is one example: it creates a table of checkboxes based on the user's model. There is one row for each "layer" (grouping of model components) and one column for each "scene" in the animation. It can only be created after querying the user's model for, for example, a list of the names of each layer. JavaScript for my Ruby's table would look like this:
This uses JavaScript's
DOM scripting
In my Ruby, for reasons I'll skip here,
Each web page is a set of objects attached to the "document" object, or attached to other objects which are, in turn attached to the document. In our table example, the table is attached to the document. The table row is attached to the table and the table headers are attached to the table row. Skipping lots of details, the basic idea is this:
Working at this very low level, your JavaScript is in total command. The cost: the simplicity of HTML is gone. If you have to drop to this bottom level, the amount and cost of the JavaScript rises dramatically. Switching from
"We don't go here unless we need to. Right, Monty?" Monty, my pet python, doesn't hear me. He's busy playing with the kitten.
This NY Times article contains an excellent set of links to the pro and con positions re the settlement of authors and publishers v. Google. (The settlement will a: liberate books, or b: obliterate books say those who support or oppose it. I'm betting on c: boost books' Google search rankings.)
The Three-Fold Path to HTML Documents.
I have just released my first serious Ruby plugin for Google SketchUp. It is useful for creating multi-scene animations of a 3D model. Any non-trivial SketchUp Ruby UI is shown as a page in a browser, an HTML document. Here are the alternatives for creating an HTML document.
HTML
First, there is HTML, a simple set of markup commands that are the cyberspace equivalent of typesetting instructions. Let's look at a sample:
<table align=center bgcolor=#fofoff border=1>
<tr>
<th>Heading, column one</th>
<th>Heading, columne two</th>
</tr>
...
</table>
The basics are a set of tags that come in
<tag> ... </tag>
pairs. Here you see table, table row, and table heading tags. Omitted are the table datum ( <td> ... </td>
) tags that will be part of the additional rows that provide the table's contents. These tags can have embedded attributes. Here the table is centered, its background set to light blue and border set to one pixel wide. Other tags imply attributes. Table heading cells default to centered and boldface.If you decide to learn basic HTML, to improve your blog posts, for just one example, my easyHTMLtutorial.com will get you up and running quickly. HTML is simple. It's also the underpinning of the second path to HTML documents.
JavaScript: document.write()
There are times when you leave the simplicity of HTML and use JavaScript programming to create your HTML customized to your viewer's data. My Ruby is one example: it creates a table of checkboxes based on the user's model. There is one row for each "layer" (grouping of model components) and one column for each "scene" in the animation. It can only be created after querying the user's model for, for example, a list of the names of each layer. JavaScript for my Ruby's table would look like this:
// query model for data
// construct a "model" object from the results
document.write( '<table align=center bgcolor=#fofoff border=1>' );
document.write( '<tr>' );
for ( var i = 0; i < model.scenes.length; i++ ) {
document.write( '<th>' + model.scenes[i].name + '</th>' );
}
...
This uses JavaScript's
document.write()
method to write HTML into the page. It is not as simple as plain HTML but it lets your UI be tailored to the users' specifics. In this case, it is writing as many column headings as the user has scenes in his model, using names read from the model. At a cost of one level of indirection, this creates a web page tailored to the user's data. Unfortunately, it is not always an option.DOM scripting
In my Ruby, for reasons I'll skip here,
document.write()
was not an option. While technically, simple document.write()
calls are a form of DOM scripting (Document Object Model), there is another, less simple, low level at which you can create a web page.Each web page is a set of objects attached to the "document" object, or attached to other objects which are, in turn attached to the document. In our table example, the table is attached to the document. The table row is attached to the table and the table headers are attached to the table row. Skipping lots of details, the basic idea is this:
var table = document.createElement( 'table' );
// set table attributes here
document.appendChild( table );
var row = table.insertRow();
head = document.createElement( 'th' );
head.innerHTML = 'The Column Heading Text';
row.appendChild( head );
...
Working at this very low level, your JavaScript is in total command. The cost: the simplicity of HTML is gone. If you have to drop to this bottom level, the amount and cost of the JavaScript rises dramatically. Switching from
document.write()
to bottom level DOM scripting was one of the reasons my two-week Ruby project took six weeks to complete."We don't go here unless we need to. Right, Monty?" Monty, my pet python, doesn't hear me. He's busy playing with the kitten.
Labels:
document.write(),
DOM scripting,
Google settlement,
HTML,
JavaScript
Friday, August 28, 2009
I Love JavaScript (Sometimes)
News:
From Business Week Big Blue's Global Labs
Building a global chain of "collaboratories." Good luck, IBM. May I loan you my copy of Fumbling the Future?
JavaScript:
Something like this:
That, obviously, will never work. This will:
Did I say "obviously"? That, obviously, was sarcasm.
When coding you exhaust all the rational possibilities first. With code still failing, you move on to the semi-rational possibilities.
After exhausting the rational possibilities, I briefly considered DLing the source for Mozilla, to just take a look for myself at the troubled area. Briefly. Just long enough to learn that there are about 2.5 million lines of code there.
It was Saturday, the 15th, when my Ruby writing ground to a halt with The Bug from Hell. I believe I can proceed again, albeit with the simplicity of
Started yesterday building tables the slow way. Create a table element and attach it to the body of the document. Create a row element and attach it to the table element. Create cell elements and attach them to the row element. Create contents and insert or attach (depending on type) content to the cells. On to the next row.
My UI includes a table with a table. It's very complex so that the user will think it simple. It took a half day to build it with
Anybody going to bet against more "gotcha"s?
From Business Week Big Blue's Global Labs
Building a global chain of "collaboratories." Good luck, IBM. May I loan you my copy of Fumbling the Future?
JavaScript:
Something like this:
btn.onclick = click_func;
document.body.appendChild( btn )
That, obviously, will never work. This will:
document.body.appendChild( btn )
btn.onclick = click_func;
Did I say "obviously"? That, obviously, was sarcasm.
When coding you exhaust all the rational possibilities first. With code still failing, you move on to the semi-rational possibilities.
After exhausting the rational possibilities, I briefly considered DLing the source for Mozilla, to just take a look for myself at the troubled area. Briefly. Just long enough to learn that there are about 2.5 million lines of code there.
It was Saturday, the 15th, when my Ruby writing ground to a halt with The Bug from Hell. I believe I can proceed again, albeit with the simplicity of
document.write()
in the rear view mirror.Started yesterday building tables the slow way. Create a table element and attach it to the body of the document. Create a row element and attach it to the table element. Create cell elements and attach them to the row element. Create contents and insert or attach (depending on type) content to the cells. On to the next row.
My UI includes a table with a table. It's very complex so that the user will think it simple. It took a half day to build it with
document.write()
. I'm thinking five times the code, and five times the time, doing it the slow way. That, of course, doesn't allow for additional "gotcha"s.Anybody going to bet against more "gotcha"s?
Subscribe to:
Posts (Atom)