The principles of building modern, scalable mobile applications

Miquido
Miquido News
Published in
7 min readJun 24, 2021
Photo by Austin Distel on Unsplash

The mobile application development process, especially in the early stage of the development lifecycle, requires architects and lead developers to make (sometimes irreversible) decisions that significantly impact the future shape of your app.

How fast can new features be delivered? How much of the existing code can be reused later on? How sure are you that introducing new features won’t turn into a costly process of rewriting most of the current code, if not the whole application, again and again?

There are many real-life examples when wrong or unconscious technical decisions prevented promising mobile apps from becoming successful products. But you can avoid it, as long as you know how to correctly identify areas that need special attention and act accordingly.

Your final goal should be to allow long-term development of the mobile application with the same codebase for a reasonable price without sacrificing the scope of features and code quality.

To maximise the effectiveness of your product from the start, trust a seasoned team of professionals with your mobile app development — trust Miquido! Tell us about your idea and get a price estimate in 48 hours or less.

Modularised architecture

high-level architecture of mobile apps

High-level architecture of a mobile app should assume how new features fit into the existing codebase:

  • adding a new feature should not affect the existing ones (or that impact should be minimised),
  • features should not depend on each other (however, users can navigate from one feature to another),
  • removing obsolete features/replacing feature implementation with a new one should not affect other features,
  • adding new features shouldn’t require reimplementing core, internal, feature-agnostic parts of the application (e.g.networking, analytics, or reusable UI components).

You can achieve this by introducing high-level architecture based on independent modules, with a clearly defined hierarchy and dependencies between them. As a result, you achieve high app scalability and better feature stability.

The approach is suitable for applications with any number of features, and it doesn’t introduce any significant cognitive or technical overheads.

Data, logic, and view separation

There are several layers to each of the independent features and within them, as well as to each of the regular application screens: dedicated UI, presentation logic, business logic, data layer.

However, many people still often forget to introduce a sufficient separation between those. Even small, seemingly safe changes can unnecessarily affect unrelated parts of the feature. Besides, mixing layers often introduces hard-to-spot and fix issues, possibly affecting many layers at once.

As a result, developers have to deal with unreadable, unstructured code, with unintended complications preventing them from introducing modifications or extensions in the future.

The Clean Architecture

The clean architecture graph
Source

Modern mobile applications often follow The Clean Architecture pattern, which helps developers separate layers in the code and define sane dependencies and flow between them with higher efficiency.

By correctly implementing the Clean Architecture rules, you can build Architectural patterns like MVVM or MVP, commonly used in well-designed mobile apps.

It’s essential to choose the correct architectural pattern for the application, depending on how you want the core features to work, load their data, and handle the UI.

Also, keep in mind that said architectural patterns can evolve or even be replaced by new ones, adjusting the code for the product needs and speeding up the development process.

pt 2 of the Clean Architecture graph
Source

Handling external dependencies

Whether it’s a push notifications service, client-side analytics service, or just some library provided by an external contributor, mobile apps need to smoothly handle them, avoiding a negative impact on the regular application features.

External dependencies should be sandboxed: when integrating with libraries, developers need to pay attention to catch all the crashes caused by them and inform the analytics service whether they work correctly.

Additionally, external dependencies should be integrated in a way that allows developers to quickly replace a library with another one without changing the code used by other parts of the application. For example, when you need to replace the provider of analytic services, this should be easily done without affecting the application’s other features.

Asynchronous data loading

To prevent users from experiencing UI glitches, mobile applications need to load their data independently from the UI rendering phase. Also, in some cases, data needs to be loaded from different sources at the same time.

Technologies like Kotlin Coroutines, Combine, or ReactiveX can make asynchronous data loading easy and reliable. They are often considered complicated, but when used correctly they can significantly improve the user experience and the performance of your mobile app.

Error handling and reporting

Errors returned from backend services or validation errors should be clearly displayed to the user. Unexpected crashes, which are one of the major reasons why people quit using the app, should be caught and presented to the user in the form of an error screen or another UI element.

Both caught and unexpected uncaught errors should be sent to the crash reporting service to let developers know about the problem. Only then will the team be able to introduce a fix in one of the upcoming versions and make your app more stable.

Security

Sensitive data your application keeps in the storage of a mobile device should always be encrypted. The same is true about network communication between the app and the backend services. Modern mobile applications should meet security standards like OWASP Mobile Application Security Verification Standard.

Reusable UI components

Depending on how the UI of your mobile application is designed, you might want to consider introducing a module with UI components that can be reused across the features. Reusable UI components can be a part of a larger Design System or just a small library of frequently used elements.

In the development process, if all of the UI components are already available via the components library, implementing the view layer of the new screen comes down to joining together existing components. This is especially useful when the application consists of multiple screens using common elements, such as form elements like inputs or dropdowns.

Modern programming languages

Modern mobile app development requires modern programming languages. Some of the language features can make the application more stable. For example, thanks to nullability being a part of the type system, Android apps built with Kotlin are 20% less likely to crash.

Programming languages like Kotlin, Swift, or Dart, with features like type safety, variable immutability, or functional programming style, can help developers manage code structures better, speed up the development process and avoid returning hard-to-spot bugs.

Code quality

When your project grows over time you’ll want to introduce new features at a fast pace. it will most probably prove hard to keep your code style and quality consistent.

A properly configured static code analysis can find out various problems (e.g. style inconsistencies, unused resources, misused APIs, etc.) before they are merged to the shared codebase, relieving the developers of the responsibility of finding them in a manual way in a code review process.

Test automation

Testing pyramid

Unit tests are the fundamental tool for checking the correctness of the isolated parts of the code. There are two types: integration and end-2-end.

Integration tests can check larger parts of the projects, such as mobile application variants with mocked backend services.

End-2-end tests check the whole application system.

Implementing a complete testing pyramid for the project allows for reducing manual testing (which cannot be easily scaled) by up to 90%! With this approach, only test cases that cannot be automated are tested manually.

Test builds for manual testing

Testing a new version of the application before releasing it to the market can sometimes be complicated, mostly due to organising test data and trying to recreate user journeys. Builds dedicated to manual testing should have the possibility to communicate with test backend environments. Also, you should be able to set up a proxy in communication between the application and the backend to alter the communication for testing purposes easily.

Continuous integration and continuous delivery

Continuous integration (CI) aims to automate the process of safely integrating the code changes authored by developers into a single, shared codebase. For mobile applications, continuous integration solution is responsible for running static code analysis and unit/integration/end-2-end tests.

The continuous delivery (CD) part of the process automates releasing the test version of the mobile application to the testers and the release version to the app store.

CI/CD processes for mobile apps must be fast, reliable, and stable.

Frequent, safe releases. Remote configuration, analytics & A/B testing

To prevent releasing a broken version of your product to the app store, staged rollout can be used. This is the process of releasing the new version to the specified percentage of users and increasing the number over time.

A remote configuration mechanism should be used to dynamically control the application’s behaviour when published to production. For example, a feature toggle mechanism can be implemented using a remote configuration solution.

Remote configuration and analytics functionalities can be combined into an A/B testing solution.

Summary

As you can see, there are lots of hidden elements to creating modern, scalable mobile applications. You need to keep in mind user behaviour and expectations, as well as numerous technical specifications that can affect your app in the long run.

In order to avoid having to deal with troublesome code and costly errors, our advice is to start developing your product with a team of professionals from the very beginning. You can choose whether you want to proceed with your mobile application in-house or if you are ready to trust a brand new team and outsource it to a third-party vendor.

Check how Miquido can help you on your way towards building modern, scalable and business-oriented mobile products.

--

--

Miquido
Miquido News

We are Miquido — a 360° software house with 12+ years of experience in web & mobile development, AI & product design.