Demystifying the mobile app dragons

When mobile development is a teach/learn experience for the whole team

Fabrizio Moscon
AnyJunk
6 min readMar 8, 2018

--

Context

A few months ago I was asked to help AnyJunk rewrite their current mobile app for partners using React-Native. The key reasons for this were to a) add new features and b) bring the mobile development knowledge in house through a tight team collaboration. Based on my past experience with these kind of apps at Bizzby (an on demand services app) and my exposure to React-Native at Hoxfon I felt I could deliver on the company’s expectations.

AnyJunk is a very small but innovative award winning logistics company, with a great development team who share the same culture and values. Some pillars of the culture are the mutual respect for each other’s ideas and expertise, a healthy practice of code review and pair programming and the same passion for code quality and testing.

The server applications are written in Scala and embrace principles of pure functional programming, leveraging the language’s strong types to enforce the correctness of the business domain logic. These principles strongly influenced the way in which the React web app is written. In fact the web app makes extensive use of monet, a standard library for functional programming in JavaScript that brings monads such as Maybe, Validation, and Either to React. The Javascript codebase is also using flow to infer data types and code correctness.

When planning the rewrite of their service partners’ mobile app, a clear objective was to deliver the best mobile user experience. Another important goal on the agenda was to not compromise the team values, philosophy and development practices. AnyJunk wanted to allow both Scala and React developers to review the mobile app’s code, develop in an iterative way coexisting with the weekly sprints and enable automated testing and continuous releases.

The React-Native mobile app

After comparing a few options of mobile technologies, AnyJunk opted for React-Native. The fact that the team was already familiar with React played an important role in this choice. Meanwhile more companies were sharing their positive experience with React-Native and this convinced both technical and non-technical stakeholders to use it.

The app uses redux to store the global app state and it can also be used offline thanks to redux-offline which under the hood implements a clever retry with decay strategy mechanism for offline actions that are stored on the device disk with AsyncStorage wrapped by redux-persist. Side effects such as HTTP requests/responses are integrated in redux using redux-thunk and promises. The codebase quality currently meets the highest standards. It uses eslint to detect mistakes and nuisances, it is typed with flow and tested extensively with jest. These tools work well together and represent the standard tooling configuration found in many React and React-Native projects. In particular flow has proven itself very useful in two ways. Firstly, we ensured that each component was used with the correct props and state types. This saved us time in development and code review. Extra simulator reloads were avoided and most importantly it has ensured that the end result app was free of types bugs and typos. Secondly, it has helped create close interaction between Scala and JavaScript developers where common ground was found over the nature of strong types within technical discussions.

Below is a screen shot taken from the final app version showing a service partner job details.

AnyJunk app screenshot

Functional programming in JavaScript

Before this collaboration I only used functional programming at university with OCaml and whilst conducting a few personal experiments with ReasonML, but I had no previous commercial exposure. At AnyJunk I have been exposed to more advanced concepts and I was taught how to code and design the internal API in a functional way using the folktale library.

The Maybe is the first functional construct that I used in the app. Maybes are returned from a helper function called safeGet and provide a clean and reusable way to check the existence of Object properties and exposed me to another important functional concept: the distinction between nullable and non-nullable data.

To fully understand what are the pros of using Maybe and why they solve a very common problem found in React applications I suggest to check out Dan Hood’s article that explains in detail how Maybe can be used with redux and improve your code correctness. The following code snippets compare imperative and functional approaches to display a validated collection volume which represent the size in yards of a junk collection. I want the reader to appreciate that even though the imperative way has less lines of code it leaks basic validations into the main program forcing code repetition (lines 15–21).

Encapsulating the validation into a function allows for code to be reused easily and makes the app more resilient to future developers’ mistakes. Note how validateCollectionVolume() returns a Result that can be used for presentation purposes inside the render() function of a Component and for business logic.

The Model layer

Another part of the React-Native app where I was able to learn and apply concepts of functional programming was the data bridging between the redux state and the React Component through the use of models. The app uses models to separate data validations from the presentation layer. The models are JavaScript Objects that use Maybes and Results to separate data validation from the React Components and allow the same validation to be used in both Components and thunks. The below example reuses the validateCollectionVolume() function to demonstrate what the purpose of the model is.

After I introduced this pattern in the mobile app the rest of the team and I had few brainstorming sessions to understand why this pattern was useful in the current app structure and how it could be ported and even improved in the web app codebase. Eventually this constructive sessions helped implementing an improved and novel version of this pattern that uses data marshalling to process data between the server and the client. This is an example of cross-pollination of ideas between projects, initiated by peer code review that allowed to improve a shared code pattern through team collaboration. Redux and functional concepts established a common ground for the collaboration that helped to find this new useful pattern. This wouldn’t have happened using a completely different technology for the development of the mobile app.

Another example of team collaboration is what brought Dan and I to make a few open source contributions to redux-offline and to create redux-offline-immutable-config, a small JavaScript library written with functional programming concepts in mind that allows the use of immutable.js with redux-offline.

We did this by extracting the methods for reading and writing to the state into a lens that could be passed in as part of the configuration, as well as extracting some dependencies. This way the redux-offline library doesn’t depend on things that it only needs when an assumption is made about the type of state it’s being used with. The redux-offline-immutable-config library is then a collection of the parameters and dependencies required to use redux-offline with an immutable state specifically, while the config included within redux-offline itself is an equivalent one for a non-immutable state.

Conclusions

The first phase of the project is now completed and the service partner’s app is used by all AnyJunk’s service partners every day. Almost a 100% of the code is shared between Android and iOS and thanks to the tight collaboration and code review carried on during these past months, the in-house AnyJunk team is completely confident in extending and maintaining the React-Native code base. During these time I have learnt a lot of new and useful concepts that I will certainly bring to my next projects.

One of the main benefits of using React-Native at AnyJunk was giving all developers complete visibility of the code and the pattern used. This is a clear improvement over developing Android and iOS apps in isolation, where it is is really hard to communicate and share because of the different languages and paradigms.

--

--