Reflections of a JS guy on AS3
6 months ago / 0 Comments
I've been doing a bunch of stuff with AS3 at Slide, and as a long-time JavaScript guy, thought it might be interesting to record my impressions of the language so far. I'll do the bad news first, so I can end on a positive note.
The bad news
Type annotations
Not a fan of the type annotations. I realize this was supposed to be one of the improvements to JS from ECMAScript 4, but so far there has not been a single instance where I've thought "wow, thank FSM I had that static typing to keep me safe."
I know this is jumping into the eternal static/dynamic typing debate, and I skew entirely toward the dynamic. But the reality is that I've met multiple people who've moved from using say, Java, to Ruby or JS, and they always talk about how painful it is to go back to Java. The awful verbosity is one of the reasons.
I see stuff like this in AS3:
var mySprite:Sprite = new Sprite();
This just seems silly.
It's also worth noting that with typed functions you can't have multiple return types from a function now, either -- for example, returning a string on success, and null on failure. (Okay, you could just type it as Object, but that seems pretty pointless.)
// Hello, pretty much everything is an Object // Why am I typing this at all? public function foo():Object { // I'd kinda like to return different stuff here }
And now I have to think about two different types for unassigned variables -- one for typed ones (null) and one for untyped ones using the asterisk annotation (undefined, like old-fashioned JS).
// This has a value of null var foo:Event; // This has a value of undefined var bar:*;
Now, there may be benefits to it that are a little bit invisible to me in day-to-day dev, like performance. But with the huge advancements in JS interpreters like the ones we're seeing in TraceMonkey, V8, and SquirrelFish, I'm a lot more dubious about the cost-benefit offered by the static typing and a compile step.
Access modifiers
Seeing all this public/prviate stuff everywhere makes me feel like I'm using Java. Maybe that's the whole idea; I don't know.
At one point I was reading documentation on the Adobe site, and it took me about 10 seconds to realize that a large chunk of code I was looking at actually was Java, not AS3.
Using enclosing scope seems mostly fine for private vars in JS. I guess the implicit binding of all the local vars to this in instances in AS3 makes that impossible, but I get the feeling that some guys really like all the delicious explicitness they get from having to pedantically declare all this stuff.
For me, it's mostly just more crap to have to type, and more noise to filter out when I'm trying to read code.
Closed classes
Again, this is supposed to be a feature. But overriding specific behavior in a class (in say, for example, testing, which is what I'm working on) requires endless subclassing, and having to think about inheritance-chain specificity way too much.
The most annoying example of this so far was some code that needed to accept various types of Events, but some of the containing code might call methods on a specific subclass. The compiler really doesn't like that.
The only way I can see to handle that is to use the "any type" asterisk for the annotation for that param, which kind of raises the question of "this static-typing stuff, it's good for exactly what again?"
Subclass 'super' invocation isn't really a function call
The correlary to this endless subclassing-annoyance is that I can't call a subclass's constructor method with Function.apply, and just pass it the same arguments as the constructor. There are couple of old mailing list threads from back in 2007, one here and the other here that talk about this.
Even after reading these I'm still don't get the rationale for this is -- but as a mere workaday developer, I do know that forcing me to type long lists of parameters mechanically on top of the endless subclassing is horribly tedious and error-prone.
Compile step
Hate it.
I guess I'm way too ADD, or spoiled by JS Web-dev work, but I need my instant gratification. Sitting and waiting for five or six seconds for multiple interdependent SWFs to compile totally breaks my workflow.
I feel like I'm spending a disproportionate amount of time making the compiler happy, and less time thinking about what my program actually does.
Object keys don't iterate in insertion order, WTF?
Okay, so I get that this isn't in the ECMA-262 Edition 3 spec (and don't know if it was supposed to be in ECMAScript 4), but every major ECMA implementation iterates over an Object's keys in the insertion order.
I'm not sure if it's a huge perf-killer, or if they just didn't get around to making it work right, but it seems pointless to position AS3 as "JavaScript with improvements," and then screw up something so fundamental. Before you implement all the improvements, how about getting the basics right?
(And by 'right,' I don't mean "bare minimum correctness according to the spec," I mean "at least as good as the other implementations.")
The good news
A real 'for each'
It's really nice to iterate over items in an array without the tedious array-index incrementation. This is so much nicer, so much more readable:
for each (item in someArray) { // Do stuff to item }
Yes, I know this already exists in newer JavaScript implementations -- but we can't use it until old Internet Explorer albatross goes away.
Checking for the existence of an attribute
So nice to stop using the janky test for whether a property's typeof is undefined. Now I can do:
if ('foo' in bar) { // Do stuff }
I really like this syntax -- way more much readable.
If these kinds of syntactic niceties are in the more-modest ECMAScript 5, I'll definitely continue to be a happy JS programmer.
In Short
I guess it's pretty clear -- what I like about AS3 is its similarities to the JavaScript I know and love, and the small syntactic fixes to what have always been obvious JS warts.
What I don't like is all the Java-like verbosity which, thankfully seems to have died in the main JS evolutionary branch with the ill-advised ECMAScript 4 adventure.
New gig at Slide, new digs in SF, new ... Python?
7 months ago / 0 Comments
Okay, yeah, so I've left the blog pretty quiet the last couple of months -- it's been a busy time with lots of changes.
After being without a full-time gig, doing a bunch of contract work, and looking around a lot, I accepted a job offer from the nice folks at Slide. The position is in their office in San Francisco, so in the last month I've moved myself and my family (and our whole houseful of crap) out to the Bay Area.
We're ensconced in a lovely rental in Pacifica, and loving the amazing views of the mountains, ocean ... and of course, the fog.
It's an interesting change going from years of working remotely from home, to working day-to-day in an office. With actual human beings in it. It's quite a change, and actually nice in a lot of ways seeing people other than my family on a regular basis, but there are downsides to the whole deal -- like, you know, having to wear pants.
The other big change, of course, is using Python for my server-side language of choice. I've been pretty much a Ruby guy up to this point, but Slide is a Python shop. The switch has been pretty interesting so far: I'm learning fun idioms like how to fake the ternary operator, and (of course) basic stuff like how not to screw up my indentation. I like it pretty well. Of course we're building Web apps, so there's also piles and piles of tasty JavaScript to work on.
Now that we're set up in our new digs (and the endless piles of boxes are mostly disposed of), and I'm managing to make major changes to code without blowing shit up, I think I'm settled in enough to begin updating here a bit more regularly.
Either that, or microblogging has killed my ability to post -- we'll see I guess.
Fleegix on Sinatra
10 months ago / 0 Comments
The Sinatra Web dev framework has been around for a while, but I've recently been seeing it popping up a lot more.
Simon Willison, the co-creator of the Django Python Web-dev framework, even mentioned it to me at SXSW Interactive when I buttonholed him after his panel on the Changing Face of News, to ask him what the Guardian is using for their API service.
(Sadly, he said, it's still all enterprise Java. NPR is using a mix of PHP and Java, and the New York Times runs their API service on Ruby on Rails.)
I suggested to Simon that Sinatra's higher profile comes from its status as the new anti-Rails, and Ezra Zygmuntowicz said the same thing today on Twitter:
@wycats sinatra is filling the gap now that merb is an organ donor ;)
He is of course referring to the fact that Merb, the Ruby Web-dev framework which has proven to be a credible competitor to Rails, is now being merged into Rails -- the result being Rails 3.
But Sinatra is more than that -- Adam Keys put it well in that same back-and-forth on Twitter:
@wycats I see some people taking to Sinatra now that Merb isn't the angsty choice. But mostly, its people looking to do more with less code.
Unless you have a case of man-with-hammer syndrome, you see that no single tool is right for every job -- and Sinatra's lightweight approach (it doesn't even bill itself as a framework, just a 'DSL') looks great for simple uses where you don't need all the overhead of Rails (or even Merb).
I recently converted the Fleegix.js project site from a Merb flat app to a gorgeously minimalist Sinatra app, and found Sinatra's simple aesthetic to be just about perfect. I could also see using it for throwing up simple Web services as well (although it's hard to beat Merb's resource routes and braindead-easy display/provides content-negotiation for that).
My next Sinatra project will be the EpiphanyRadio site, which is definitely due for a little love. It's another simple site (currently a bunch of raw mod_ruby/eruby) which would be a lot nicer as a simple Sinatra app.
Leaving Seesmic
10 months ago / 3 Comments
I started at Seesmic a little over a year ago, and it's been great helping the platform grow from a full-page Flash app prototype to an Ajaxy Web app backed by a solid REST API.
There is a time for every purpose under the sun, and now it's time for me to be moving on to other projects better aligned with my personal career goals.
I'm really proud of the work I did at Seesmic, and some of the early technology choices we made (particularly Merb) have proven to be excellent bets.
I also feel extremely fortunate in the great people I've gotten to work with there, and owe Loic a huge debt of gratitude for that opportunity. I remain a Seesmic shareholder, and a big believer in what they're trying to do with the platform. I look forward to seeing where they take it.
Not sure what's ahead for me yet -- I have just started my job search, but I will be blogging (and microblogging) about the process as it unfolds.
Apple MobileMe using fleegix.date.Date for timezones
12 months ago / 0 Comments
Sometime last year I found out that Apple was using the fleegix.date.Date plugin to build the timezone support in the MobileMe calendar, and recently had the opportunity to take a look and see what they did with it.
The MobileMe calendar is quite pretty, as you might expect with an app written with SproutCore. It still has some pretty rough edges (I'd say even lagging behind the UI we built for for Cosmo (AKA Chandler Server) in a lot of areas), but is mostly speedy and pretty solid.
You can see from the core JavaScript file for the calendar that Apple is indeed using fleegix.date.Date for handling timezones. Also nice to see that Apple is living up to their open-source obligations by including copyright information in their distributed source.
On a technical note, it's interesting to see that they're preparsing all the Oson zoneinfo data into a big JSON string and including it directly inline in the JavaScript source -- that's quite a big ol' ball of JSON data.
Seems pretty inefficient to me to push that out to all users (or even just all users who have timezones enabled) with no regard for how much of that data is actually ever used. But of course, MobileMe is still a relatively new product, and has a lot room for optimization.
I'm pretty excited to see a company like Apple building a major end-user-facing product using a Fleegix.js plugin, and even more enthused about the idea that the code is getting some real large-scale usage.
Fleegix.js and Framework Scanner
12 months ago / 0 Comments
A former colleague of mine, Teodor Moisa, pointed out to me recently that Fleegix.js is one of the libraries showing up in the scan performed by Framework Scanner. This is a very cool utility by Mats Bryntse that compares the impact on the global namespace by various JavaScript toolkits.
You can see Framework Scanner in action here.
Fleegix.js comes out looking pretty good in this online demo, with only 6 additional global symbols detected -- and as it turns out, 2 of those are false positives. One of those is an undeclared local variable which was leaking out into the global namespace (and has subsequently been fixed). The other is an old-style "onunload" which I can't find any references to in the code anywhere -- perhaps it existed in some plugin somewhere at some point in the past, I'm not sure.
The online demo includes an "Analyze your own scripts" feature, so I re-ran the test with the most up-to-date version of the library on GitHub, and it correctly found only 4 global symbols: ($, $elem, $text, and fleegix).
This stacks up pretty well with Dojo 1.2.3 (5), JQuery 1.3 (2 -- presumably jQuery, and $, which they use as an alias for it), Prototype 1.6.0.3 (25, wow), YUI 2.6.0 (5), and MochiKit 1.3.1 (243 (robot Jesus!), or 11 with __export__ set to false).
Really nice to see Fleegix.js showing up with such illustrious company -- and with the magic of alphabetical order, it's right there at the top, sweet!
Framework Scanner is pretty cool -- since more people are mixing-and-matching toolkits, knowing what kind of impact they have on the global namespace is really helpful. It also gives you a good idea of whether the creators of the toolkit in question put much priority on "playing nicely with others."
BOSH and iframe cross-domain pain
about 1 year ago / 0 Comments
A big feature of the new Seesmic.com Webapp is our auto-update feature which provides near-real-time updates in the UI of videos as they're posted.
Under the hood the auto-update uses simple long-polling of our XMPP service via BOSH, using Jack Moffitt's excellent Strophe.js library to handle the nitty-gritty of connections, auth, and parsing all that tricksy XML output.
Pretty cool seeing those video posts pop into the UI over that sweet BOSH connection. But of course with that permanent long-running connection in the browser, we butt right up against the dreaded two-connection limit, and API calls to the backend are stuck going serially through the one remaining pipe. That really sucks a lot of the awesome out of the user-experience we're trying to bring.
The obvious solution was to move that dude to to a different subdomain so it's not permanently hogging half of the pipe to the backend. The same-origin policy for XHR calls in JavaScript throws a little bit of cold water on this plan, but like all things in the world of cross-browser Ajax apps, judicious application of a bit of ugly hackery will make things work.
In this case, the hackery is the fun and super-interesting world of cross-domain iframe communication. This technique has been around for a long time, but I've never had the pleasure of working with it. And by "pleasure," of course I mean "annoying, nagging pain, like a migraine that just won't go away."
The same-origin policy means pages served from different subdomains can't communicate with each other, but that's precisely what we need in this case -- we need to unload that BOSH connection to a different subdomain. Cross-domain iframe communication gets around this limitation by taking advantage of the fact that you can change the document.domain (essentially the security context that JavaScript executes in) of a page after it reaches the browser.
The idea is pretty simple -- serve the page in an iframe from a subdomain, change document.domain to match the hosting page. XHR objects in the iframe page don't change their notion of relative URLs, so they can still make calls back to the original subdomain server with no problem, but JavaScript can report those results back up to the parent page.
In practice, it's tweakier than that, with different browsers having different ideas about what exactly "match the hosting page" means. And as you might expect, it's Safari and Firefox at one end of the table, and IE way down at the other.
Here's the breakdown I found. Maybe this will save some other folks a few minutes of irritation.
Firefox/Safari
TLD: They don't care if the parent page and the iframe
document.domainare a top-level domain or not, they just want them to match.Setting the
document.domain: Bizarrely, you have to set thedocument.domainon both the parent page and the iframe page even if the parent page is already what you want.
Internet Explorer
TLD: Totally doesn't work unless both parent page and iframe page are using a top-level domain for the
document.domain.Setting the
document.domain: Bizarrely, you cannot reset the document.domain of the parent page if it's already a TLD. Resetting it (even to the same value) will break the cross-iframe communication.
Once I got through stubbing toes on all the annoying inconsistencies, communication back and forth between the iframe document and the parent worked great. Now we've got the two pages chit-chatting back and forth like two distant relatives at a family reunion who discover they both love Ronnie James Dio.
The browser still has to deal with the continuous open connection to the backend, but it's noticeable how much snappier the app is without BOSH sitting there Bogarting one of only two available connections to the main app domain.
WTF, global "item" symbol in IE
about 1 year ago / 0 Comments
Like any self-respecting Web UI developer, I have a lovingly cultivated hatred of Internet Explorer.
IE and I go way back -- I've been developing for IE since version 3, and I have a fairly well evolved sense of sense of what breaks there. So it's always an occasion for rejoicing when I trip over something strange and new.
Some recent code-refactoring breakage (I moved a code loop and left a variable undeclared, sweet!) unearthed this little gem: IE (both 6 and 7) seems to have a built-in global symbol called item.
It reports its type as 'string', but appears to be an invokable function -- calling it with a random param passed yields the error: "Member not found":
alert(typeof item); // Alerts 'string', expected 'undefined' item('foo'); // Throws 'Member not found' error
I'd love it if someone could enlighten me -- WTF is this 'item' thing?
It looks like some kind of vestigial Active Scripting organ -- I did find a reference to a default item method of WshArguments in Windows Script Host, but nothing to explain, what, if anything it actually does in IE.
As a side note, IE6 is older than all my kids. And they're about to graduate college. Okay, not really -- the oldest is in first grade. But still.
Kerblooey accessing DOMException location property
about 1 year ago / 0 Comments
This past week I ran afoul of an interesting bug in Firefox 3 trying to serialize some stuff with fleegix.json.serialize.
Iterating over the properties of the DOMException (which for some inexplicable reason isn't an instance of a generic Error, but that's another rant) reveals the existence of a a location property. But sadly, much like Nigel Tufnel's Fender Bass VI, this property is not to be touched, or even looked at -- if you actually attempt to access the property directly, you get the wonderfully intuitive error, "Permission denied to create wrapper for object of class UnnamedClass."
As it turns out, this bug has already been reported -- it's Firefox bug 436953.
Fleegix.js 0.5.0 released
about 1 year ago / 0 Comments
Okay, so the docs are all polished up, and tarballs/zips are freshly cooked, piping hot from the oven, so here it is, Fleegix.js 0.5.0. Mmm, tasty JavaScript.
The code name for this release is "Palace of ECMA Supremacy." Any questions or concerns regarding this release must include the code phrase, or they will not be responded to. Just kidding. Probably.
New features in this release include:
- Metaprogramming! New extend, mixin, clone methods in base.
- New string module
- Even more arrayish-method goodness for the fleegix.hash.Hash sortable Hash plugin -- reverse, splice, push, pop, unshift, and shift
- fleegix.date.Date plugin can now load timezone data from JSON objects
- User-agent sniffing (yeah, we live in an imperfect world)
- New fleegix.ejs module for EJS (embedded JavaScript) templates -- why let the server-side guys have all the templating fun?
In addition to the new features, a vast number of bugs lost their lives in this latest release. As Hernando says, "The bugs are enormous. There are an infinity of bugs." Feel free to peruse the ChangeLog for a roll call of the deceased, and details on the new-feature work.