One of the issues we face developing our mobile app for both Android and iOS is a significant amount of code duplication between the two platforms. They provide the same functionality, they talk to the same server, and they store the same information, but that’s where the similarity ends. The implementations don’t just differ by being written in different languages (Java vs. Objective-C); for historical reasons, they also have remarkably different architectures and store information in different ways.

As a result of these differences below the surface, we occasionally see inconsistent behaviour between the two apps. Bad data from the server might go unnoticed on one platform where it’s handled gracefully, while it could crash the other, or even lead to subtle data corruption. To accomplish the same task, the two apps might call different sets of APIs or pass them different parameters. Bugs in general are also a major problem: We’re implementing the same functionality twice, which means we’re doubling the odds of bugs and writing the same unit tests twice (at best!).

Djinni in a Bottle

Last year at CppCon 2014, Dropbox announced they were open-sourcing Djinni, a tool they developed internally to generate the code necessary to support cross-platform development between Android and iOS.

At the core of Djinni is an interface definition language (IDL) for declaring data structures and interfaces in a platform-neutral way. From this, the Djinni tool generates Java, Objective-C, and C++ classes to represent the types you’ve declared in each of those languages. It also generates Java Native Interface (JNI) code to bridge calls between Java and C++ as well as Objective-C++ classes that simplify calls between Objective-C and C++.

The intent with Djinni is that you write your user interface code in your platform’s native language and write the rest in a common C++ code base. While my C++ might be a bit rusty, it seemed worthwhile diving into Djinni and giving it a shot. In an afternoon, I was able to put together a proof of concept fetching stories from Wattpad and displaying them in very small iOS and Android apps. The biggest learning curve as an iOS developer was adapting some of the documentation to Android Studio 1.0, which had not been released at the time Dropbox announced Djinni.

Word to the wise: Djinni includes an “optional” type which you will inevitably find yourself using. The command line options allow you to specify the implementation to use in C++. Since C++11 and C++14 didn’t include a std::optional , it’s a good idea to install Boost and use boost::optional . On OS X, you can use HomeBrew to install it. Since Boost’s optional is a header-only class, you don’t need to link any libraries into your project or worry about pre-compiled binaries for different CPU architectures.

Asynchronous Error Handling with “Either”

Getting beyond the basics, I needed to think about how we would handle errors originating in C++ code being run on potentially multiple background threads and pass them to the user interface layer in a sensible manner. While Djinni translates exceptions across language boundaries, exceptions are really only intended for exceptional situations (usually programmer errors), not expected runtime errors, and exceptions aren’t automatically carried between threads; if an exception thrown in a thread isn’t caught in that thread, it will terminate the thread (and usually the app with it). We needed a better solution for communicating expected errors and it offered a chance to rethink the way we already perform error handling.

One of the considerations in implementing error handling is that we often perform operations composed of smaller operations, and the failure of an individual operation doesn’t necessarily imply a failure of the composite operation. A trivial but realistic example is fetching profile information for a set of usernames: If the server doesn’t recognize some of those usernames, the overall operation can still succeed and return mostly valid results, but we need a way to signal that some of the results are invalid. Enter the Either data type.

The Either is a data type we borrowed from functional programming. An Either is similar to an ordered pair, with a notable distinction: Whereas an ordered pair has a first and a second value (which can be of different types), an Either has either a left and a right value (which typically are of different types). By convention, the left value often represents an error while the right value represents a “good” value.

Unfortunately, while Djinni provides some parameterized types (set, list, map), it doesn’t let us define our own, so there wasn’t an obvious way to declare arbitrary types of the form either<A, B>. Fortunately though, Djinni is open source, so I did the obvious, learned just enough Scala to shoot myself in the foot, forked the repository on GitHub, and implemented it.

Using Either, the return type for a call to fetch usernames is either<error, list<either<error, user>>> , and it can be visualized like so:

An error on the outer Either would typically indicate a problem contacting the server or an invalid request, while an error on the inner Either would indicate a problem looking up a specific user.

While it’s still a work in progress, you can find a complete example of Android and iOS projects at https://github.com/Wattpad/Either. The requirements are listed there.

Next Steps

Djinni seems to be a good solution for new apps, but we’re looking to apply this to an existing app. The next step for us will be implementing wrappers for some of our simpler APIs to stress test it and look for performance issues, which we can talk about in another blog post. Feel free to use the Either project as a template for your own projects and let us know if it’s helpful!

— Tony