Making your iOS Apps Portable

The explosion of the iPad on the market is taking the business world by storm. Software giant SAP deployed 1,000 units to their employees last fall, only to be eclipsed by the 4,500 tablets rolled out to the sales force of medical device innovator Medtronic by the end of the year. More and more companies are embracing the iPad as an essential tool for conducting business.

One of the biggest challenges facing these enterprises is how to bring their existing business-critical applications to this revolutionary device, while still supporting legacy desktop systems, web applications, and other mobile device platforms. In response to this challenge, the open-source MonoCross project provides a pattern for development that enables code-portability across enterprise platforms.

Code portability

People have been talking about code re-use and portability for years, but the discussions have been largely theoretical. Most large enterprise software organizations tend to create homogeneous development environments. "One Language, One Platform" has been the mantra of most shops because it's easier to manage things that way. You settle on a single technology stack and build your applications on it. The organization also dictates the infrastructure needed, as well as the devices that will be supported. Most of those decisions are made after the technology stack is chosen.

Then Apple came along with the iPhone—then the iPad, and these organizations started having these decisions made for them by their employees. This consumerization trend has turned corporate IT on its head. The status quo is no longer sufficient. "One Language, One Platform" doesn't work anymore in the rapidly changing world of mobility. Suddenly, these enterprises were facing problems they'd never had before. Supporting multiple, heterogeneous platforms had become a necessity, but very few organizations had the expertise to do so because of their homogeneous platform strategies of the past.

Fortunately for most of my clients who have already made significant investments in C# and .NET as their language and platform of choice, Mono provides a compelling path forward. Those theoretical discussions around layered architectures and re-use of code became real, and the benefits became apparent in this new world order. With MonoTouch and Mono for Android, we could clearly demonstrate that the millions of dollars spent on existing applications could be leveraged and brought to these new platforms. With the application of a few proven enterprise design patterns, significant modules could be shared across them all.

Code Portability Model diagram.NET Developers now had a choice. They could deliver native applications in MonoTouch and Mono for Android, or they could deliver web applications using HTML 5 and ASP.NET—but a new choice was also available. From our experience delivering HTML 5 applications with ASP.NET and PhoneGap, we saw a new pattern emerging. Native device integration could be achieved in HTML 5 via the JavaScript interface, and custom URI schemes. Now developers could build applications across the hybrid spectrum, delivering as much or as little native vs. web functionality as their use-case required. Web techniques could be used where they were strongest and native techniques used where they excelled. Not only had Mono enabled cross-platform development in C# and .NET, it had enabled cross-architecture development.

This code portability model has become the foundation upon which we have built the MonoCross pattern. The core principles of code-reuse span not only across platforms, but also across architectures. That became our rallying cry and it remains our vision moving forward.

Coding across platforms and architectures

This realization of code portability across both the platform and architecture dimensions was exciting, but we knew there were some practical problems that still needed to be solved. Most business and data access code could be ported and shared easily. We had proven this in our initial experiments with MonoTouch. But the UI paradigms exposed by the various native SDK's were decidedly different. Beyond that, we had to solve the problem of workflow and navigation. How do you enable cross-architecture development when the fundamental construction of application screens varies so much between web and native implementations? Finally, we needed to provide a mechanism to handle changes to objects that were in-play and successfully communicate changes from the UI to the shared application.

Separating the user interface

Make PortableThe solution to the mismatch in UI paradigms was obvious. We needed to provide for fully customized views in the presentation layer, while sharing as much of the other application code as possible.

Make PortableTo accomplish this, we settled on a modified Model-View-Controller pattern that uses a separated view-interface to loosely couple the View and Controller. As long as the custom view implements the correct interface, the shared Controller code can interact with it as needed.

Defining the application workflow

We also needed a mechanism to define the application workflow in a manner that would easily translate from native to web-based architectures—this was an absolute necessity in achieving our vision of cross-architecture portability. We knew we needed to provide for stateless navigation to support web architectures, but needed a way to accommodate the event-driven application interaction model in the native platforms. We settled on a URI template navigation model in the shared application. This model provides for seamless integration in web scenarios, while exposing hooks to the native views to initiate actions in the shared controllers. Controllers are registered with one or more URI endpoints that follow RESTful design principles to enable multiple workflow paths, and full CRUD data operations.
NavigationMap.Add("", new CategoryListController());

NavigationMap.Add("{Category}", new BookListController());

NavigationMap.Add("{Category}/{Book}", new BookController());

The Navigation Map is shared across platforms, and the use of a URI-based navigation scheme further extends the MonoCross architecture to support URI-based device API's, web links, and deep-linking to other MonoCross applications by registering your own custom URI schemes.

MonoCross containers

Much of our work of late has been to continually refine the container concept in MonoCross. A container is a platform/architecture specific executable that runs a MonoCross application. The container is where calls between the shared application, (i.e. Model and Controllers), are marshaled to and from the platform specific UI implementation, (i.e. Views). The purpose of the abstract MXContainer class is to provide the base interface and implementation that is extended to each specific platform target. These concrete containers, one per platform, mitigate much of the mismatch between platform UI paradigms. They serve as an application wrapper, message broker, and utility interface, and are a critical component to MonoCross.

Handling changes

To achieve the necessary communication of changes, including validation and CRUD operations, we settled on an Observer pattern on the container to notify the shared controllers of changes to the model. The MXContainer implements a NotifyViewModelChanged() method that is exposed to the Views.

 new CategoryListController());


new BookListController());


new BookController());

We're also exploring a move toward a pseudo-MVVM pattern to achieve synchronization of model changes in the shared application; this is actively evolving as we speak.

Moving MonoCross forward

We continue to refine and evolve the pattern—and we want your help! Please visit the MonoCross project and get involved. The current roadmap is published there, and there is plenty of opportunity to help us take this into the future. Suggestions are welcome, and our hope is to build a vibrant community around MonoCross. Come join us!


July-August 2011
Creating Apps
TOC Weight: