3 Cool 'Joyride' Features on dwarfland.com
In a brief departure from all the talk about ‘Vinci’ (no worries, the next post will be coming soon ;), this weekend i found some precious time to work on my personal dwarfland.com website which – as regular readers of this blog will know – is built on top of a flickr.com account using none other than our upcoming Chrome 2.0 (‘Joyride’) and ASP.NET.
There’s three language enhancements coming in ‘Joyride’ that i have grown particularly fond of, and all three of those came in very handy for the code on dwarfland.com.
First of all, of course, there’s LINQ. As you probably know by now, Language Integrated Query is a new feature coming in the ‘Orcas’ version of the .NET framework, version 3.5, and is a combination of helper classes provided by the framework itself, and new language syntax provided by language vendors (including us). LINQ allows to write SQL-like queries for data manipulation, right inside code, and working with strongly-typed objects.
For example, to obtain a list of photos to display on a particular page, i might write something like this:
var lPhotos: sequence of Flickr.Photo; lPhotos := from p in Flickr.GetPhotos(...) where p.Public = 1 order by p.DateUploaded desc;
which would return me a list of photos in the requested condition (only those flagged as public, and pro-ordered by upload date).
All that’s left to do is some boilerplate for each/Response.Write code to emit the HTML, and it’s done.
Now, in this particular case, the GetPhotos() method is simple, it fetches all photo info from the server and returns an IEnumeranble.
The beauty of LINQ is that someone could go ahead now and change GetPhoto to be smarter. imagine i have thousands of photos in my account, but only a small subset is marked as public. Now, that’d be a huge waste of network bandwidth, getting all the info from flickr, just to have 90% of it discarded.
What if the implementation of GetPhoto were to be changed to know about LINQ and be “query aware”? If that was the case, the exact same LINQ code posted above would continue to compile – but do something quite differently at runtime. Instead of simply asking the remote flickr server for all images and then filtering locally, GetPhotos could actually go ahead and pass my filter (“Public = 1”) on to the server, which would then only return those photos i actually need. All of this, without any change to the actual code that processes the collection of photos.
With LINQ, the same coding paradigm can be used on sequences of data – whether those sequences are simply a local list (as in the current Flickr.Net implementation), or not. And optimizations to data access can happen inside the data provider, without the consuming code having to be adjusted, at all.
The second feature that i want to talk about is a small, but imho pretty revolutionary change to member access in the Chrome language.
Developers of pretty much all object oriented languages are familiar of the “.” operator used to access members of an object, such as “MyString.Length”. But what happens if you use this operator on an object reference that is null? You will get an Null Reference Exception or an Access Violation.
To avoid this, todays code is full of nil checks, along the lines of “if MyString <> nil and MyString.Length > 0”, which make the code hard to read, cause unnecessarily nested “if” statements, and so on.
‘Joyride’ introduces a new operator, “:” to bring an end to all this nonsense. “:” can be used in place of the familiar “.” operator in all places, and will behave in exactly the same way, except in one case: if the left-hand object is null. If the left-hand is null, the member to the right is evaluated as “null”, itself.
To be honest, when we first planned this feature i considered it to become a “nice gimmick no-one really needs”, but it has been amazing how many scenarios are made easier by this operator, and i find myself using it every day. It comes in handy for simple things such as MyString:Length, but it also allows extreme simplification of nested object access. Consider the following code:
var lGreatGrandDadsName: Myself:Parent:Parent:Parent:Name;
assuming an object’s Parent can be null, the above code would require 4 separate checks for nil, either in nested “if”s or in one bad mother of an if clause. The above code, in contrast, is about as simple as it gets.
Furthermore, assume the “Parent” property wasn’t backed by a field, but actually required some complex code to compute (search thru a list to find the right object, for example). Pretty much all standard ways to write the above code would have each Parent queried several times – unless you further complicate the code with local helper variables.
in the above line of Chrome code, each Parent is evaluated exactly once.
Finally, i want to look at a small enhancement we have made to the “for each” loop construct, that comes in handy in cases where you need both an iterative and an index-based approach. For example, you might want to fill elements of a sequence into an array, or display them in a table where you want even and odd rows to look differently.
The new (optional) syntax looks like this
for each e in lSequence index i: Int32 do ...
and you’ll immediately notice the new “index” clause, which will provide an indexer variable that will count up from 0 as you enumerate your sequence.
This came in handy for two things at once when i implemented the new “set” page for dwarfland.com./ For one, i needed to create a comma-separated string of image ids to emit as a JavaScript array (the set page allows you to browse all images client side, without refreshing the page from the server), and of course when doing this in a for each loop, the problem always is that you need one less commas than you have items – usually requiring an extra bool var to be maintained manually.
Using the new “index” syntax, i could simply write
if i > 0 then s.Append(', ');
and that was the end of it.
In addition, the sets paged allows passing in an image id as part of the query string, forcing the page to preselect this particular image. Again “index” came in handy – i simply placed a check for the image id within the loop, and if they match i use “i” as index to pass to my JavaScript.
Of course, these are only three of many cool new things coming in Chrome ‘Joyride’ this July. So stay tuned.
That’s all for now – there’s a new Data Abstract article to be written, with my name on it…