Softwire Blog


A War on State


3 February 2016, by

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.

We’re using the repository pattern throughout to enable this. We have a set of repositories in our javascript code which load data and manage internal caches using HTML5 local storage, and we’re then able to get away with just passing IDs between pages, because we know the next page will be able to load any information it needs from the repositories at very little cost.

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!

Smooth transitions in Cordova / Knockout


15 January 2016, by

Here at Softwire, we’ve been busy building a mobile app for a chain of health clubs, and this is the third 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. Take a look at the first post to read about what Cordova is or the second to see some of the other practices we use to make Cordova feel as app-like as possible.

One of the important requirements was for scrolling and transitions to be smooth and to avoid the screen juddering. Lack of polish and smoothness is one of the most common objections raised against Cordova; it’s an easy trap to fall into, but simpler than you might expect to solve once you’re aware of it.

Work with the phone

Modern phones have powerful graphics processors, so we want to offload as much of rendering onto the GPU as we can, to keep the CPU free and ensure our rendering goes at top speed.

Let’s say we’re using CSS to move an element ‘my-page’ off the right of the screen by applying the ‘off-right’ class.

We could write:

#my-page {
    left: 0;
    transition: left 1s;
}
#my-page.off-right {
    left: 100%;
}

This will work, but it’s not typically run on the GPU by most browsers, which means performance may take a hit if you have many or large elements moving like this across the page.

Fortunately we can replace this equivalent to get GPU acceleration, with:

#my-page {
    transition: transform 1s;
}
#my-page.off-right {
    transform: translateX(100%);
}

The ‘transform’ property here is designed to be easy to handle on the graphics processor, and so runs much more smoothly.

Don’t stop me now

We’re building our app as a single-page website, within Cordova. As part of this, we’re using Knockout.js to do data bindings. Knockout is a simple way of keeping your javascript object models in sync with the HTML (or ‘binding’ them together, in Knockout lexicon).

It’s important to understand how this works to improve performance though, with Knockout or other similar frameworks. When you change the value of a Knockout-observed variable, Knockout will immediately make the corresponding change to the HTML, and each of these changes in the HTML will cause the browser to re-render the relevant part of the page. If a large part of the page is moving when this re-render is trigger then it will appear to stop, re-render and then continue moving, causing a noticeable judder.

This is particularly noticeable if you update properties across an array of objects. Knockout interprets each of these as a separate change and causes the page to re-render multiple times, resulting in a very juddery transition! Doing this is generally bad for rendering performance, but it’s a very easy pattern to fall into with many modern single-page app frameworks.

To solve this, in our app we’ve been careful to make sure we never change knockout-bound values whilst we’re transitioning. When we move between pages, we’ve adopted a workflow like this:

  • 0 ms
    Create new page, start loading data and binding each part to the page.
  • 100 ms
    Pause data bindings. Put any data change requests in a queue.
    Start transition (transition lasts 500ms).
  • 600 ms
    Resume data binding. Process any queued requests.

In our testing we’ve found that the first 100ms is typically long enough for data to be fetched from the cache and rendered, when it’s already cached, without being long enough for the user experience to suffer.

Nothing to see here

Generally, we’ve been very happy with the performance of Knockout, but it’s performance can degrade with increased load. Every data-bound value causes extra work for it, and slightly reduces performance. For best performance, we should minimise the amount of data that Knockout is binding.

For us, this means segmenting the app into different ‘journeys’ and ‘pages’ and ensuring Knockout is only data-binding the journey and page currently in use, and disposing of the data and DOM elements not relevant to the current page. Within some of our larger pages, we take this further, and change what data is bound as the user moves around the page. This requires some discipline for us to remember to destroy pages and journeys as soon as we’ve finished viewing them, but has been well worth it in performance benefits. If there’s “nothing to see here” then it’s best if Knockout doesn’t have to keep track of it.

All this has come together for us fantastically; despite being built with Cordova the app feels snappy and quick across a wide range of devices, and our customer is very happy with the result.

In the fourth and final post we’ll look at how we architected the app to ensure maintainability for the future. Keep an eye on our blog for the next edition, or follow us on twitter for updates.

What does it mean for an app to feel like an app?


21 December 2015, by

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.

As a quick recap: Cordova is cross-platform way of building mobile apps using web technologies. As a developer, you write a regular website using HTML, CSS and javascript, and Cordova takes this website and creates an app that is a wrapper around the website.

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.

No 404s

We’re lucky to have some really nice designs for the app, and we wanted the entire UI to live up to these.

IMG_0014IMG_0017IMG_0019

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.

Smooth transitions

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.

Write an app without writing an app


16 December 2015, by

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.

What’s the alternative?

(more…)

Ice Skating


13 December 2013, by

To celebrate the festive season, 13 Softwirians went to Somerset House to…

We skated (some forwards, some backwards, some into other people)

We ate mince pies, we drank mulled wine (actually apple crumble and mulled cider), and we were merry

Here’s a photo of us all:

Skaters