Mobile app development is too hard

mobile-app-development-is-too-hard

I've come to realise that mobile app development is too difficult for beginner programmers, but it can be made simpler.

Toby Kurien articles apps Android development beanshell mobile app development scriptdroid xtend

I've come to realise that mobile app development is too difficult for beginner programmers (by which I mean programmers with little software development experience, e.g. university students). This is true for most of the various SDK's I've tried (Android, iOS, Windows Phone 8). The reason it's difficult is because these new developers have to learn a lot of hard things just to get a basic app up. As an example, to fetch data from the internet and display it, they typically need to know: Views and controls, app lifecycle, design patterns and development patterns (like MVC, MVVM, etc.), multi-threading (with access to UI only on the UI thread), memory management (in a restricted environment), data usage management (caching, etc.), networking (with battery considerations), and so on. That's just the programming skills, as they also need to learn UI skills like interaction patterns, navigation patterns, native controls and skinning them, creating responsive layouts for various orientations and screen-sizes, etc. They can't ease into this knowledge, they need to absorb all of it before they can develop even the most basic app, if it is to be published on an app store. No wonder everyone wants to use PhoneGap or other HTML5 solution - there's a lot less complexity there.

I've been thinking about a possible solution to this problem. I want junior developers to be able to get common stuff done easily, and then ease into learning all of the advanced techniques as they progress. I like the Qt/QML framework: it shields you from C++ for the simple stuff by allowing you to declaratively build a UI, instantiate components to do the hard work, then string it all together with some JavaScript. It has great ways of extracting your own code into components, and the ability to use C++ to create components for the intensive/low-level stuff. This is like the Unix philosophy: create tons of little utility programs that each do one thing well, then string them together using some script (like BASH) to do useful complex things.

I thought about how I could bring this component-based approach to Android, and so I came up with a prototype (warning: demo-only, not a practical framework) to test my ideas: ScriptDroid. ScriptDroid is simply a scripting environment inside Android that can call various components (written in Java). The components can do complex things (such as an asynchronous web request), but hide the complexity with simple method calls and callbacks. Before diving into what I've done there, I'd like to talk about my thinking behind it:

Core principles

  • Simplify Android development, don't dumb-it-down. AppInventor (or evenPhoneGap) for example, dumbs-down the development experience, meaning you are limited in what you can develop using it. While PhoneGap does allow native extensions, the programmer would have to make the huge leap from HTML to full-on native development, which is a big barrier.
  • Abstract away complexity until such time as the programmer is ready to explore it, e.g. multi-threading. Multi-threading is hard, even for seasoned developers. The component-based approach makes this possible.
  • Reduce syntax burden - for a junior developer, leaving out closing braces or semi-colons, or building up SQL query strings in a language without string templating, can be daunting! They shouldn't have to waste tons of time on this. Ideally, Ruby would be the language they develop in, because it has the loosest syntax in any dynamic language I've tried, making it very beginner-friendly. I've used BeanShell script for my demo instead, as it was easy to get working in Android, lightweight, and provides some nice hooks into Java. I'd also like to try using Xtend at some point.
  • Reduce/eliminate boilerplate code as beginners find it hard to read past it. Take a look, for instance, at the boilerplate code for multi-threading on Android using an AsyncTask. It may be just a few lines, but to a beginner it's very confusing with all those generics and different execution scopes.
  • Allow messy code, and let programmers learn to refactor and use design patterns in an evolutionary way. HTML/CSS/JavaScript allows extremely messy code, but programmers learn to separate things out and re-use code as they get more experienced.
  • Quick turn-around between code change and execution. Ideally, I'd have implemented a REPL (like RubyMotion does, for example), perhaps using a TCP/IP socket connection to the app forwarded over ADB

Implementation

I simply embedded BeanShell script into Android and wrote two components to demonstrate the idea:

  • Alert - for Toasts and AlertDialogs (although I haven't implemented the dialogs yet).
  • HttpRequest - to make an asynchronous web request and return the results.

The Demo app

The demo app is extremely simple (to demonstrate the unnecessary complexity of standard code). It fetches a quote from www.iheartquotes.com and displays it. That's it. The MainActivity class sets up the scripting environment (this stuff will obviously get extracted into a library project) and finds and calls index.js (which is not technically JavaScript, it's BeanShell, but they are very close). In index.js, the layout is loaded into the Activity and then the components are used to fetch the data and display a Toast. So apart from the UI layout (which is standard Android fare), this is all the code needed:

    onHttpLoaded(data) {
       Alert.toast("got data");
       activity.findViewById(id.main_text).setText(data);
    }

    activity.setContentView(layout.activity_main);
    http.fetch("http://www.iheartquotes.com/api/v1/random", this);

Notice that BeanShell does some magic with interfaces to allow passing a function from the script to the Java component, and I've injected some Java stuff into the scripting environment for some syntactic sugar (e.g. the id and layout objects). The programmer did not need to worry about multi-threading issues and code was kept to a minimum to get the job done (apart from error-handling which was omitted for brevity). The HttpRequest component did all the schlep work.

Of course, this app could have been done as simply in Java (without the scripting language) with maybe just a few more lines of code, if it called the same components. The idea of using the scripting language is to reduce syntax burden and boilerplate code (which will become problems as this app is developed further).

Incomplete

Unfortunately I didn't reduce much syntax burden as BeanShell needs semi-colons and curly braces everywhere, but more complex code would be simpler than Java due to the loose typing. Xtend would reduce the syntax burden more, still remain strictly typed and provide tooling support, so I may pursue that at some point. This brings up the main problem with ScriptDroid: no tooling support (code completion,  compile-time syntax checking, etc.). Another problem is that errors in the script are not properly handled and displayed. I also didn't tackle the quick turn around problem, but that can be accomplished by moving the scripts into a read/write folder where it can be edited while the app is running, and also by implementing a REPL interface.

As I said, this is just a demo of the ideas, not a practical framework.

More components

This system gets more useful as you add more components and features, for example:

  • HttpRequest: implement caching, check for large response size and force a stream if so, implement GZip, and so on.
  • Alert: also add prompts and confirmations (like you get in a web browser, but using AlertDialog)
  • Timer: auto-execute a callback at certain intervals or install Alarms using the AlarmManager
  • Database: create and manage a sqlite db (perhaps ActiveRecord-style), provide cursors to data queries. Setting up and querying databases is quite a menial, labour-intensive process.
  • ListAdapter: make loading data into a ListView easy. Should have properties to enable section headers, and maybe lazy-loading callbacks to separate the intensive view rendering from the non-intensive rendering, so that scrolling is always smooth (a hard problem with multiple solutions).

Those are just some basic examples, but they are examples of common functionality that can be major stumbling blocks for beginner developers. One unintended benefit of the component approach is that the components can abstract higher-level problems by communicating their needs to a component manager. An example would be that components could register their intended memory usage, so that the component manager can reply with how much temporary memory may be available (e.g. for caching images), based on usage by other components, the device specs and heap space available. Another consequence is that the components are re-usable in Java/Xtend as well, making coding an app much easier once a suite of components are developed.

What about the UI?

I've left the UI code as standard Android XML-based layouts. I could implement a pre-processor that would allow embedding scripts into the layouts, but I think the standard Android layout XML is pretty simple already (apart from XML's syntax burden). This is the fun bit for a beginner to learn, anyway.

Wrap up

In summary, I was inspired by the component-based approach (among other things) of Qt/QML. I believe that using a scripting language together with components can make the life of junior developers much easier, while allowing them to learn the advanced programming skills as they gain more experience. Most senior developers work this way: building reusable components/classes/libraries and then stringing them together, but they are not slowed down by the syntax burden or boilerplate code like junior developers are.

I should also just mention the Jimu project, which uses a component-based approach to building an app, although it does things differently by generating standard Java code for the components used, thus resulting in an editable app.