Paul Robertson's words, punctuated

Thoughts on development, user-centered design, code, etc. by Paul Robertson

Adobe AIR 1.0 ships! SQL changes, and other thoughts

Now that Adobe AIR 1.0 is in the wild, I wanted to post an update about changes that happened with the local SQL database functionality between beta 3 and the final release. Plus, I’ve had some general thoughts about the release of the software that I thought I’d share.

For some reason, the final time that I saved this post before publishing it, my changes didn’t get saved. So if you saw this soon after it was posted, and wondered why it didn’t really talk about SQL changes, and why it had some messed up headings…that’s why. Sadly I’m sure I can’t recreate the text as well as I wrote it the first time. But here’s my best effort…

First of all, allow me to clear something up. I am aware that Adobe AIR 1.0 shipped almost exactly a month ago, so this shouldn’t be news to anyone who’s actually interested in it. I intentionally held off on publishing my thoughts (and a description of changes since beta 3). As a rule, I never post anything in the week or so following a big product announcement – there are so many “me too” posts about the product, and so little actual different thoughts or original ideas, that I don’t want to clog up the aggregaters by adding to the hubbub (the “MXNA firehose” as I’ve heard JD describe it).

That’s not a complete excuse, of course. The truth is also that I’ve just gotten busy with a lot of post-launch cleanup activities, and of course moving ahead on future projects (Flash Player 10 and AIR 2.0), so I’ve neglected this post for longer than it deserved.

And now, lest I postpone it any longer, here are a few bits of news and opinion from my corner of the Flex/AIR world:

Local SQL database feature changes

Wait a minute – didn’t I say a couple of months ago that as of beta 3 AIR is API frozen? Indeed that was the intention, and with one small exception it’s true. And that was the first thing that came to my mind when I read the notification (shortly after beta 3 was locked down) that some changes to the SQL functionality had been checked in to source control. But I was correct before – the API hasn’t changed – just one particular behavior has.

The specific change is with how the runtime treats column data types in database tables. In betas 1-3, AIR was consistent with the “default” SQLite behavior:

the type of a value is associated with the value itself, not with the column or variable in which the value is stored…. All other SQL databases engines that we are aware of use the more restrictive system of static typing where the type is associated with the container, not the value.

In order to maximize compatibility between SQLite and other database engines, SQLite support [sic] the concept of “type affinity” on columns. The type affinity of a column is the recommended type for data stored in that column. The key here is that the type is recommended, not required. Any column can still store any type of data, in theory. It is just that some columns, given the choice, will prefer to use one storage class over another. The preferred storage class for a column is called its “affinity”.

So under the “affinity” system, if in your CREATE TABLE statement you specify that a column stores INTEGER data, and you write an INSERT statement that stores a String instance in that column, the runtime allows it. (I initially wrote “it works just fine” but that may not be true – since your application may be assuming that values retrieved from that column are always integers.) When I first read about this behavior when we were reviewing the spec for the feature, I recognized that it was different than what I’d done before, but I figured it was okay – I’d just have to be extra careful when inserting values into the database, and enforce the data types myself by convention even if the runtime didn’t enforce them in practice.

However, the feedback we got from developers was that this doesn’t really match what they’re used to from typical web app database code (which likely uses databases such as Oracle, SQL Server, or MySQL). As a result, in the final release, the declared data types of database columns are more strictly enforced. If you declare a data type for a column, then attempt to store a value that isn’t an instance of that type, the database will try to convert the value to the appropriate type (for example, turning a number into a string, or parsing a string to see if its text is actually a number). If the value can be converted, then the converted value is stored; otherwise, the runtime throws an error. (For more details, see the column affinity description in the documentation.)

Personally I’m pretty happy with this solution. It’s still a bit more flexible than the databases I mentioned before – usually they won’t even try to convert a value, and will just choke if the data type doesn’t match. But I think that the way it works in AIR 1.0 is consistent philosophically (and actually) with the way data types work in ActionScript 3.0 where values can be strongly typed or weakly typed at compile time, but either way at runtime the type must match.

So, what do you do if you were one of the people with more SQLite experience than other db experience, of who otherwise preferred the old behavior? Well, there is still a workaround. If you don’t declare any data type for your columns, you can store data of any type without causing errors. This isn’t the same as the previous behavior, but based on some anecdotal observations I’d guess that developers who intentionally mix data types in columns are less likely to declare a column data type, in any case.

Also, as a side note, I decided to keep the term “column affinity” in the documentation even though the behavior changed. I did this for a couple of reasons: 1) Developers who’d been reading the docs were probably familiar with the term now, and 2) the data types still aren’t strictly enforced, in the sense that the runtime attempts to convert values before storing them (just as a default SQLite implementation does). For example, just about anything can be stored in a TEXT column without an error occurring. So in that sense, the data type specified in a CREATE TABLE statement is still somewhat of an “affinity” rather than a traditional strictly enforced data type.

What does “finished” really mean?

Not too many years ago, my definition of a “release version” of software was different than it is now. I knew that any software, no matter how much it is tested, is bound to have some bugs in it – it’s just not possible to ship software of any notable size without making a mistake somewhere. However, I had enough faith in big software companies that I assumed that when a company declares a product to be a “release” or “shipping” version, that it at least doesn’t have any bugs that they know of.

I’m not sure when I realized that this view is far from reality. I suppose it was probably with the first private beta I was involved with, though maybe it was before that.

In any case, I hope I’m not shocking anyone’s sensibilities when I point out the reality, that even though Flex 3 and AIR 1.0 have shipped, they do have bugs – and Adobe even knows it! The recent openness of Flex, in particular the introduction of the public Flex bugbase, makes this reality much more transparent. A quick search on the Flex SDK project, looking only at bugs (as opposed to feature requests), shows 309 “open”, “in progress”, “community”, or “new” issues. And that’s not even taking into account “deferred” bugs, such as SDK-14339 “WindowedApplication doesn’t update/show menu when it changes during runtime”.

While Adobe AIR doesn’t have a public bugbase, that doesn’t mean it’s any more free of bugs. Try calling the NativeMenu.display() method on a PowerPC Mac running OS X 10.4 and you’ll see what I mean (hint: the menu appears at the mouse cursor rather than at the specified coordinates).

So what does “release quality” software really mean? Well, it means that it doesn’t have any bugs that are “showstopper” issues, or that are “really bad.” Yes, I’m intentionally using non-specific terms here. The reality of life is that if Adobe (or any software company) waited to release software until all known bugs are fixed, the software would never get released. So instead, they use a process that’s sort of like this (I’m generalizing and also stating this based on my own observations, not on any review of actual process or guidelines within Adobe):

  1. The decision makers figure out a date by which the software should be done. (I’m not talking about at the beginning of a product cycle – I’m starting somewhere in the middle.)
  2. Throughout the process, bugs are reported. Any time a bug is reported, it is investigated and a decision is made as to whether resources can/should be allocated to fixing it. The criteria for this decision are generally based on how severe the bug is (whether it crashes the software/computer, causes data loss, is a usability issue, etc); how hard it is to fix; how much time it will take to fix; how likely it is that someone will run into the bug; whether or not there’s a workaround; etc.
  3. As the product moves closer to the release date, the threshold for whether a bug will be fixed goes up – the closer the software is to the release date, the more severe and less difficult to fix a bug must be in order for it to get fixed.

This can be frustrating for people who file bugs, like me. Often, due to workload and general stability issues, it’s not practical for me to start writing the documentation for a feature until it’s fairly stable and close to finished. But that means that when I do find bugs, there’s a good chance it’s too late in the process for the bug to get fixed in time for the product release.

Ah, tradeoffs.

Go right to the source

Now that Flex 3 has shipped, the Flex 3 source code is available in the Flex Subversion (SVN) repository. I’ve actually been accessing it there for a while – internally we made the switch from Perforce to Subversion around the first of the year. I was pretty worried at the time, because I had never used SVN before. The majority of the Flex 3 work was already done at that point – they were just in final bug fixing mode. We still had about a week before our content had to be locked down, so I was working furiously to try and finish up some work I was doing on the Flex AIR components. I wasn’t too excited about the prospect of switching source control systems in the middle of that crunch. Fortunately, SVN turned out to be pretty straightforward. (In case you’re wondering, I use TortoiseSVN). It’s actually been good for me to learn SVN at work – it made it easier for me to move some of my code projects over to Google Code (a few that are already there, and a few more that I’ve started but not posted on my projects page yet). So overall I give SVN thumbs up, and I’m happy that the Flex source code is available that way.