real-time collaborative problem solving

I left work early to have time to walk along the ocean while the sun was still up. As I walked south along the sea wall, the pier eclipsed the sun. I saw a seagull limping oddly at the beach at the foot of the pier. I thought it was just injured, until I saw the straight, thin lines extending in the air from the bird up to the pier. Fishermen stood sillhouetted against the sky. A woman walking the other direction paused and said to me, "It's a shame. The bird's got a hook caught in it. It's a death sentence." I realized a boy was climbing down the seawall to free the bird, which was almost as big as he was. After watching for a minute, I said, "I'm going down there." The woman standing next to me said, "I would but I'm wearing leather clogs." I looked at her in a tidy corduroy blazer and slacks, then down at my sneakers, bought for $150 back when I thought I could afford such things, but now much worse for the wear. "Don't ruin your shoes," I said to her. "Can you do it, just you and the boy?" she asked. "We can do it. You don't have to come.""Hold on, kiddo, we're coming down there," she called to the boy, who had backed the gull against the pier's rusted metal base.

When I got to him he said to me, "I don't want to touch her." I didn't, either. I felt vulnerable and soft, could imagine the frightened bird squirming in my arms, scratching me, wings beating in my face, more horror. The woman with me said, "Don't cut the line. If you cut the line, the hook will stay in it, and it'll be a death sentence." In the back of my mind I thought about this: is a fishhook stuck in a gullwing a death sentence? Not necessarily, but maybe; it depends on where we cut the line and whether the hook had punctured her skin. The bird was actually caught in two lines. I pulled on one of them, felt the flexing fishing pole it was attached to, and called out for slack. We would need slack to do anything at all for the bird; if we cut the line while it was under tension, we'd have no control over the fragment attached to the bird. I held onto the line a few feet from the bird, reached out to gather up the other line and take the tension off the bird, and paused to consider the technical questions.

At this point the mood changed. The older woman began to harangue the men on the pier for a knife. Yes, harangue. I couldn't understand what the men were saying; they were just shadows against the bright sky. A woman wearing fleece and sunglasses leaned over the railing of the pier and called down, "don't cut the line. we're going to get scissors." I thought that scissors sounded great, but I didn't want to wait some unknown amount of time for scissors to appear. I decided to see if my keys could cut one of the lines. The woman beside me kept issuing instructions, but I honestly wasn't listening. I think a few times she said, watch out for the water, meaning that a wave was coming in. I mumbled, "that doesn't matter," not selflessly, but just wanting to ellide the problem of paying attention to the surf. There seemed to be an argument about how best to proceed. The serrations on my keys couldn't fray the nylon line; in the back of my mind I realized, this is why one should always carry a knife. I longed for my leatherman. "Don't leave the hook in!" the two women called out. "You've got to get the hook out!" Then their chorus changed. "He says his girl is coming down," one of them announced, and indeed I saw a young woman begin to pick her way down the rocks. The coming of the girl seemed to be considered by the men on the pier to be a complete and perfect solution; I was curious as to how she was going to fix the situation. Perhaps she was carrying scissors or a knife.

While she climbed down the rocks, another shouted conversation emerged; the woman on the beach with me was sarcastically repeating the fishermen's claim that the bird got stuck in the line all the time. "Yeah, right, he gets stuck in the line all the time!" she mocked. I didn't understand this, either. The same bird? What on earth was she talking about? I think what the fishermen meant is that a seagull stuck in their lines is not such a rare occurrence and not a cause for panic.

Indeed, the young woman knew exactly what to do. She used a rag she was carrying to cover and then wrap the bird's head; the bird stopped flapping. Now we had a topology problem, not a wildlife problem. This, I knew how to cope with. I passed the two lines, which I still held, to the older woman. "Take this" I said. "Hold this." Apparently my keys were in my hand, too, because she took those first. "Take the lines." I pressed them into her hands. I needed her to keep the lines slack, and I needed both my hands free. Then the girl and I knelt beside eachother in the sand and tracked the lines around the body, untangled the lines from the birds legs. To slide it underneath her, I pulled the line into the wet sand. I still didn't want to touch her much, but the girl held the bird's head in the rag and deftly extended its wings. Almost without words, we unwound loop after loop. She could tell that I didn't want to touch the bird much, so she did, gesturing with her chin and eyes at the next knot we should tackle. Two, three, six times the line was looped around the bird. The woman on the beach behind the girl and I asked, "should I hold her down? should I pick her up so you can get around her?" "No," I mumbled again, as the girl and I passed the tangles, bird, and sand back and forth between us.

Finally the line was almost free, disappearing into the bird's wing in the large flight feathers at what would have been her elbow. In my head I was picturing a bat skeleton, because I know bats better than I know birds. The hook might have been sunk into the flesh of her wing, or the line might be simply looped around the bone. Here again I didn't know how to proceed; I didn't know the shape of the hook, or how big it was, and I was not going to poke my finger into the squirming feathers to find out. I was definitely not willing to cut my hand on the hook in blind exploration, so again, I paused to consider the technical issues. I briefly imagined a cut finger infected with bird germs, which reinforced my desire not to find the hook by touch. The fishermen's daughter saw to the heart of it, though; the lines entered the wing feathers in two places. The hook was a few feet up the line, already controlled by the other woman holding the lines for slack. She held the wing open while I loosened the loop and finally freed the wing. I think there was another pause then; the girl gestured that I should step back, and she stepped back, and released the bird and the hood, at once. The bird flew away; I did not see it go.

I didn't know what to say to the girl who had held the bird and extended its wing. She had been so skillful and fearless. The bird would not have been freed if not for her. For just a moment I saw her skin glow in the red sunlight, saw her hair in the wind, saw her eyes shining; she climbed up the rocks and was gone.

The older woman in the clogs and corduroy was still talking; I began to understand that this adventure was part of a long narrative for her, of a small town homeowner resentful at the men who came daily to her neighborhood to fish from the pier. "They didn't want us to cut the line because they were so concerned with their precious fishing line." This was ridiculous; I pictured in my head spool after spool of fishing line on a rack in a store, and knew that a few meters of line would cost only pennies. "That's why they wouldn't give us a knife," she continued. "They were going to let it die." And then, strangest of all, she said, "I was saying 'don't cut the line' because I wanted you to cut it closer to her body so you could take the hook out. I didn't mean you should leave the line in her." In the same breath that she justified the instructions she had issued, she criticized the fishermen's motives for advocating the very same plan. She cared about the bird, in a save-the-wholes kind of way, but she had no immediate solutions to help it. She made plans and gave instructions, while actually doing nothing, until a task was literally thrust into her hands. When it was over she couldn't say, well done, or I'm so glad the bird is free; instead she went immediately to criticizing others. I asked her, "Do you see the bird? Did it fly away all right?" "Yes," she said. "I saw it leave." I found my footing atop the seawall and walked away, dirty hands, sand in my shoes, feeling for once my body as a useful physical implement and not simply a container for my soul.

Neat app for pesky windows product key

My windows xp license comes from an MSDN subscription; there's no orange sticker with the product key. I wanted to start over with Parallels, because one of my windows vm's had eaten itself. (When I start the vm, I get an empty pale blue screen with a sedentary pointer. It used to work. The joy of windows.) To find the product key, I ran Magical Jelly Bean Keyfinder in one of the vm's that hadn't eaten itself yet. Easy as pie, there's my windows product key.

Now I'm rebuilding my windows vm's with Parallels 2.2, following this carefully planned strategy:

  1. Create a new clean VM using Parallels' Install OS feature. Do not use the Express Windows XP Install; the express install requested the XP SP 2 disk, which I don't have sitting around. The express install gave me a pre-hosed VM, so, I recommend the custom windows XP install. Don't turn on auto-update; developers will want to manage their updates themselves. You'll need to enter your product key here.


  2. As soon as the initial install is completed, before running Windows Update, clone that VM, saving a clean copy of the fresh install into an always-clean image. (Does that sentence say 'clean' enough?)


  3. Run the cloned VM, and now run Windows Update. I also let windows activate at this point, which I hope doesn't muck things up later.


  4. Clone that VM, the uptodate, clean one, and save off a copy.


  5. Run the cloned VM and install Firefox


  6. Clone the uptodate-and-clean VM again; install cygwin.




and so forth.







powered by performancing firefox

low expectations surfing

Rules of thumb for re-learning to surf when thirtysomething:

  • Beginner surfing is almost equivalent to playing in the water... so you might as well just play in the water and enjoy yourself.

  • No one is paying any attention to you. Be as dorky as you want.
  • Getting tired in the ocean is bad. Therefore, get out of the ocean before you're tired.

  • Getting cold in the ocean is to be expected. Don't worry about it.

  • Pretend that everyone else in the water is either a beginner or as old as you or both.

  • Pretend that everyone else in the water is very nice and mellow.

  • Pretend that everyone else in the water is trying to kill you, and stay well out of their way in the breakers.
  • Never turn your back on the sea. (This feels like an old sailing safety tip, but I can't remember where I would have heard it. I've never done any ocean sailing.) The waves in the shallows can still bowl you over, and getting held under in one foot of water really hurts.

  • If you're scared, go to someplace that scares you less. This is the fucking Pacific Ocean we're talking about here, and what will it prove to be a tough guy? The ocean can always kick your ass. get in the water whenever you might possibly have a chance. Even in November. With a beginner's mind, it will always be worthwhile.

If anyone surfs at Linda Mar and sees me playing in the breakers, please don't disillusion me. Except maybe about the "you're trying to kill me" part.





powered by performancing firefox

A java applet that actually works

Java applets on web pages haven't worked properly for me, pretty much ever. Educational applets work, but if there's any b2c relationship going on, it never works. Usually if a web page even tries to launch an applet, I kill my browser before java takes over my entire machine. When I have actually tried to complete a transaction using a java application, I lost money. (It doesn't take losing much money on a technology to decide not to use that technology again. About forty dollars, in my case.)
The only reason I tried another java applet was that the alternative was waiting on hold for "the next available representative will be with you shortly." So I watch incredulously as Comcast (my internet service provider) launches an applet for chat with a live representative. I waited a few minutes, watching the West Wing Season 7 on dvd, then an analyst appeared. I described my problem, and s/he asked a few more questions to verify my identity and to pin down the problem. Then (mirabile dictu!) she sent an updated signal to my cable box, and said that should fix it within the hour.
This sort of technology was totally workable nine years ago, 1997, when I worked on a java applet for playing (ahem) the Dating Game over the net. It was totally workable four years ago, when everybody in educational technology was writing and sharing applets. Four thousand ways to learn the pythagorean theorem! I'm down for that. What was missing before was enterprise integration. The tech support rep got my information via the applet, and moved that information quickly into the cable tv service monitoring system, wherein she took action and solved my problem. (I hope.) The purpose of this interaction was getting my service fixed, and the applet worked for me, because I find internet chat more convenient than phone hold. They used ten year old technology integrated with their core systems to create a better user experience for a paying customer. So we're back to the fundamental lesson of usability: it's about the people, not the technology.
In the time it took me to write this blog entry, my cable box has indeed received new information which corrected the problem I was having. And... the technician was in Colorado. (Another Turing test variant: is the tech support person located in the same country as you?) Comcast, I salute you for providing excellent customer service tonight.

stanley tucci can be sexy -- who knew?

The new CBS medical drama, 3 lbs, is my favorite new show of the season, beating Aaron Sorkin's latest effort and the other nbc show about nbc shows. When I heard about this obvious take-off on Fox's House, I thought, "Stanley Tucci? Why would I want to watch him for 47 minutes in a row? And why do I need another doctor drama?" It doesn't sound good, but there was a free download on iTunes, my dvr is on the fritz, and netflix is in a dull period. I turned it on an hour ago and couldn't move from in front of the screen, entirely forgetting the pasta on the stove and my home-rewiring projects.
Remember what happened in Pulp Fiction, when Bruce Willis makes his first appearance onscreen, and we all thought, "Christ, where'd he get thirty pounds of muscle at his age?" Same thing here with Stanley Tucci, but instead of a sweaty boxer pulling off his handwraps with his teeth after killing his opponent, we've got a gratuitous shot of Tucci as he changes into scrubs. The writers went a bit far to make sure we noticed Stanley's physique; they actually put a beautiful woman in the locker room with him, and gave her the line, "you look hot!" The writers can relax: we get it. Strange but true, Stanley Tucci is hot.
If you don't care about medical drama or well-defined biceps, this show is still worth watching for the use of music. The illness = dissonance / health = harmony metaphor is well-traveled, but 3 lbs connects the music back to the characters' narratives with a sincerity I haven't seen since yet this century. With DEVO and Talking Heads and Lisa Simpson and TMBG, music became defiantly ironic. Crooners weren't cool anymore. Which brings me to the 3 lbs coup de grâce: 'Fix You' by Coldplay. This song is so perfect accompanying the episode's climax that I hesitate to write about it here and risk spoiling the moment of recognition for my few readers who intersect the emo/indie music world with the new-fall-season crowd. 'Fix You' features an Edge-like guitar riff that reminds me of the best bits of All That You Can't Leave Behind, and a clarity of vocals that recalls, no shit, "Sweet Baby James." The song fulfills and unites themes of vulnerability and interdependence crafted with Poe-like attention to detail from the first notes of the opening scene. (Wasn't there a 9/11 movie which tried to use this song as the anthem for "the defining moment of our generation"? Sorry, no.)
My Grandma Bea would have liked this show. Perhaps the only thing about which I ever actually related to her as a human being was our shared adoration of George Clooney. Stanley Tucci would have been just right for her. But she probably wouldn't have understood the Coldplay reference.
Note to relatives: no, I am not going back to medical school.

Open Laszlo 3.x vs Open Laszlo Legals: About that tablecloth...

Jim Grandy wrote

the magician yanks the tablecloth out from under the place settings for an elegant meal, leaving the wine glasses and candlesticks in their places, unperturbed. A neat trick, but even better would be to replace the tablecloth with a new one, all without touching the candelabra or the crystal goblets. I’m not usually given to hyperbole, but with our latest Legals snapshot, PR3, we are nearing the end of a process that feels a lot like replacing the tablecloth.
Developers have started looking at the preview releases, and they're noticing that not only is the DHTML runtime incomplete, but the swf runtime has major regressions. "What's with all these regressions? Isn't that a bad indicator of code quality? Is the next version of Open Laszlo going to be worse than the current one?"
Well... I can see how this is worrisome. Let me offer this adjustment to Jim Grandy's analogy: Legals doesn't just replace the tablecloth; Legals sends the chef to culinary academy. The chef comes back from culinary academy, and changes the sautée pans, the waiters' uniforms, the produce supplier, and the actual furniture... but he leaves the menu the same. And, yes, he keeps the same silverware and china. That nasty ceviche appetizer is made with tuna instead of snapper, and the house salad uses butter lettuce and hothouse tomatoes instead of iceberg and cherry tomatoes.
What I'm trying to say here, while perhaps pushing the analogy too far, is that Legals changes the compiler and the Laszlo Foundation Classes. A lot. We refactored the Laszlo Foundation Classes into the runtime-independent parts and the runtime-dependent parts. In 3.x, the LFC code assumed that it was executing in a flash runtime. The 3.x LFC wasn't shy about reaching down to touch the flash movieclip directly. Legals inserts a portability layer between the LFC and runtime-dependent code; we call this portability layer the kernel. Everywhere that LFC code, components, and examples assume a flash runtime needs to be refactored to call the kernel API. So, you see, just about every line of the LFC has changed, even for the swf runtime. All that change was bound to cause regressions and introduce new bugs.
Here's the good news: we're software engineers with a track record of shipping solid software. We manifest our commitment to high-quality software by fixing bugs properly not just expeditiously. This stage right now is the right time for fundamental architectural changes and thorough discussion and investigation thereof. We have a large set of unit and integration tests, which we run, and ever-improving tools for tracking, assigning, reviewing, and fixing bugs. At any given time, several team members are devoted full-time to either increasing test coverage, improving test tools, or fixing known bugs.
When you sit down to eat at the new restaurant before opening night, the table might wobble, and there might be too much cayenne in the chili. But we're fixing the table by switching to a three-legged design, not just shoving a wad of napkin under one leg. We switched to venison and buffalo chili, so we're fine-tuning the spices with every batch we cook. We're working hard on getting it all back to solid and tasty, and we won't open the kitchen until taste-testers have approved every dish.

"there's more than one way to do it"

TMTOWTDI is pronounced tim-todd-ee and it means there's more than one way to do it. I think I picked this up from Programming Perl or Learning Perl. I didn't really learn to program or learn perl, from consulting those books, but I did learn TMTOWDI... which is kind of a problem.
I'm working on a relatively simple task: measure, store and analyze benchmarks for Open Laszlo runtime performance. The problem is that there's so many ways to do it! My thinking started with Java, because most of the OL server is written in Java. Indeed, I implemented the measure-and-store part of the problem with Java Server Pages (JSP). Now it's time for log analysis, and ye gods, Java has been through major honking changes in its support for logging, regular expressions, and XML. There is a surfeit of XML API's for java; in java 1.4 or so log4j-ish behavior became part of the java platform, in java.util.logging; Xerces, Xalan, SAX, JAXB, and JAXP all seem to do pretty much the same thing (parse XML) but Xerces and Xalan were merged into another project, and JAXB and JAXP seem to be just implementations of SAX. Maybe. And how does this all relate to java.util.xml? On the way-back machine that is the WWW, projects from 1999 and Java 1.1 can be nearly indistinguishable from a project from 2006 and Java 1.5. And how can I distinguish between an abandoned project and a project which is so stable that it hasn't needed an update in two years?
...Then the java code that does seem relevant seems to require a heckuva lot of boilerplate. All I want is a bit of regular expression support and math!
That sort of thinking leads directly to perl. Perl has superpowers and was designed for just this sort of task, but I'm not a perl programmer, and I don't want to be. Sorry. Does that make me a bad person? Lazy, maybe: I'd rather spend my time learning and working with a language that I like. I'm not talking fundamental goodness here; I'm talking personal preference. I don't like the idioms of global variables with names like "$_".
Personal preference leads me to Ruby and JavaScript. Ruby, oh you tasty jewel, would be a pleasure to write this log analysis and reporting in -- but ruby is one of the few languages that isn't required by the Open Laszlo tool set yet. A disciplined software engineer wouldn't add a new language requirement to the development environment on a whim. JavaScript would be darn nice, too, especially using E4X, ECMAScript for XML. Is E4X supported by the version of Rhino we use for unit tests in Open Laszlo, rhino 1.5R3? I just spent ten minutes browsing mozilla.org trying to figure this out, and I still don't know. (This feels like what I'll end up doing, though.)
My high school fencing teacher used to say, "don't parade your ignorance" and maybe as a career web programmer I'm hurting my future prospects by confessing confusion with all these API's. So I'll skip rhapsodies on python and bash and XSLT, and just get to the point: TMTOWDI, so let's just get it done! All of these languages and libraries can get the job done, with a complex set of trade-offs between brevity, readability, maintainability, portability, external dependencies, and personal preference. It doesn't matter. Just pick one and get on with it. Stop trying to figure out which one is best; stop trying to grok new technologies while standing in an aisle at Barnes & Noble. What would get me from here to performance benchmark analysis by tomorrow? Straight-up java parsing. Forget XML, just use line-based text parsing with a string tokenizer. Forget object serialization. Forget XSLT. Forget trend graphs of benchmarks over time. Just use plain old text files, and get the job done.
(If I get to producing a simple report with single-number reports on the performance of three different builds, today, then I can play with Ruby while watching Desperate Housewives.)

UPDATE (eight hours later): I wrote the tool that I need in a few hours, using java's StringTokenizer and JUnit. I also went for a walk along the beach and took a nap. Shiny things: IntelliJ IDEA 6 integrated JUnit support. I'm in love with the green bar.

Porting to Legals

In a post on the Open Laszlo forums, rcyeager of cooqy described his experience trying his Open Laszlo applications in the latest preview release, PR4:

The demos in the PR4 Explorer work...but my "real-world" code fails miserably. I expected DHTML conversion issues, but to lose support of SWF mode compatibility is scary...and this is with Legals supposedly going to Beta soon? In my case, 100% of my V3 apps don't work in either SWF mode or DHTML w/ Legals PR4. Is anyone getting better results with their real-world V3 apps running in Legals?? So far the attempt by Legals to pull the tablecloth out from under the dishes has left my lobster dinner strewn all across the floor...

Jim Grandy's post about Legals Preview Release 3 sets the stage. My perspective on porting existing applications to the multiple runtimes infrastructure is based on converting the calendar demo. A few highlights:
  • swf assets won't work in DHTML. To display a swf asset, you'd need the flash player; we're not using the flash player in DHTML, so, swf assets just won't appear. The solution here is to use bitmap assets instead of swf's.
  • We haven't made all the components work yet in PR4. We've got open bugs in JIRA for all the component problems.
  • drawview support was just added in the last few days; it's not in PR4. Look for it in beta 1, at least for firefox. (IE support is still in progress, I think.)
  • DHTML doesn't support embedding fonts; swf does. If you try to embed a font, you'll get a compile warning, and the text will look ugly, or it won't appear at all.
  • The flash runtime is permissive about derefrencing a null reference and getting properties on an undefined object. DHTML blows up if you do this.Because it was permitted in swf, lots of code doesn't check for null. All the places that don't check for null need to be tracked down and fixed, both in the LFC, the components, and application code. This was the source of at least half of the problems I had.

The overall story is that we're still getting up to feature-complete, and we know we've got a lot of optimization and bug fixing ahead of us. We really appreciate all our users, especially when they take the time to post their concerns and problems. Keep the bug reports coming, and we'll keep working.

changing values

Doing laundry instead of shopping for new clothes. A simple meal cooked and enjoyed at home, instead of another $16 meal from a thai restaurant. Getting a great deal at Sports Basement instead of overnight shipping on a plastic-within-plastic patagonia mail order. Neighbors who know my cats' names and all three of my names, instead of neighbors who genteely avert their eyes if we cross paths in a hallway. My threadbare collge sweatshirt instead of a pre-stressed sweatshirt with the name of a surf competition that never happened at a beach that doesn't exist. Spending time with my cats on the back porch, watching them bat at moths, instead of battery-powered pet toys with fluorescent feathers. $10 key-combo software instead of a new keyboard with literally buttons and whistles. Running a line from the cable box to the clock radio, instead of buying new speakers. Discovering old music in my collection instead of "Discovering New Music" at Starbucks. Self-serve locally-roasted Kona Blend instead of a six-dollar latte. Rereading my favorite books instead of buying the flavor-of-the-week at Barnes & Noble Big Box.
It's not just that these things cost less than the alternative... It's that they actually feel better. You couldn't have told me this ten years ago, or even five. I used to think that costing more money inherently made something better than any lower-cost alternative. I used to think that new meant luxurious, and old meant moldy. I used to think that bills were just greeting cards with numbers on them. And today, just today, I'd rather have a little less debt than a little more stuff.

Constraint maintenance in Open Laszlo

Sometimes someone says something so clear that part of my worldview crystallizes, creating order where before there were only vague ideas. A few weeks ago, "tomcat is a servlet container" hit me this way. Today, it's getters and setters in Open Laszlo. In recent email to the laszlo-dev mailing list, P. T. Withington wrote:Before my time, I think we had getter's that pulled values, now we have setters that push them, and getters are only there for back-compatibility.

I understand this, I think: Open Laszlo is permissive about accessing an object's attributes. Open Laszlo maintains a one-way constraint propagation network. If value x changes, then any constraints which depend on x must also change.

<attribute name="x" value="70"/>
<attribute name="hotness" value="${x * 3}" />

To maintain the desired constraints, hotness must be recalculated whenever x changes. There are (generally speaking) two ways to maintain this dependency: "push" or "pull."

In a pull system, hotness would only be recalculated when it's accessed. Between the moment when x changes and the moment that hotness is accessed, hotness is in limbo; it doesn't reflect the value of x. That doesn't matter as long as you only access hotness with an accessor method. While the value of hotness is unused, it doesn't matter. However, if you change x and then access hotness directly, you are not going to trigger the constraint recalculation, and you'll get an old dirty value of hotness:

// Pull system example
Debug.print("hotness is ", myobj.hotness); // prints "hotness is 210
myobj.x = 12;
Debug.print("hotness is ", myobj.hotness); // error, prints "hotness is 210"

To get the right value of hotness in a pull system, you'd have to call the getter:

// Pull system example continued 
Debug.print("hotness is ", myobj.hotness); // prints "hotness is 210"
myobj.x = 12;
var t = myobj.getAttribute("hotness");
Debug.print("hotness is ", t ); // correct, prints "hotness is 36"
In a push system, hotness would be recalculated when x changes. The runtime maintains a list of the attributes that depend on x, and when x is changed, it tries to inform interested parties of that change. (This is really handled with delegates, but that's an implementation detail.) The runtime needs a chance to push the changed value into hotness and charm. It only gets that chance if a setter is called:
// Push system example
Debug.print("hotness is ", myobj.hotness); // prints "hotness is 210"
myobj.setAttribute("x", 12);
// Behind the scenes, delegates update hotness and charm.
Debug.print("hotness is ", myobj.hotness ); // correct, prints "hotness is 36"

Open Laszlo uses a push sytem for constraints. It is safe to get the value of an attribute with simple object access myobj.hotness but it is not safe to set the value of an attribute by direct access without calling the setter. To set an attribute which is an independent variable in constraints, you must call the setter." Setting a value directly, without the setter, can only be done if you don't need dependent constrained values to update. This is dangerous, but fast.

Understanding Tucker's quick quote explains why some code uses getters (an old idiom, no longer necessary, but valid) and some code uses setters. (They're required for constraint updates.) The correct, safe idiom is to only set attributes with setters. When this is too slow, setters can judiciously be replaced with direct assignment. Why do we use a push system? Performance. Typically the ratio of sets to gets of properties in a program is 1:4 1:5, so it is more efficient to only have to intercept the sets.

Postscript: Tucker adds, "setAttribute should be an implementation detail too, some day. The compiler really ought to intercept your attempts to set properties that constraints depend on and do the right thing."

Alternate ending for The Departed (not a spoiler)

Colin Sullivan runs into the woman's apartment, hoping he's gotten there before the bad guys. He's too late, but she's still alive, gagged and tied to a chair! They spared her life, but took her (horrors!) right hand and wrist! As soon as he removes the gag from her mouth she gasps, "the sink! the sink!" He runs to the sink where her fingers are just barely visible in the maw of the garbage disposal... which is on! In perhaps vain hope of reattachment, he scrambles to find the off switch, and simultaneously to remove the severed hand from the drain. But (again!) he's too late; he grasps at the fingertips; he can't get a grip on them, but the motion of the disposal on the tendons opens the fingers, releasing... what? A travel-size game of Clue, the classic Milton-Bradley board game! The camera zooms in on the pristine label of the game, and the sink and the desperate man and the brutalized woman are replaced with an advertisement for a new, The-Departed-branded special edition of Clue, based in not a crumbling mansion but a map of the Massachusetts State House, with butlers and professors replaced by, ahem, cops and lawyers. With the characters fate implied but unknown, the bad guys probably drinking Guinness in a bar in Southie, and the marketing deals solidly in place (the Clue special edition includes a DVD with the theatrical trailer for the movie! and a real replica "T" token!), the credits roll, and we (the self-forgotten audience) are sitting in the theatre dumbfounded, all of our passion and excitement and dread created by the ever-onrushing story replaced with a none-too-subtle feeling that our lives would be this exciting, too, if we were much worse people, but given our straightforward allegiances and Judaeo-Christian values, we can at least spend a sunday afternoon (the concluding anti-climax product placement tells us) pretending we are as vital as William Caustigan, Jr, as ethical as Captain Queenan, as powerful as Frank Costello, and as vicious as Mr. French. And yet... we are simply the bourgeoisie, resembling these brazen, sultry, consumed characters only in that we, too, are doomed to die.
FIN.

tuesday is tools day

Today is a big demo day for Open Laszlo at Ajax World. where we're showing off more progress on our multiple runtimes infrastructure. I've been heads-down crunch-mode working on demo apps for a week, so I think today might be tools day. A few months ago I rebuilt our nightly build system, and by now it's become clear that it's really a build-on-demand system. The turnaround from checking in a bug fix to running an official build on a qa machine could be about a third what it takes now, if I parallelize it. The build is already distributed onto three machines and three OS's, but it runs those three builds serially. Worse, it doesn't even parallelize pushing the distros from build machines to distribution machines. I can improve this a lot, pretty easily. It doesn't feel as <em>urgent</em> as fixing bugs in demos or tracking down bugs in the DHTML kernel, but I think it might actually be more <em>important</em>. Saving thirty minutes each time we're waiting for an official build adds up to real time, especially with some big releases coming up. Time is more precious when preparing for a release, so saving time in the release process saves extra-special time. I've convinced myself, so, it looks like tuesday is tools day for me.

release excitement

Release excitement is starting again, on the OpenLaszlo front. We're working towards Legals-PR4, which means preview release 4 of the multiple-runtimes platform. We're simultaneously working towards 3.4, which adds video, CSS, and many charting & graphing bug fixes to lps-3.3.3. And I'm playing my favorite role, working on a demo application to show off the technology. Watch this space... in a week or so I'll have some hot stuff to show off. Just imagine it... you write a RIA in lzx, and with the flip of a switch, it runs in DHTML and in the flash player. A real application, I'm talking about, here. I love this part of the project cycle, when people from different efforts come together towards a common goal. I'm working with these masterminds who seem to be able to take any weird thing I throw at them and come back with a workaround in a few hours. It's a good day when I come home from work and can't wait to plug my machine in and start getting back into it. And I know that I will wake to an inbox full of expert discourse on dynamic language and library design. I love working at this company.

OpenLaszlo debugging tips from Tucker

The OpenLaszlo debugger has many features that I haven't learned about until recently. The classic println in OpenLaszlo is just

Debug.write("My message, hooray.");

This method is variadic and clever. Comma-separated arguments are printed as "live" debugger objects.

<method name="doSomething" args="x">

Debug.write("This is", this, "and x is", x);

</method>

gives you this...

This is #theView and x is 27

See how #theView is blue? That indicates that it is live. Click on the blue text
and the debugger will print (almost) everything it knows about #theView.

lzx> Debug.inspect(#theView)
#theView {
_events:
[LzEvent, LzEvent]
_instanceAttrs: «Object#1#3| {id: theView, bgcolor: 2383748, height: 40, width: 40}»
_instanceChildren: «undefined»
addedToParent: true
bgcolor: 2383748
doSomething:
«Function#4| theView_doSomething»
hassetheight: true
hassetwidth: true
height: 40
id: theView
immediateparent:
«LzCanvas#5| This is the canvas»
isinited: true
mask: null
nodeLevel: 1
onheight:
#theView.onheight
onvisible: #theView.onvisible
parent: «LzCanvas#5| This is the canvas»
width: 40
}
«LzView#0|
#theView»

All of the strings in blue are also clickable; clicking them will print the results of Debug.inspect(it), which may in turn yield more clickalbe, inspectable objects. But this is all kid stuff. Let's get to the power tools. The underscore character is a shortcut for "the last thing the debugger printed," in this case, #theView.

lzx> _
«LzView#0| #theView»

I can call a method on #theView by typing

lzx> _.setAttribute("bgcolor", 0x777777);

and the bgcolor of my view changes immediately.
The last three values the debugger has printed are stored in variables named _, __ and ___.
Up-arrow and down-arrow retrieve this history of commands. Up arrow, return repeats the previous command.

Debug.monitor(who, what) prints out a message each time a particular
property (what) of a particular object (who) changes. Debug.monitor is documented in the developer's guide and is present in 3.1 through 3.4, but not yet present in the DHTML runtime.

And finally, backtracing! Edit the lps.properties file, in $LPS_HOME, to say

compiler.debug.backtrace=true

then you can call Debug.warn('foo'), Debug.info('foo'), or Debug.debug('foo') in your code and it prints a string which you can click on to see the backtrace from that place. If you use
Debug.trace(<object>, <method name>) or Debug.monitor(<object>, <attribute name>) the messages that those output (at function entry/exit or on modification of an attribute) will include a backtrace too.

(Thanks to Tucker for implementing and explaining these tools.)

Latest developments at Laszlo Systems

Laszlo Systems just announced a Series C funding round of $8 million. They like us! They really like us!
Meanwhile, I've been working on an implementation of CSS for OpenLaszlo. Adam Wolff and I have been doing the work in a developer branch, coal. Our CSS implementation is planned to be released as part of OpenLaszlo 3.4. Unlike the bone-deep changes to DHTML programming paradigm with the adoption of CSS, the dominant paradigm for writing OpenLaszlo applications will still be to write lzx classes and scripts. OpenLaszlo, unlike DHTML, was designed from the beginning to be a presentation and interaction language, so it has far fewer empty spots to spackle over with an additional syntax layer than did pre-dynamic HTML. CSS will allow for themes, skinning, and a smoother designer/programmer collaboration workflow.

  • We're supporting a big subset of CSS 2.1 selectors: element type, attribute selectors, id selectors, and descendant selectors, while leaving out .class selectors, sibling selectors, pseudo-elements and pseudo-classes.

  • CSS rules are evaluated at construct-time to determine attribute values for any attribute of any node (just about).

  • We have introduced style constraints to specify how to map CSS style properties onto lzx attributes; these are much like the $once, $always, and $path syntaxes already present in OpenLaszlo.

  • There is compiler support for CSS, which feeds the runtime CSS engine.

a little bit of yiddish

A friend of mine commented to me recently that he is "culturally Jewish." The discussion moved on to cynicism, genX, and my friend's refusal to engage in the former despite being a member of the latter. Later though I reflected, "Am I culturally Jewish?"
I more commonly identify as a "New York Jew" than (just) as jewish; my membership in this sub-sect is mainly signified by my sunday morning ritual, involving lox, bagels, and the New York Times. That is certainly the jewish tradition in which I most consistently participate. I also often think about attending friday night services; ambivalence about participation in religion seems to also be part of being a New York Jew. (I don't think my dabbling in Unitarian Universalism (very cool) or TM (sigh) particularly excludes me from the Tribe.)
My most Jewish daily behavior, though, is invoked as a habit when someone else sneezes. I say gesundheit when all around me everyone else says bless you or god bless you. "Gesundheit" means "be healthy!" in Yiddish. "Gesundheit" is pragmatic; why invoke the blessing of a god that neither I nor the sneezer are sure exists and cannot characterize as a being capable of nor interested in issuing a "blessing"? [In my various lives as an east coast academic or a silicon valley salariman, I assume that most of my contacts are agnostic, atheist, or unitarian universalist.]
So to all of you I say, unprompted by a sneeze, cough, or elevated low-density lipids in your blood work, gesundheit! Because no matter which god you or I do (or don't) believe in, no matter which god we were raised to identify as the One and Only God, no matter whether we cynically or sincerly identify as a member of a particular religion, I do sincerely want you to be healthy and happy. So far as that goes, I'm willing to be a New York Jew, and I claim my heritage with this daily invocation. Gesundheit!

cognitive-behavioral therapy for controlling anxiety (about terrorism)

As has been said many times before, the "war on terror" makes no sense; terror is an emotion, and attacking an emotion or defending againstan emotion is best left to cognitive-behavioral therapy. In the parlance of CBT, we challenge a possibly irrational emotion (say, "terror") with rational thoughts. "The city where I live has never been a target for terrorrism. The city where I live is not an icon of american expansionism. Most people bring harmless beverages onto planes. Most people wear harmless shoes on planes."
The "homeland security" efforts, the boots-on-the-ground in Iraq and Afghanistan, the reactionary travel policies, the color=fear scale, reinforce the (questionably rational) fear of "terrorism." It actually would be pretty rational to infer a real risk of danger from huge efforts by the government to "protect" us -- if we stipulate that "the government" will behave rationally. Which, sadly, it does not.

surfing in water

I spent the first part of yesterday trying to grind through various paperwork and online bill-paying and bookkeeping and such. These activities brought me to a fairly familiar state of low-grade anxiety and self-recrimination. (Lately I haven't been doing many financial things about which I later feel guilty. Quite the opposite.) Then some new Pacifica friends took me surfing; they provided a wetsuit, a longboard, and encouragement. We loaded some boards into the Element (finally this car fulfills its purpose in life!) and drove to Linda Mar. My anxiety at this point was directed at something about surfing, but honestly I can't remember what at this point. Got into the wetsuit, carried the board down to the water, got in, started paddling out...

Then
everything
else
disappeared.

Whoever created the pacific ocean, thank you.

musings on small pieces of paper

I tried the hipster pda with vanilla 3x5 index cards, $4 for 1000, popularized by Merlin Mann. I tried it, but the cards were too white trash for me. Literally. While I was planning my third cross-country move, I splurged on Crane pure cotton 3x5 cards. They were beautiful and strong, but really, $22 for 100, that's insanely expensive. I looked lovingly at Levenger cards; they register higher on the quality-meter than supermarket index cards. I indulged in these when studying for the MCATs, and I'm glad I did. I made a few hundred flashcards and kept them for a year; good design makes it easier to tolerate endless drilling. But Levenger cards cost too much ($44 for 1000) for GTD-style short-term disposable usage. I find Post-it index cards incredibly offensive, design-wise. The rules are far too dark, and the sticky backing literally attracts dirt and lint, which then ends up marring the face of the card behind the dirty/sticky card. The Real Simple index card deck caught my attention, but it suffers from horrible colors and too-wide rules. I honestly don't understand how the people who fetishize moleskine notebooks can tolerate all these loud, rough-edged designs.

My favorite so far: Paper Source business card blanks. Except that (ye gods!) these are $1.50 for 25 cards. Six cents per card? Yuck.

I just bought a deck of long, thin, oval index cards by Umbra and found them entirely the wrong size to play Freecell. (Which is a whole 'nother blog post: why it's better to have time-wasting fun activities that don't involve the computer.) Now I'm experimenting with combining them with a fisher space pen for a cool-shaped hipster pda. Thinking about it in the light of day, though: I paid maybe $5 for 52 cards. This is not a good long term plan.

My latest greatest innovation is using Umbra Meow Playing Cards as bookmarks. Each card has a lovely illustration of a different cat breed, and they're a great form-factor for bookmarks. $5 for 52 cute-as-a-button bookmarks is a big win.

And, ahem, Kitty Spangles Solitaire is really the bomb for mac os x solitaire.