Monday, 28 November 2011

Hello, RoboBinding (part 1)

At a recent Londroid meetup I listened to an interesting talk by Gonçalo Silva where he assessed the Android automated testing landscape.

Amongst other things he lamented the obstacles facing Android developers wishing to unit test their code, in spite of the emergence of frameworks like RobolectricEven with the help of such a framework he argued, developers are ultimately dependent on its underlying implementation, which doesn't necessarily reflect the implementation of the real-world devices being targeted. Furthermore, writing testable view-oriented code (as with most GUI frameworks) is a tricky affair.

These factors serve to undermine the confidence and value developers can derive from their tests, and the ease with which they can write them.

Whilst I remain a strong advocate for using tools like Robolectric, I can't help but agree.

Unit testing on Android remains challenging. I can empathise with Paul Butcher's conclusion that "Android is the most test-hostile environment I’ve ever had the misfortune to find myself working in". Fortunately for Paul, he clearly hasn't been subjected to BlackBerry development. Nevertheless, the Android designers certainly didn’t do a great job of making things easy and in his talk, Gonçalo went on to argue that ultimately the way we architect our systems has a crucial role to play.


On a related note, I've recently started working with Cheng Wei on an open source framework called RoboBinding. RoboBinding is a Presentation Model framework for Android.

The goal of the presentation model approach is to extract all the state and logic out of the views into a separate class, a class that ideally has no awareness of the views that are attached to it. Updating of the views to reflect the state of the presentation model, as well as the routing of user input events, is achieved through a synchronization or 'binding' mechanism. What remains are a set of lightweight views and a presentation model class that contains the distilled view logic.

Since a presentation model class contains only view logic with no dependencies on the views themselves, tests can be simple and concise to both setup and write. UI aside, there need not be any dependency on Android framework classes so the code can be free from the testability constraints imposed by the platform. Furthermore, as the code is more loosely coupled, maintenance overhead is reduced. Readability is also improved through clean separation of concerns.

RoboBinding requires a (pure pojo) presentation model class to be supplied at the time of view inflation (typically when calling Activity.setContentView(..)). To synchronize views with the properties and commands exposed by their presentation model, users declare bindings in their layout xml. Aside from that, the framework does the rest - all the wiring of views to the presentation model is handled transparently, keeping your code clean, focused and testable.

How many times have you needed to fix a small UI bug, only to stumble across the relevant Activity and find it stretches to hundreds (thousands?) of lines. The onCreate() method and instance initializers are likely overburdened with initialization code and umpteen findViewById() calls. What's more, it’s likely laced with numerous anonymous focus, click and text listeners, all required to wire the system together. Lost within that morass is the code you actually want to get to, the logic that will affect the state of the UI. RoboBinding's aim is to alleviate this pain, providing users with a cleaner, more testable foundation.

As it happens, the idea of data binding in Android has been tried before. Andy Tsui's Android Binding framework has been available for around a year (see Roy Clarkson's good introductory article covering it here). At the time of writing Android Binding is certainly more feature rich than RoboBinding, so if you would like to experiment with an existing alternative I recommend giving it a try.

The comparative strengths of RoboBinding, as well as a detailed look into how to use the framework will be covered in the next post. In the meantime, please checkout the code on GitHub and let us know your thoughts.


UPDATE: Part 2 of this series is now available.


Disclaimer: portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License