Hoe wij efficiënt onze mobiele apps bouwen

· 02-05-2017
Door slim naar de architectuur te kijken is het Moneybird gelukt om met beperkte inspanning mobiele apps te bouwen die door duizenden ondernemers worden gebruikt. Joost legt uit welke keuzes gemaakt zijn tijdens het bouwen van de nieuwe apps voor Android en iOS.

Bijna een half jaar geleden hebben we onze nieuwe mobiele apps voor iOS en Android gelanceerd. De apps zijn in drie maanden tijd met een klein team gebouwd en worden nu maandelijks door duizenden ondernemers gebruikt. We hebben bewust voor een hybride oplossing gekozen. Hiermee willen we uiteindelijk het grootste deel van de functionaliteit van Moneybird die op desktop beschikbaar is, ook op je mobiel gaan aanbieden. De desktop versie van Moneybird bestaat op dit moment uit ruim 300 verschillende schermen met allerlei interacties. Onze grootste uitdaging is dan ook de vraag hoe zo'n complexe applicatie naar een mobiele applicatie is te vertalen met hetzelfde gebruikersgemak.

De complexiteit van Gaudi... of toch eenvoudiger? #

In 1883 kreeg Antoni Gaudi de opdracht een kerkje te bouwen in de binnenstad van Barcelona dat in enkele jaren af zou zijn. Na tien jaar besloot hij de rest van zijn leven er aan te wijden omdat hij inzag dat het anders nooit af zou komen. De Sagrada Família (opent in nieuw tabblad) is na meer dan een eeuw nog steeds "Work in progress". Natuurlijk is de Sagrada Família een waar meesterwerk, maar alle details zorgen er ook voor dat de bouw een ontzettend complex traject is. Op het merendeel van de foto's is dan ook een grote bouwkraan te zien:

De Sagrada familia in Barcelona

Er zijn veel gelijkenissen tussen de bouwkundige architectuur en software architectuur. Projecten die enorm uitlopen of in z'n geheel niet afkomen. Budgetten die worden overschreden of projecten die vanwege gebrek aan geld maar half af zijn. De lessen die we van het werk van Gaudi kunnen leren zijn vrijwel één op één te projecteren op softwareprojecten. De volledige experience van Moneybird vanaf de grond af opnieuw bouwen in zogenaamde native apps (in Java en Swift) voor Android en iOS is een onbegonnen klus voor een klein team zoals wij. Het ontwikkelen in Swift en Java is zeer tijdsintentensief op deze schaal. Apps met een dergelijke omvang hebben in de regel ontwikkelteams met tientallen programmeurs.

We zagen het daarom niet zitten om onze mobiele apps onnodig complex te maken, en besloten op zoek te gaan naar eenvoud en wendbaarheid. Die eenvoud zat reeds in de HTML-versie voor smartphones die erg succesvol werden ontvangen en bovendien goed beheersbaar zijn in HTML, CSS en Javascript. Browsers op je smartphone zijn tegenwoordig razendsnel en ook het ontwikkelen voor het web is ons erg vertrouwd. Daarnaast is Moneybird een typisch voorbeeld van een app die als Progressive Web App (opent in nieuw tabblad) prima zou kunnen werken. Onze gebruikers willen heldere interfaces die eenvoudig te begrijpen zijn. Special effects zoals in games zijn overbodig.

Wanneer we native apps zouden gaan bouwen wordt het beheren van designkeuzes binnen de code een stuk lastiger. Op diverse plekken in de code staan `if` en `else` condities die bepalen wat in welk scenario moet worden weergegeven aan de eindgebruiker. Een eenvoudig scherm, zoals de weergave van een factuur, bevat bijvoorbeeld al tientallen designkeuzes en bijbehorende `if` en `else` condities.

Volledig native apps voor Android en iOS zouden ervoor zorgen dat deze keuzes ook in Java en Swift geschreven moeten worden, met als gevolg dat binnen Moneybird programmeercode in drie verschillende talen uitgevoerd zou zijn. Dit is niet voor iedere medewerker in het team leesbaar, waardoor de ontwikkeling stroperig zou voelen.

Native navigatie, weergave in HTML #

Toch wil je gebruikers een ervaring bieden die een "echte app" benadert. Na diverse prototypes met een eigen hybride oplossing kwam Turbolinks for iOS (opent in nieuw tabblad) en Turbolinks voor Android (opent in nieuw tabblad) beschikbaar. Het bleek voor ons de ideale oplossing om apps te bouwen die een native experience benaderen en de mobiele webviews te blijven gebruiken als uitgangspunt. Onderstaande video geeft een uitstekende uitleg van de mogelijkheden van de native wrappers van Turbolinks voor iOS en Android:

Turbolinks maakt het navigeren door je webapplicatie sneller. De voordelen qua performance van een single-page applicatie worden behouden, zonder de complexiteit van een client-side Javascript framework. De eenvoud van HTML kunnen we daardoor behouden en de webviews gebruiken die we al hadden. Wanneer er op een link wordt geklikt vangt Turbolinks de request naar de server af. Turbolinks doet vervolgens zelf de request naar de server en vangt het resultaat op, waarmee inhoud van de `<body>` en `<head>` op de bestaande webpagina wordt vervangen. Binnen de Ruby on Rails-stack, waar Moneybird op gebouwd is, waren we al erg bekend met Turbolinks. Met Turbolinks voor iOS en Android waren we daarom vlot in staat om de mobiele webviews in een app te gieten waarmee we toch native controls kunnen behouden. Daardoor voelen de apps nog steeds heel prettig aan.

De Bridge: de verbinding tussen native en webview #

Om tussen de mobiele webviews en de native componenten te communiceren gebruik je een zogenaamde Bridge. Tot op heden is er nog weinig te vinden over de opzet van een dergelijke Bridge. Wanneer je besluit om gebruik te maken van Turbolinks voor iOS of Android zul je waarschijnlijk voor je eigen webapplicatie een Bridge moeten schrijven die aan je specifieke wensen voldoet.

Nadat Turbolinks een pagina bezoekt, bijvoorbeeld de pagina om een inkoopfactuur te bekijken, wordt vanuit de native applicatie de Bridge aangeroepen op de webview. De Bridge is in Javascript geschreven en geeft een JSON response met informatie over de huidige pagina terug. Aan de hand van deze JSON response wordt de blauwe navigatiebalk in de native applicatie opgebouwd. De JSON response bevat onder andere het volgende:

  • Is er een terugknop in de blauwe navigatiebalk?
  • De titel van de pagina
  • Het menu met acties met een bijbehorende lijst met knoppen (Registreer betaling, Bewerken, Verwijder document)

De verbinding tussen native en webview

In het bovenstaande voorbeeld zie je het verschil tussen het actiemenu in de webviews in Safari en de native applicatie voor iOS. Zoals je ziet worden de items in het HTML-menu van de webview omgezet naar een native menu in iOS. Dit wordt gedaan doordat `Bridge.getMenuItems()` wordt uitgevoerd op de webview. Met behulp van data-attributen in het HTML-menu is de Bridge eenvoudig in staat JSON te genereren.

Hoe bevalt deze keuze? #

We zijn erg tevreden met de designkeuzes die we gemaakt hebben. Wanneer we native apps hadden geschreven, zouden we waarschijnlijk niet gestaan hebben waar we nu stonden. De apps voor Android en iOS hebben in korte tijd al 10.000 maandelijks actieve gebruikers gekregen met een gemiddelde van 4-sterren reviews en groeien heel vlot door. De komende periode gaan we meer native componenten toevoegen aan de mobiele apps die de interactie verbeteren en natuurlijk gaan we meer functionaliteit naar mobiel brengen!