A few years ago now, we evaluated web-based mobile apps on the Phonegap platform – before Adobe took it over, donated Cordova to the Apache foundation, and started adopting it big-time.
It seemed a nice potential way to build smaller, less sophisticated apps in a way that could reach many platforms. Indeed this is often the challenge of small business looking for mobile tools – money and device constraints.
While our native app business is doing well at the top-end of the market, we thought it might be interesting to delve again into the lower-end of the market and see how tools have evolved.
My new approach was pretty specific – build a pattern to rapidly construct web-based mobile apps on top of Phonegap as Single Page Applications (SPAs). It’s been an interesting journey the past couple months.
Our prototype app, which will be hitting the App store soon, we built in conjunction with Bob Almack, a local expert on Dyslexia. For his business, he needed a tool to help with assessment of students with regards to their level of visual word processing difficulty that accompanies Dyslexia. Dyslexics (sorry, I hate using labels) have difficulty often with things like reversing letters, but current belief is that it’s something akin to thinking too fast for your mouth to form the words. They tend to be very smart, but underestimated by the education system because of this visual processing issue which makes it seem like they have a learning disability. One of my daughters is diagnosed with dyslexia, and I’ve seen all this first hand. By the way, she’s a relentless reader now, and has consumed books at a frightening pace for years.
So, about the app.
We’ve been using KnockoutJS for years, and in the context of web-apps I really like the MVVM (Model-View-ViewModel) pattern – I think often the MVC (Model-View-Controller) approach tends to end up with heavy-weight controllers where domain specific concerns can become muddled in mechanics.
In web-apps with a server component, it’s convenient to keep the Controller layer and heavier logic on the server – where you’ve got far more processing capability than on that tiny mobile system. But for SPAs, where to put business logic…
A recurring theme at SCNA 2012 (Software Craftsmanship North America) was Functional Core, Imperative Shell. I wanted to stay as lightweight as possible (the budget on these apps is minuscule), and I needed to keep design clean so that if development continued on any of these projects, we could keep a reasonably level velocity.
So the initial approach I took was an imperative shell around business-level classes that encapsulated behaviour and data, with an eye towards developing more functional overtones once my overall structure was established. Hey, I need to pick my battles 🙂 and today was not the day to tackle this one.
We decided to apply Adobe’s PhoneGap platform as the wrapper, put the project up on Github and even used the PhoneGap Build platform to do our multi platform app builds.
I initially built out the app on just KnockoutJS trying to keep it simple, the less additional framework overhead I needed, the better velocity I could maintain even if it meant some more code. In the end though, on an SPA, I couldn’t contain the complexity around managing multiple views by-hand. On web-apps I just use a simple state-machine to take care of things, with some business-level events, but it just got too hairy inferring transitions and ensuring I had enough events firing to keep things managed once the number of views got above 3 or 4.
Not to be discouraged, I decided to re-write using Durandal as a master framework, which utilizes RequireJS and KnockoutJS and layers on a view and routing system that is nice and simple. Getting the Durandal skeleton in place went well, and I really enjoyed the way it removed the friction of managing multiple views in a Knockout driven app.
Initial impressions were good, the default PhoneGap platform skeleton even bakes in some Jasmine JS testing so you could explore some test-first development, but the default test cases do nothing to show new developers how to use it on their own projects – being too mired down in testing their default load event-processing mechanics. I wouldn’t be surprised if most developers, even if they might be amenable to test-driven-development, just dropped that whole part of the skeleton because it’s just so uninviting.
We’ve actually gone full days sometimes awaiting iOS builds to complete to get testing done in the field. Not cool.
From a technology standpoint, this was no big deal though. Adobe will solve this problem pretty handily at some point. But some real insidious issues began to surface that became bigger barriers.
For example, Cordova/Phonegap has an XML file that should let you declare all of the icons and splash screens to use when packaging your apps. Current tally as of today is we need 14 different icon sizes for iOS alone, 8 different size launch screens for iPad and 3 for iPhone. Never mind Android, Windows Phone, and Blackberry sizes. That’s a lot of derivative assets, and you can easily get bogged down in the mechanics of putting all that together. Especially on a micro-budget.
So I was pretty pleased about this declarative XML file. I lit up ImageMagick and some scripting and from a single carefully crafted 2200x2200px icon we generate beautiful icons in all the sizes we need in just a few seconds. Same thing for the launch screens, from two carefully crafted high-resolution images – one in landscape and one in portrait mode, we size and crop out all the images we need.
The challenge? Well, the PhoneGap Build platform mangles your images. Launching in landscape or portrait looks horrible everywhere. Weird screen flickers, the worst I couldn’t catch in the screenshot here.
No problem, I thought, we’ll just do a local build. And? Well, the PhoneGap command-line tool doesn’t set up your icons in your platform projects. That means I need to actually boot up Xcode, open the project, manually put in all our icons and launch screens, and fix the settings for allowed orientations. There goes my micro-budget.
You could argue that on a long-running project, you should only have to do this once, that PhoneGap does an incremental build for the platforms. But on a series of micro-budget projects, you need to do this over and over again. We’ve scripted out what we can for now, minimized what time we can, but I’d rather see that time go towards a better fleshed out app than appeasing the ever-increasing overhead of platform specifics.
The local Android build process wasn’t much better. Given how Java is largely persona-non-grata these days on OSX, ensuring that the JAVA_HOME environment variable is set up correctly, and getting undocumented dependencies like ANT installed (thanks Homebrew!) were reasonably small hurdles. The bigger hurdle remains the poor state of support for Java security on OSX – I still can’t get the high-crypto Java add-on working correctly on Mavericks, and as such my Android dev keys aren’t as strong as I’d like. Code-signing was tricky because of all the different permutations and combinations of key types, lengths, and hash algorithms you might be using (many folks by accident, because this is a deep poorly understood world unto itself). Oh, and for some reason Phonegap insists on specifically the v17 version of the ADK. Go figure.
In the end, I have a reasonable pattern to follow now for simple apps. Over the coming months I’ll be strengthening the testing support in the pattern, adopting something like mimosa for more automation, and whatever else comes to mind before we open-source the skeleton in the summer.
In the meanwhile, despite the hurdles, we have a great pattern for entry-level mobile apps that lets us get a good amount of time focused on the business problem at hand instead of infrastructure, on project budgets from $3-10K.
So all in all, I’m pleased 🙂