Apple's App Store Submission Process & Java Verified
August 9th, 2009
There’s a lot of discussion going on at the moment about Apple’s App Store submission process and the role that carriers play in vetting applications. When the App Store was announced, I naïvely believed that Apple had successfully cut out the carrier middleman responsible for crippling every other mobile development platform. Unfortunately, the carrier protectionist oligopoly lives on, albeit on a slightly smaller scale.
But it’s not all doom and gloom. I see two major issues:
- Carriers are barring applications they deem disruptive to their business
- The submissions process is completely opaque
If history is anything to go by, the first issue is going to be very difficult to resolve directly. It’s the second issue I think we’re in a position to easily fix.
First, I think it would be productive to look at the J2ME platform.
One of the biggest issues that’s plagued J2ME has been greedy carriers standing in the way of developers trying to bring their applications to market (ring any bells?). To access run-of-the-mill features like the address book, networking or GPS APIs you need to sign your application. Problem is, certificates from well known CAs like Verisign are stripped from carrier-branded phones in favour of carrier issued certificates. Many carriers run their own developer program to facilitate code-signing of applications that will run on their network.
The industry’s “answer” to this problem was to come up with Java Verified, a process that allows developers to submit their applications to one of a handful of “Authorized Test Houses” and pay around $300USD to have it taken through a standard test procedure. If it passes, you get a signed application which will run on most carriers and devices. If it fails, you pay again for the privilege of having it retested. Also note that you’re paying to have your application tested on a specific device of your choosing, so if you’d like your application tested on multiple devices, you pay per device.
Disregarding the fact that the Java Verified process will leave you thousands of dollars poorer once you’ve released a few versions of your application to a handful of devices, it’s quite similar to Apple’s verification process. You submit your application, it gets tested according to a criteria that carriers are happy with, and if your application passes you’re good to go.
BUT, there’s one minor difference; the Java Verified testing houses are all following the same open, standard test script. It’s called the Unified Testing Criteria (PDF), and it’s made available to developers so that they know how their applications are being scrutinised by the testers.
I think Java Verified’s Unified Testing Criteria would form a great basis for a similar document to be written for the App Store submission process. It would cover areas like:
- High-level APIs being used (GPS, address book etc.), how frequently they’re used, and whether or not they remove user data (address book entries etc.)
- Remote content used in the application. Where does it come from? Is it interpreted and/or executed to change the behavior of the application? Could it contain offensive content? Does the application’s rating take into account mature content?
- Data usage over 3G, including a clear set of quantitative guidelines that take into account what carriers deem appropriate on their networks
- Rights to publish content, either through ownership, licensing or fair use
- Use of advertising
- Whether or not behavior, usage and metrics about the user are recorded
- Stability, performance, memory, network and battery usage tests
- Adherence to the Human Interface Guidelines (HIG)
- Handling of memory warnings
- Handling of registered URL schemes
- Ability to run during a call or tethering
- Ability to handle lack of network access or network delays
- Appropriate use of the keychain for secure storage
The document would likely take the form of a questionnaire, with a clear definition of pass/fail conditions for the various questions. If a developer filled out the questionnaire and received a clear pass but Apple’s testing produced a fail, the difference between their questionnaires would form the basis for productive communication to resolve the issues and allow for resubmission. The document would evolve over time, hopefully reaching a point where if you filled out the questionnaire yourself and got a pass, you’re almost guaranteed to get through the submission process.
I really think this would make a world of difference, and wouldn’t require any drastic changes for Apple other than a little bit more open documentation of the existing process.
Thoughts?
My Feed URLs Have Changed
July 29th, 2009
With Google’s acquisition of Feedburner, I’ve been locked out of my Feedburner account. Since Google doesn’t seem to be providing any level of support for the relocation process, I’ve been forced to recreate my feeds. If you’re subscribed to the article feed (http://feeds.feedburner.com/atnan) or comments feed (http://feeds.feedburner.com/atnan-comments), you should point your feed reader to these new feed URLs:
http://feeds.feedburner.com/atnan-articles http://feeds.feedburner.com/atnan-all-comments
Sorry for any inconvenience—I know I’ve found it a bit of a pain when other blogs have changed their feed URLs on me!
Enabling Verbose Push Notification Service (APNS) Logs
July 27th, 2009
Those of you who are developing iPhone applications that utilise Apple’s Push Notification Service (APNS) will understand that sometimes it feels like a bit of a black hole. Fortunately, Matt Drance (Apple’s current Application Frameworks Evangelist) has made a device configuration profile available which enables verbose logging in “apsd”, the daemon that runs on devices and is responsible for connecting to the APNS servers and retrieving push notifications.
You can grab a copy of the configuration profile directly from my site (http://www.atnan.com/APNsLogging.mobileconfig), or by visiting the original thread Matt attached the file to on Apple’s developer forums.
To install the profile on your device, you can point Mobile Safari directly at the file on my site, email the file to your device, or install it via the iPhone Configuration Utility. For those of you who are unfamiliar with *.mobileconfig files, you should read Apple’s Enterprise Deployment Guide which provides much more detailed instructions.
This is a simple but useful tip for people like myself who want to stay up to date with the latest beta releases of the iPhone SDK, but who also rely on having a stable version of the SDK installed for things like deploying to the App Store, reproducing bugs from in-the-wild, or client work that doesn’t take advantage of any new SDK features.
The first time I grabbed a beta version of the SDK, all I did was hit the install button and let it do its thing. However, if you don’t change any of the default install settings, you’ll quickly find that the beta SDK has been installed straight over the top of your stable version of the SDK.
The solution is to install two copies of Xcode and the SDK; the stable version goes in ”/Developer”, and the beta version goes in ”/Developer Beta”.
If you’ve already installed a beta version of the SDK in ”/Developer”, you’ll need to remove it. To do this, you should run the following from the command line:
sudo /Developer/Library/uninstall-devtools --mode=all
You can then proceed to install the stable SDK in ”/Developer” and the beta in ”/Developer Beta”. If you ever need to blow away your beta copy of Xcode and the SDK, you should run the same command as above but from the beta directory instead:
sudo /Developer Beta/Library/uninstall-devtools --mode=all
Finally, to launch Xcode with the stable SDK you run ”/Developer/Applications/Xcode.app” and to launch Xcode with the beta SDK, run ”/Developer Beta/Applications/Xcode.app”.
Configuring Multiple CalDAV / Google Calendars on iPhone OS 3.0
June 19th, 2009
One of the cool features of Leopard was the addition of CalDAV support to iCal, which allows you to read/write/edit/delete calendars hosted by third parties like Google Calendar. Similar functionality was available on the iPhone, but only via Apple’s MobileMe service. That’s changed with iPhone OS 3.0.
If you’ve configured a bunch of CalDAV calendars in iCal, unfortunately they’re synced to the iPhone as read-only calendars which is a real pain. In lieu of a fix by Apple, we’ll need to remove the iCal CalDAV accounts from the iTunes calendar sync list, and configure them on the iPhone itself.
To set up a new CalDAV account, you’ll need to navigate through the following screens on your iPhone:
Settings → Mail, Contacts, Calendars → Add Account… → Other → Add CalDAV Account…
Once you’re there, you’ll be presented with a dialogue that lets you enter a CalDAV server, username, password and description. This dialogue is incredibly misleading, because the “server” field will not only accept a hostname like “www.google.com”, but also a full CalDAV URL like “https://www.google.com/calendar/dav/<CALENDAR_ID>/user”. If you’re using Google Calendar with only one calendar, enter your Google Calendar credentials like the following example:

If you’ve got multiple CalDAV calendars, it starts to get a little bit hairier. Initially, I emailed myself a list of my CalDAV URLs (4 in total) and used the new copy-paste features to manually configure each account using the previous instructions, only instead of using “www.google.com” in the server field, I pasted the entire CalDAV URL instead. As you can imagine, this is incredibly tedious.
Fortunately Apple also released a new version of the iPhone Configuration Utility (ICU), which is a really handy tool for creating iPhone configuration bundles for deployment in enterprise environments. Among other things, this new version allows you to configure CalDAV accounts. If you haven’t already, you should grab a copy of ICU for OS X or Windows.
Launch ICU, create a new configuration profile, and open the CalDAV pane. For each CalDAV calendar you want to configure, you’re going to want to fill it in like this:
If you’re looking at the Principal URL field and wondering what ”<CAL_ID>” is, you’ll find it in the calendar settings page of Google Calendar under Calendar Address (it should look like an email address).
Once you’ve entered all your CalDAV accounts, plug in your iPhone, select it in ICU and open the Configuration Profiles tab. You should see the configuration profile you just created, with an “Install” button next to it. Hit the “Install” button.
You iPhone should show a screen like this:

If you hit “More Details”, you’ll see the CalDAV calendars listed:

Hit “Install”, confirm, and open up the Calendar App to see if everything works as expected. You should be able to create, edit and delete calendar entries in your CalDAV accounts, and have them update in iCal / Google Calendar. If you ever want to add a new CalDAV calendar, I think you need to remove the configuration via the iPhone Configuration Utility and re-install the edited configuration bundle.
Hopefully it doesn’t take too long for Apple to make the CalDAV integration between iCal and the iPhone more seamless.
UPDATE: Due to changes in the public release of iTunes 8.2, you will now need to quit iTunes and run a command in your Terminal before proceeding with the instructions below. The command is: “defaults write com.apple.iTunes carrier-testing -bool TRUE”.
UPDATE: I’ve downloaded the Telstra and Vodafone bundles and made similar modifications, so they’re now available in the guide. If you’re using Telstra/Vodafone and my modified settings bundles work, please let me know in the comments as I’m unable to test it myself.
The following instructions are intended for members of the Apple Developer Connection (ADC), running an iPhone with a developer version of the iPhone OS 3.0 software. This guide also only provides Australian carrier settings for Telstra, Vodafone and Optus (plus resellers like Virgin), but if you follow the link to Crunchgear in the first step there are instructions on downloading and modifying the carrier setting bundles.
- Download Telstra_au.ipcc, Vodafone_au.ipcc or Optus_au.ipcc, which were created as per the AT&T instructions on Crunchgear (note that the file should have an ”.ipcc” extension, not ”.zip”. If your downloaded file has a ”.zip” extension, unzip it to produce a “Carrier_au.ipcc” file)
- Open iTunes
- Plug in your iPhone
- Select you iPhone under devices
- In the Summary tab, ⌥-click (option-click) the “Check for Update” button
- Select the previously downloaded Telstra_au.ipcc / Vodafone_au.ipcc / Optus_au.ipcc file and click “Open”
- Once the settings have been copied, disconnect your iPhone
- Restart your iPhone
- Open the Settings application on your iPhone, and navigate to General, then Network, and finally Internet Tethering
- Turn Internet Tethering on. At this point, tethering is now possible via USB when your iPhone is plugged in. If you’d like to use Bluetooth, continue reading
- You will be prompted to turn bluetooth on if it’s not on already. Select yes if prompted
- On your laptop, turn on bluetooth and open the Bluetooth Preference pane
- Click “Set Up New Device…”, which will open the Bluetooth Setup Assistant
- Select “Mobile Phone” as the Device Type
- Select your iPhone from the device list
- A number should appear on your laptop, and your iPhone should prompt you for a pin
- Enter the pin from your laptop into your iPhone
- Once paired, make sure you keep “Use device as network port” selected
- In the Bluetooth Preference Pane, make sure “Show Bluetooth status in the menu bar” is selected, since it makes things easier for starting and stopping tethering
- Click the Bluetooth icon in your status bar, where you should now see your iPhone under devices
- Click on the menu item for your device, and select “Connect to Network”
- On your iPhone, you should now notice that the top of the screen has a blue bar titled “Internet Tethering”
- You can now use the Internet!
- As an optional extra, you can open Network Preferences and rename the two new network devices to “iPhone USB” and “iPhone Bluetooth”
Hope that helps someone! Not really a difficult process, but it can be a bit fiddly. Downloading my Optus_au.ipcc file also saves mucking around in Property List Editor too, which most people will attest is a bit of a pain.
"Chunked" Transfer-Encoding Support in Apache/Passenger
April 4th, 2009
I wrote an article last year about the lack of Apache support for HTTP requests with the “Transfer-Encoding: chunked”. Of course, this problem really only affects those of us who use Apache modules that were developed against the Apache 1.3 API (pre-HTTP 1.1). One such module was Phusion Passenger – also known as “mod_rails” – which I was using at the time to provide a web service to J2ME MIDlets and an iPhone application (among other things). To get around the lack of support, I presented a solution involving the use of mod_proxy to buffer the chunked request and rewrite it as a new request before passing it to the non-HTTP 1.1 compliant backend.
Thankfully as of two days ago, that hack is no longer required if you’re using Passenger.
Hongli Lai (the lead developer of Phusion Passenger) has checked in a change that enables support for chunked transfer-encoding, which means no more dreaded “HTTP/1.1 411 Length Required” responses. So the fix is checked into the tree, and according to the bug report will be made available in the next release of the Passenger gem – version 2.1.4.
Configuring Apache to accept chunked HTTP requests from J2ME (CLDC and MIDP)
November 28th, 2008
A few months ago, I wrote an article (“Transfer-Encoding: chunked”, or, Chunky HTTP!) describing a solution for accepting chunked HTTP requests made by J2ME devices to non-HTTP 1.1 compliant servers unable to accept such requests (Mongrel, Lighttpd, Nginx etc.).
One of the commenters was concerned that J2ME developers suffering from this problem might find it difficult to find my article since I didn’t really mention J2ME MIDlets much at all. So, if you’re a J2ME developer suffering from problems like those described here, here or here...check out the original article for a simple solution.
Issues with CoreFoundation chunked requests (iPhoneOS 2.x / OS 10.5.x) and Apache / mod_proxy
November 28th, 2008
A comment was made in my previous article, Memory issues with NSMutableURLRequest’s setHTTPBody: method in iPhoneOS 2.1, stating that the “c” of “chunked” in the “Transfer-Encoding: chunked” header is similarly capitalised in OS 10.5.5, which means that the flaw in Apache’s mod_proxy is exposed by more than just the iPhone.
So if you’re trying to do chunked HTTP POST requests using the CFNetwork stack, make sure your Apache configuration can deal with the chunked header:
RequestHeader edit Transfer-Encoding Chunked chunked early
Memory issues with NSMutableURLRequest's setHTTPBody: method in iPhoneOS 2.1
October 16th, 2008
The iPhone developers at my work have been tearing their hair out over the last few days, trying to resolve the last few memory issues in our iPhone application before we send it off for approval by Apple. One of the problem areas they’ve noticed is when a photo is uploaded to our service via HTTP POST (both from the camera and otherwise).
Not sure who had the bright idea, but one of the developers decided to try passing in the HTTP body as an NSInputStream (via NSMutableURLRequest’s setHTTPBodyStream:), rather than as NSMutableData (via NSMutableURLRequest’s setHTTPBody:). Magically, this seems to have solved the memory leak issues.
Unfortunately, it created another issue.
You might remember that 3 months ago I wrote an article on how much of a pain in the arse it was to accept HTTP POST requests from user agents specifying a Transfer-Encoding HTTP header value of chunked (resulting in a POST request with no content length). In that article, I proposed a solution using Apache 2 and mod_proxy’s proxy-sendcl option to get things working again. This worked fine for our J2ME clients, but when our iPhone application started blowing chunks at us, our server crapped out with the dreaded 500 error I thought I’d fixed for good:
Chunked Transfer-Encoding is not supported
After whipping out Wireshark, we realised that there was a tiny difference between between what our J2ME client was doing and what the iPhone was doing.
This is the header the J2ME app was sending:
Transfer-Encoding: chunked
And this is the header the iPhone was sending:
Transfer-Encoding: Chunked
As much as I’d like to think the different casing of chunked and Chunked wouldn’t affect the behaviour of mod_proxy, it seems it does. Fortunately, we can work around this problem too by using Apache’s mod_headers module. This allows us to do the following:
RequestHeader edit Transfer-Encoding Chunked chunked early
When combined with the solution from my previous article, this leaves us with the following complete solution:
ProxyRequests Off
<Proxy http://localhost:81>
Order deny,allow
Allow from all
</Proxy>
Listen 80
<VirtualHost *:80>
RequestHeader edit Transfer-Encoding Chunked chunked early
SetEnv proxy-sendcl 1
ProxyPass / http://localhost:81/
ProxyPassReverse / http://localhost:81/
ProxyPreserveHost On
ProxyVia Full
<Directory proxy:*>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
Listen 81
<VirtualHost *:81>
ServerName ooboontoo
DocumentRoot /path/to/my/rails/root/public
RailsEnv development
</VirtualHost>
Hopefully this saves someone a little bit of time :).
"Transfer-Encoding: chunked", or, Chunky HTTP!
August 8th, 2008
Providing a web service for a bunch of browsers is a relatively straightforward affair. It’s really only once you jump out of the back-end and into the front-end side of things where issues like browser incompatibilities start to become a problem. Thankfully, I feel like I’m in the position where I think I’ve got my head wrapped around what’s involved in providing solutions to these problems.
And then mobile phones came along.
The service I’m working on at the moment is consumed by a bunch of clients, including but not limited to web browsers, WAP browsers, the Flash player, iPhones, J2ME devices. It’s the last one that’s causing headaches at the moment.
You see, despite the fact that HTTP/1.1 is about 9 years old, not all web servers support the features that were introduced. The particular one I’m talking about is chunked tranfer encoding, but I’m sure there are many others.
To give you a general idea, the HTTP implementations on many mobile handsets will decide to use a chunked transfer encoding if the payload of a PUT/POST request is over an arbitrary threshold. This causes issues with servers like Nginx, Lighttpd, Mongrel, and Thin, since most of those assume that an incoming HTTP request with a payload will also include a Content-Length header.
Well guess what? As of 9 years ago, that hasn’t been the case.

Take a look at this request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
POST /search.json HTTP/1.1 User-Agent: curl/7.16.4 (i486-pc-linux-gnu) libcurl/7.16.4 OpenSSL/0.9.8e zlib/1.2.3.3 libidn/1.0 Host: ooboontoo Accept: */* Transfer-Encoding: chunked Content-Type: multipart/form-data; boundary=----------------------------ab5090ac7869 92 ------------------------------ab5090ac7869 Content-Disposition: form-data; name="query" zoooom ------------------------------ab5090ac7869-- 0 |
Notice anything? If not, try and find a Content-Length header. Pre-HTTP/1.1 you’d expect to get an HTTP 411 error (length required), but after HTTP/1.1 it’s pretty clear what the HTTP/1.1 applications are obliged to do:
All HTTP/1.1 applications that receive entities MUST accept the “chunked” transfer-coding (section 3.6), thus allowing this mechanism to be used for messages when the message length cannot be determined in advance.
That’s why I find it so surprising that hacks are involved in allowing mobile clients to POST/PUT to what I’d traditionally thought of as HTTP/1.1 compliant web servers.
But anyway, you want to see the solution right?
Well, our initial solution involved Gerald writing a little web server in Python which went by the name of “Dechunker”. You can imagine what it did, but we quickly found that while it was the simplest way to avoid the problem, it also meant that over time we would end up needing to implement the functionality that was already available in most other web servers. Servers like Apache2 and Lighttpd have become incredibly hardy over the years, and we’re not going to achieve that overnight.
So I then took another look at Apache2, knowing that some modules do support chunked transfer encoding while others don’t. What I discovered was that Apache’s mod_proxy module could be used in front of anything that doesn’t support chunked encoding, since it can be configured to “dechunk” requests before passing them to a backend.
It looks a little something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
ProxyRequests Off
<Proxy http://localhost:81>
Order deny,allow
Allow from all
</Proxy>
<VirtualHost *:80>
SetEnv proxy-sendcl 1
ProxyPass / http://localhost:81/
ProxyPassReverse / http://localhost:81/
ProxyPreserveHost On
ProxyVia Full
<Directory proxy:*>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
Listen 81
<VirtualHost *:81>
ServerName ooboontoo
DocumentRoot /path/to/my/rails/root/public
RailsEnv development
</VirtualHost> |
As you can see I’ve got Apache2 listening on port 80, which uses the “proxy-sendcl” environment variable available in mod_proxy to repack the HTTP body and add a Content-Length header to the request. This request is then passed back to a virtual host running on port 81, which is configured to use Phusion Passenger.
Turns out it’s pretty simple, and from what I’ve seen there haven’t been any negative performance impacts by proxying all requests. It’s not a permanent solution, and as soon as Phusion Passenger fixes the chunked encoding bug, I’ll drop mod_proxy from our configuration.
Hope that helps someone!
ActiveRecord Model Serialisation
April 8th, 2008
I’ve been working on a JSON API for mobile clients recently, and in doing so I’ve realised how much you need to repeat serialization options throughout Rails applications despite options generally being model specific.
This little patch solves that problem by allowing you to decorate your Rails models with model-wide serialization options, like so:
1 2 3 4 |
class Article < ActiveRecord::Base has_many :comments serialization_options :include => :comments end |
This means that whenever you call to_json or to_xml on an instance of Article, you’ll get the comment association thrown in for you. You’ll find you can clean up your Controllers and remove explicit calling of to_json, which previously would have looked like this:
1 2 3 |
respond_to do |format| format.json :json => @article.to_json :include => :comments end |
But can now be change to this:
1 2 3 |
respond_to do |format| format.json :json => @article end |
While it’s very simple, some people might find it useful. If you do, chuck this in your /lib directory and require it in environment.rb.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
module SerializationOptions def serialization_options(options = {}) class_inheritable_accessor :serialization_options self.serialization_options = options.dup end end ActiveRecord::Base.send(:extend, SerializationOptions) class ActiveRecord::Serialization::Serializer alias_method :old_initialize, :initialize def initialize(record, options = {}) if record.respond_to? :serialization_options options = record.serialization_options.merge(options) end old_initialize(record, options) end end |
Andy Clarke Announces the "CSS Eleven" (WD07)
September 27th, 2007
Opening session at Web Directions today was given to Andy Clarke, who proceeded to wrap it up with an announcement of a group put together to tackle the recent issues regarding submission of proposals and recommendations to the W3C. The eleven involved are:
- Cameron Adams
- Jina Bolton
- Mark Boulton
- Dan Cederholm
- Andy Clarke
- Jeff Croft
- Aaron Gustafson
- Jon Hicks
- Roger Johansson
- Richard Rutter
- Jonathon Snook
From what was explained, their aim is to work through the CSS specifications and give feedback and examples for some of the more difficult issues, and then provide a body of work to the W3C and/or browser vendors with the hope that it things along a little faster than is currently the case. More details are sure to appear on the CSS Eleven website.
Here’s a snap of his slide:
Adobe Made Their Move, Now It's Apple's Turn
August 29th, 2007
Despite the speculative bullshit that always seems to spout from Walt Mossberg and Robert Scoble’s mouths, we still don’t really know what’s driving Apple’s decision to not support Flash content on the iPhone. They’ve also removed the Flash content from their website, which leads me to believe that this issue runs far deeper than I previously thought.
Adobe’s recent announcement of H.264/AAC support (among other things) in their Flash Player 9 product, has overnight turned Adobe’s Flash Player and Apple’s Quicktime Player into competing products. If you read between the lines, however, you might see something interesting:
“Adobe has licensed the x86, PowerPC and ARM versions of MainConcept’s H.264 and AAC decoders”
Keyword, “ARM”. Previously, Adobe have not had a Flash Player 9 SDK for the ARM architecture. For this reason, products like the Opera Browser on the Nintendo Wii have needed to settle for Flash Player 7, or in the case of Apple’s iPhone they’ve decided not to settle at all and instead ignored support for Flash altogether. Now, it seems that Adobe might be planning on releasing an SDK for the ARM architecture since the H.264/AAC support only affects the version 9 product.
Once Adobe releases an SDK, Apple will have the means to support the plugin on the iPhone. As an added benefit, they won’t need to worry about licencing On2’s VP6 codec since the H.264 videos which currently play on the iPhone, iPod and iTV will also play within the Flash Player too. Not only that, but the annoucement from Adobe also mentions support for reading iTunes metadata (“list” atom) embedded in audio and video files.
Adobe are playing straight into Apple’s hands!
So what’s Apple going to do about it? Should they embrace these changes and welcome Adobe with open arms? Keep in mind that according to the Adobe FAQ, “new releases of Flash Player take approximately 12 months to reach 90% penetration”. We’ll see this Flash Player in the wild as a release version sometime in September, so I expect Apple to have at least polarised by then.
I honestly hope that they chose to support the Flash Player. By doing so, they will put the power back in the hands of the content providors. While this doesn’t mean I expect them to re-instate Flash content on their own website, at least we’ll be left with a choice in the matter.
Which Do You Prefer, And _Why?
June 20th, 2007
This is in response to Greg Borenstein’s article titled A Beginner’s Guide to Practical Syntactic Magic: the tale of Hpricot’s sudo-constructor and Stuart Halloway’s follow-up article, With great power comes great responsibility.
Both articles make reference to the odd method-naming tricks used in Why The Lucky Stiff’s Hpricot library for parsing XML (commonly HTML). In light of those tricks, I have a question for you all…
Which of the following two snippets of code would you:
- Prefer to read
- Be inclined to write
1 2 3 |
doc = Hpricot.parse(open('http://www.atnan.com')) title = doc.at('title') articles = doc.search('.entry') |
1 2 3 |
doc = Hpricot(open('http://www.atnan.com')) title = doc % 'title' articles = doc/'.entry' |

