Mobile

Experimenting with mobile application development

One of the key ideas I took with me from Devoxx a while ago was this: mobile app development is hot. I wanted to gain some experience in this field so I decided to create a pet app to mess around with: WhereIsMyCar. It does exactly what the name implies: the app lets you take a picture of your parked car and it stores this picture and your current coordinates so you can easily find it again after a long night of coding. The reason I went for this kind of app is twofold:

  • It’s limited in scope, so I wouldn’t be coding for months on end
  • It uses some of the newer device/HTML5 capabilities (taking pictures, geolocation, localstorage,…) so I could also gain a little experience with those.

After deciding on which app I was going to build, I hit the next bump in the road: should I go all-native, or should I create my app in a non-platform-specific way? Martin Fowler has an excellent infodeck on this topic here. Since I did not want to limit myself to the Android platform right off the bat, I went for the cross-platform option.

Cross-platform app development = HTML5 + javascript + device wrapper framework

That about sums it up. You create a nifty website using HTML5 and javascript (Dojo, jQuery, or whatever flavor you prefer), choose a framework that wraps all device-specific behaviour (such as taking pictures with your Android phone or iPad) in a single API and you’re good to go. I went for the Cordova framework (previously known as PhoneGap), since at the time this was one of the only mature frameworks with decent documentation.

I decided to start up my Eclipse IDE, with the intent to quickly get an “Hello World” app running on my smartphone. To sum it all up, there are roughly two ways to get this to work:

  1. You can download a ton of Cordova libraries/ADT plugins/Android SDKs to your machine, so you can create Android apps in Eclipse (for an overview, click here). -Wait, what just happened? Didn’t we just choose to go for a platform-independent solution?- Turns out that it’s not all that bad if you are developing on a single platform (I only have an Android phone), but plan to release your app to other platforms. All you have to do then is open your platform-specific IDE (XCode for iOS, Eclipse for Android), again download a ton of platform-specific libraries/plugins/SDKs and link to your existing HTML5 app there.
  2. For those of you that don’t want to go through this configuration hell (especially when you want to see your app in progress running on multiple platforms), the guys at phonegap have made available a nice alternative: phonegap build. To sum things up: you upload your web app (HTML5 + plain javascript using the Cordova javascript framework) to their servers, they build your app for every possible platform and you just download the app installer for the device you want to deploy your application to.

I went for the first option because I did not want to wait 2 minutes everytime I wanted to build my app after some small changes.

After *ahem* easily configuring my first mobile project in Eclipse and succesfully deploying my “Hello World” app to my smartphone, everything would go smoothly, right? Not quite. Turns out that:

  • Best practices in design/testing also apply on mobile development
  • There are some subtle tradeoffs between using the Cordova framework and using the new HTML5 capabilities like media-capture and geolocation.

Testing woes

In order to adequately test my codebase, I wanted to keep the number of dependencies on any external library (including Cordova) low and use dependency injection in the cases I really needed them. The motivation behind this is simple: the Cordova framework code is designed to run on a mobile device, so it would be impossible to run any unit tests on my desktop computer if the code-under-test had any dependencies on Cordova.

The codebase did not start out that way (my main issue was purely personal: I did not have much experience with the javascript language and there are some intricate differences between modern OO-languages and javascript). Thanks to J.B. Rainsberger’s advice I was able to succesfully refactor my codebase to something more testable (and indeed, with better design).

To make things a little bit more tangible: here is an example refactoring I performed (note that this is only a part of the code so I can make my point clearer):

Initially, I had a hardwired dependency on the getPicture method of the Cordova API:

takePicture : function(){
function onSuccess(imageURI) {
//store picture
};

function onFail(message) {
//error handling
};

navigator.camera.getPicture(onSuccess, onFail, { quality: 100, destinationType: Camera.DestinationType.FILE_URI });

}

This meant that I could not test this bit of code. After the refactoring, the code looked like this:


var takePictureFunction;

initialize : function(takePicFunction){
takePictureFunction = takePicFunction;
},

takePicture : function(){
function onSuccess(imageURI) {
//store picture
};

function onFail(message) {
//error handling
};

takePictureFunction(onSuccess, onFail);

}

After this refactoring, I could easily test this piece of code by providing a dummy implementation of the takePictureFunction. This also moved all my Cordova-specific code to a single point in the code. It removes framework-specific code from my own modules and if I ever decide to switch platforms (or go full-on HTML5), things will be less painful. Note that the refactoring actually increased the size of my codebase because of the hardcoded dependency injection, but I find this is a small price to pay for all the added benefits. There are dependency injection frameworks for javascript that take care of this boilerplating for you, but I thought this would be an overkill for a project of this size.

The key idea for me to take away here:

Mobile apps tend to have less “complex business logic”, but that does not mean you shouldn’t apply industry-wide best practices regarding design and testing.

Framework vs. HTML5 capabilities

For several features I had the option to choose between HTML5 native functionality or some Cordova API method. There are several examples (again, this is why I went for this kind of app): geolocation, media capture or storing data in the browser’s localstorage.

As it turns out, both options have their advantages and drawbacks:

  • Using the Cordova API will introduce additional dependencies on the framework, making it harder to move to another platform in the future. It will however work out-of-the-box on most mobile platforms.
  • HTML5 is new. Very new. This means that not all browsers support the full standard (check out a very nice overview here) and browsers that do might have different implementations. This is especially interesting when you unit test in one browser (in my case, Chrome using the QUnit testing framework), but the app runs in another browser (the built-in Android Web Browser). I bumped into problems with HTML5’s LocalStorage and Geolocation. The LocalStorage API (nice reference here) has two different syntax flavors: dot-notation vs. get/setItem syntax. IE apparently does not support the dot-notation.  Chrome however was giving me a hard time enabling Geolocation on my integration test html page. I wanted all my unit tests to run in a single browser, so I had to jump through some hoops here.

Closing thoughts

Although I barely scratched the surface of mobile application development (I haven’t even said anything about user experience, performance, security, distribution of your app,…), this was an interesting adventure into a new domain. Lessons learned from this experiment:

  • Don’t abandon software engineering principles when entering a new domain.
  • Bleeding edge technologies are just that. Don’t expect the same as you would from a mature one.
  • Creating your very own app to show off to friends is such fun!

[UPDATE] I just finished reading “Responsible Design for Android” by J.B. Rainsberger. He uses the native approach as opposed to the cross-platform one, but the book illustrates the “responsible” part of solid design and testing very nicely.

[UPDATE] I have put the source code on github. For those of you who just want to try out the app, use this link or the QR code below for the Android version.

downloadWhereIsMyCarQR

Standard

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.