Our 4 Keystones of Mobile App Development

It’s safe to say we’ve done it all: our financial mobile development experience started from software for the now outdated BlackBerry and Pocket PC, alongside mobile web, which included time-worn WAP, and then we transitioned to iOS and Android development, settling on them for now. Here we will reflect upon these experiences which shaped our four keystones of mobile development and brought our software to the top of its game.

Examples of trading applications on PocketPC
Trading software for PocketPC

1st Keystone: Code Reuse and its Perks

Today, most mobile apps are available on multiple platforms, challenging developers and compelling them to cut the amount of codebases. The less codebases we have, the cheaper and faster it is to support the whole solution and update it with new functions. We want to reuse one general code as much as possible.

One of the most popular answers to this challenge is having one codebase and adapting it with a cross-platform UI engine. There are two common methods for accomplishing this goal.

The first one is developing a hybrid app. In this method, base material for a “native” application is a website’s mobile version, which is inserted into a platform native framework to imitate the native code. There are dozens of hybrid frameworks available, the most notable ones are PhoneGap, Ionic, Framework 7, and Mobile Angular UI.

hybrid frameworks - PhoneGap, Ionic, Framework 7, Mobile Angular UI

The second method is to use full-fledged cross-platform frameworks, such as React Native, Xamarin, and Flutter. Such frameworks are more native than those used in the first method, each of them requires a code in a specific language (JavaScript, C#, Dart, etc.) inserted into a framework that generates a real native code for supported mobile platforms.

full-fledged cross-platform frameworks - React Native, Xamarin, Flutter

Unfortunately, these methods for reusing code have several common issues specific to the technology, and we had a chance to see them for ourselves, because at some point in the past we have created our own similar framework. We don’t use it now, but it gave us a better insight into frameworks from the developer’s side.

The stumbling point when using frameworks is a drastic difference in visual and behavioral aspects of mobile platforms: design languages, navigation (e.g. back button in Android and lack of it in iOS), interaction, and animation. Applying them makes applications look unfamiliar and broken. These frameworks give us very slow, unstable and hard to support results due to required integration with a native code. A lot of large popular complex applications were written with them, but eventually they ended up developing native UIs. A great case in point is Airbnb, which advocated for React Native from 2016 till 2018. It worked fine for them but in reality a small percentage of their app was React Native, and eventually they realized that they “wound up supporting code on three platforms instead of two and were ultimately unable to meet their original goals, having a number of technical and organizational challenges” that they were unable to overcome.

Another method used in mobile development is a thin client. Here we minimize client’s logic, but in most cases UI reaction speed becomes suboptimal, because every input goes to a server, and UI reacts only after a network response. This process makes interactions very slow and unresponsive, leading to very poor user experience with an impression of a lagging application. At best, it is inconvenient, and at worst, an application could be unusable.

Scheme of server-side interactive calculations

At some point, we researched ways to reuse the code without the methods described above, because we faced the challenge of making a mobile version of one of our desktop products, and these ways could not cope with the task. That’s how we came up with the idea of code translation without reusing UI, the part responsible for the platform’s specifics. Instead, we apply translation to the code responsible for logic, taking the best from both approaches presented above. We used to apply our own in-house solution dxByte. It solved a basic task of translating Java code to be Objective-C suitable for the further use without additional adjustments. Our translator may seem to be just a kludge, but we are not the only company that came up with such a solution. Now we use, as some other companies do, Google’s solution j2Objc, which was published in 2012 and became very powerful through the years. Now it’s a tool with almost full JRE inside, 1.8 Java language level support, default methods, and stream API. The current version stands in stark contrast to its first almost unusable release. Modern code translation tools open ways to use more complex models. Who could have ever imagined that someday we would be able to translate a desktop program codebase and reuse it in a mobile application.

desktop trading platform
Initial desktop application and the result of its code reuse for mobile platforms

Lots of software developers actively seek solutions for code reuse among platforms, and there are definitely other approaches besides j2Objc and cross-platform frameworks. After Kotlin became overwhelmingly popular, especially in mobile development, its authors from JetBrains went even further by proposing a Kotlin/Native instrument, which applies modern language code to a server-side, mobile app, and web. This kind of technology is not perfect yet – it has some adverse beginnings, but there is a great chance that soon enough they will be adequately stable for a wider audience.

Considering all methods of cross-platform development, we advocate for reusing the code as much as possible via code translation and multi-platform languages, keeping in mind that all kinds of hybrid approaches do not work in the long run for high quality apps.

If you aim for a complex quality app, it is more likely that sooner or later you will have to rewrite it with a native code, as Airbnb recently concluded. To be fair, some global companies still manage their development processes with these approaches, but they are an exception rather than a rule.

In the mobile world, there is a competition defined by user requirements and needs. Mobile apps must be familiar, easy-to-use, and responsive: users prefer working with comfortable behaviour patterns and with the speed of response that matches the speed of actions, which brings us to the next keystone.

2nd Keystone: Networking in Mobile Development — We Need to Find the Right Solution

Networking is a tricky issue due to frequently slow and unreliable connections to servers. In the perfect world of mobile networking, an app sends a request to a remote service and gets a response – it is as simple as that. In the real world, an app makes several request attempts to a remote service, and often not all of these attempts are successful. So when it comes to working on interactions with a server, a majority of developers choose either the easiest and most direct solution, or some industry standard. It’s not always for the better, particularly when an application works with a stream of rapidly changing data (market data, to be precise). It is critical for an application to display data updates quickly and often. Moreover, it’s unacceptable for an application with dynamic data to display a message “Please try again” when the loading of data is interrupted, which is quite common in the mobile world.

examples of connections to servers

In our scope, these challenges are very real, and we need to be responsible for them. If we analyze a particular use case and data set, we can learn to transfer them cost-effectively or to make connectivity breaks invisible to a user. Moreover, we want to make responsible transport code for solutions of these issues, and the code of the application itself would work at the level of “send data – receive data” without manually solving each case. We haven’t considered text protocols as a transport method because we opt for speedy and frequent deliveries. So we developed our own transport framework MOBTR. It is a binary protocol that considers all known specifics of our data. We were able to optimize work with the network exactly for our special case currently used in the development of trading frontends.

MOBTR framework

Our solution doesn’t necessarily suit everybody and doesn’t have to be in demand by everybody. It’s about conducting such analysis and choosing relevant instruments.

Optimization of data traffic helps a lot in terms of slow and unstable connections. We suggest optimizing this process by transferring only delta of numbers (obtained through subtraction). Trading apps are convenient in that line. Quotes don’t drastically change, usually only one or two of their decimals do, so subtraction works perfectly for optimization, because we need to transfer smaller values.

Optimizing data transfer for mobile is not a one-fits-all approach. In case of frequent data updates, go binary. If you need more performance, go data aware, find a way to minimize the transferred values. In case of specific requirements, go custom and develop or adapt a transport framework according to them.

There are two great examples of messengers that used different approaches: Telegram and Whatsapp. Whatsapp chose a usual way for startups: it was developed to work with a standard protocol, and its performance is close to none, when the connection is weak. Telegram is faster, because it has its own binary protocol specific for its data that performs well in bad network conditions.

3d Keystone: Staying on a Bleeding Edge

Things tend to change. Devices change a lot, and they do it fast. Today mobile phones can do what computers couldn’t 10 years ago, and smartwatches can do what phones couldn’t 5 years ago. Staying on the bleeding edge with such speedy changes is hard, and some choose the wrong way to act (or fail to act at all). Here are two dud approaches, if you don’t want to keep ahead of the game.

  1. Keeping things old school. It’s easy and stable, which makes it almost impossible to go wrong, except you get no evolution at all. Development teams utilizing this method produce apps with zero response to environment and no room for growth. On top of that, they spend more time on maintenance than anyone in the industry.
  2. Being modern and using all the frameworks on GitHub! You will spend a nice long time making it all work together, managing your dependencies, and optimizing the binary size.

Before doing all that, just watch The Silver Bullet Syndrome by Hadi Hariri to make things easier. Spoiler alert: there is no silver bullet in software development, but there are approaches that will make things work in terms of staying on the bleeding edge:

  1. Don’t drag your feet. Somebody will outrun you and make it better and faster.
  2. Don’t rush. We can drown in latest trends, and it will make the code more complex, and its development will be harder. At the same time these modernization efforts don’t pay off.

What should we do? We need to find a balance. We need to track what’s going on with the technology and experiment accordingly.

We also need to introduce something modern to our solutions only when we have answers to the following questions:

  • What does it bring to this particular project?
  • What will it cost us?

A common mistake is to search for solution in an instrument. In most cases, it is not about programming language and not an item in a library (although it happens sometimes), but in the code itself, its architecture

Gradually we actualize the code by applying everything that can be useful. At the same time we move evolutionary, not revolutionary: we’re not rushing to rewrite all applications to a new language from scratch as soon as it starts getting popular.

For example, we use the latest versions of j2objc, Swift, and Kotlin in our work, where it’s relevant and doesn’t ruin everything. Meanwhile we rewrote our transport protocol MOBTR and saved all good ideas of an old version that are still relevant. Years of feedback converted our framework into a better tool, yet it stays a cross-platform mobile data transport framework, it is still aimed at mobile development, and it is still an efficient, compact, and ready-to-use solution. This is one more lesson we’ve learned through our mobile development experience: aim for evolution, not revolution. Do not rush, do not drag, most often the tool is not the problem, the code is.

User interface of a mobile financial application
Award-winning UI developed by Devexperts

4th Keystone: No F5 in Mobile Development

It’s an important feature of mobile development that is usually omitted. In web development, you can change the code, then refresh a page, and a client will get the newest version.

It doesn’t work this way with mobile applications. There is no physical possibility to remove the code of an installed application. You can forbid an application to connect to your server, but it’s beyond the borderline of developers’ decency. That’s why we need to understand that the written client code can live a long life and we must develop its best version possible.

What should we do? We should pay particular attention to client-side code and think about backward compatibility.

Down the line, our years of mobile development have shaped four keystones that optimize it to the max:

  • Reusing code as much as possible
  • Analyzing the transmitted data and finding a suitable solution
  • Avoiding going too slow and breaking the speed of light at the same time
  • There is no F5 in mobile: once written, the client-side code is here to stay

How do you deal with the code reuse challenges?
What methods of cross-platform development do you deem fit for financial software?