28 October 2016, by Chris Arnott
If you want to write a phone app, and want it to run on multiple platforms, but don’t want to spend large amounts of time maintaining two code bases, then there are several solutions that allow writing one app, and deploying it to several platforms.
These multi-platform apps work by running a mini website on a phone, which is accessed via a web view, which is how the app appears native.
In this post, we’ll discuss several different approaches to writing a multi-platform app, and have a look which situations you should choose each option.
3 February 2016, by James Griffiths
Here at Softwire, we’ve been busy building a mobile app for a chain of health clubs, and this is the final post in a four-part series about our experience and what we’ve learned.
We’ve chosen to build the app using Apache Cordova, so our code can easily run on both iOS and Android platforms. Take a look at the first post to read about what Cordova is, the second to see some of the practices we use to make Cordova feel as app-like as possible, and the third to see how we keep our transitions smooth in KnockoutJS.
In the nearly 16 years we’ve been around, we’ve supported many customers’ projects – including maintaining and supporting this customer’s pre-existing web application, which allows users to book exercise classes and tennis courts. All this has given us great insights into what makes software easy or difficult to maintain.
One of the major causes of difficulties in the old website, and elsewhere, is unnecessary state.
As you browse the website, the site builds up a large collection of state about your visit, which it then uses to work out what should be displayed on each page. This means if we find a bug it can be quite time-consuming to work out where each piece of state was originally set, and how the various pieces of state interact.
For the mobile app, we definitely didn’t want to repeat this mistake. We decided to declare war on state and to focus within this project on making the app as stateless as possible, so it was easy to reason about, understand, and maintain in future.
What did this mean for us?
There’s an API for that
To start with, we decided that the app should communicate with the back-end booking system using a stateless RESTful API.
Each API request that the app makes contains all information that the API needs to complete the request, meaning that the API doesn’t need to remember details of any previous requests.
This makes testing significantly easier, as the back-end API can now be tested separately from the app. Debugging is also much easier, as the isolated requests make it clear whether a bug is caused by the app, or the API.
Let’s go on a journey
The design of the UI in our app is reasonably complex; it’s built from hundreds of moving parts, each of which can change depending on the state of the user’s booking.
To reduce the amount of common state that we have to deal with we’ve divided the UI of our app into 3 ‘journeys’, each of 4 separate pages. Each journey is responsible for the flow between various pages, and the interactions between the pages required to make this work. Each page is then responsible for the details of a specific part of that journey.
These are represented by ‘journey’ and ‘page’ view-model objects within our code; any state relating to how the journey and pages are displayed is stored on these objects. Each time the user starts a journey, we create a new instance of the journey and page objects, and when the user leaves a journey, we destroy the journey and page objects. This ensures the journey and pages never contain state left over from a previous visit.
On a strictly need-to-know basis
In the old website a great deal of information was passed between pages, including large, complex object models, dramatically increasing the complexity of the codebase, and making it hard to tell where any information came from.
For the mobile app we have taken the opposite approach and pass around as little information between pages as possible, usually just a single ID, e.g. the ID of the exercise class being booked, or the ID of the booking.
If it breaks, turn it off and on again
Within our app we’re using quite a few fancy UI widgets. One of them – a swipeable carousel of dates – doesn’t play very nicely with Knockout: every time we change the list of available dates, the widget re-draws the carousel vertically, rather than horizontally! Clearly this widget isn’t stateless, sadly, as it’s appearance isn’t just a function of its inputs, but is also affected by its previous state.
We spent a while trying to fix this in the widget itself, but to no avail. Fortunately, we then thought of another approach: instead of changing the list of dates, simple destroy the old widget and create a new instance with the new set of dates, which worked a treat.
This change essentially makes the widget stateless, from our point of view, by destroying and rebuilding it at any time when the state might change, so that the widget’s appearance is instead based only on its current inputs. When statelessness gets difficult frequently and pre-emptively “turning it off and on again” can actually get you remarkably close!
21 December 2015, by James Griffiths
Here at Softwire, we’ve been busy building a mobile app for a chain of health clubs, and this is the second post in a four-part series about our experience and what we’ve learned. Watch this space for the next instalment, or follow us on twitter for updates!
We’ve chosen to build the app using Apache Cordova, so our code can easily run on both iOS and Android platforms.
For the iOS app to be available on the App Store it needs to be approved by Apple. One of Apple’s requirements that is particularly relevant for Cordova apps is that the app “feels like an app, not like a website”.
What does this mean for us? There are a lot of components to this, but in this post I want to look at how it’s affected our approach to client-server interaction.
We’re lucky to have some really nice designs for the app, and we wanted the entire UI to live up to these.
To keep this user experience really smooth one thing we really have to ensure is that we don’t ever show the user an ugly 404 page.
On a regular website, a user moves from one page to another. Each page is loaded individually from the server and contains the data they have asked for, as well as the code needed to take them to other pages.
This wasn’t an option for us. Our app users might be on the move, underground or have a slow data connection. If we built the application extremely minimally as a wrapper around a traditional server-hosted application then we’d be making these page requests in an environment where they might fail. We can’t risk showing them an half-loaded page or, even worse, a 404.
Load data, not code
To solve this, we’ve built the application as a single-page website. All the code is bundled into the initial download – that way, all our pages load instantly, without having to wait for any code to be downloaded. This approach is an important part of good Cordova development, and helps solve the error handling issue above and reduce latency for users to keep the app feeling snappy.
The only communication we have with our servers is to send and receive data (rather than code). We have a RESTful API that manages all our operations, like loading class timetables, making bookings and getting club opening hours.
If any of these API requests fail we can show the user a pretty error message, and allow them to retry, without the app looking broken.
The app looks beautiful so we want it all to perform well on the phone. That includes loading pages, but we also want scrolling, swiping and transitions to all be smooth, and to avoid the screen juddering.
In the next post we’ll look at how we achieved this. Keep an eye on our blog for the next edition, or follow us on twitter for updates.
16 December 2015, by James Griffiths
Here at Softwire, we’ve been busy building a mobile app for a chain of health clubs, and this is the first post in a four-part series about our experience and what we’ve learned. Watch this space for the next instalment, or follow us on twitter for updates!
We were recently asked by a large chain of health clubs to build an app for both iOS and Android platforms. We chose to build the app using Apache Cordova, rather than writing separate native applications. Why did we choose Cordova, and how do you get started with it on a new project?
The problem with native apps
At Softwire, we’re used to building native mobile phone apps, but building native apps comes with a number of difficulties:
- Each platform requires you to learn and use a specific programming language, development environment and set of libraries.
- You have to maintain a separate codebase for each platform and keep the code in sync between platforms.
- Each platform has its own quirks and bugs will typically be different in each platform.
All of this makes native development potentially more expensive and risky, and we’ve been interested in investigating other approaches for a while.