top of page
Search

Strategic mobile app architecture

  • Writer: Marcelo Farjalla
    Marcelo Farjalla
  • May 6, 2020
  • 7 min read

Updated: May 13, 2020

An app's architecture is a critical but often overlooked factor of an apps success and longevity.



ree

Executive Summary


  • Architectural decisions are critical to success or failure of an app

  • Teams ignore architecture for various reasons

  • Download and use the CleanStack architecture for your next mobile app project and don’t let poor architecture be the reason your app fails.

— — — — — — — — — — — — — — — — —


A mobile application’s architecture is the most fundamental construct determining its success or failure. A well architected app demonstrates three essential qualities: Maintainability, Scalability, Performance.


Maintainability: How easy it is for a new developer to understand the source code in order to find and fix bugs? Good architecture exposes its code’s intentions. A good design manages complexity logically and intuitively.


Scalability: Well architected apps should cut down new feature development times by half at least. Accommodating changing requirements or swapping out dependencies should not require any major refactoring jobs.


Performance: Does the app drain the device battery? Is it sluggish and reliant on activity spinners? Performance is one of the most obvious faults a user will notice and penalize an app for. Because of this, it needs to be designed into your application from day one. Unfortunately, performance is not an activity one can attempt to improve after the fact.


Results of a bad architecture


Without a well thought-out architecture none of these desired qualities will be achieved. Nonetheless, most development teams leave architecture to happen chance. Or, let it evolve as the app grows through an endless cycle of refactors. The end result is an app that does not meet its business objectives. Users reject it for its poor performance and unreliability, protesting with a one star review and abandonment. The app’s code base is an unruly mess. Developers can’t seem to find the bugs fast enough. When they do fix a bug they cause a regression somewhere else. New feature velocity is extremely slow. Stakeholders are made to wait weeks even months for strategically important feature enhancements. Inevitably the app becomes inviable to the business and with luck a new app will be commissioned to take its place. And the cycle renews.


Why teams ignore architecture


There are many factors that lead to teams deferring or ignoring altogether any coherent remanence of architectural design.


Agility is probably the most common excuse used to ignore architecture analysis. Scrum teams get into the ‘just make it work’ or ‘you ain’t gonna need it’ mind set when swarming on their new sprint’s work items. This is a fool’s errand, though, where early productivity gains will catchup to the team later as the code base grows and feature areas become intertwined and complex.


There are also organizational reasons a codes architecture will be less than optimal. On larger projects certain modules or components may be owned by different teams. For example, the backend team designs the API’s but intra-team communication is not great so suboptimal design decisions are made rather than confront the issue. Besides time is short…we’ll make do!


Legacy is also a common factor for why application architectures get out of hand. The projects been around for a while. The original programmer understands the code perfectly and ignores that other team members are not productive due to poor design decisions made in the past. Rather than fight will just build around it. The code becomes a Winchester House of mobile applications, with features built upon features and bandaid fixes everywhere. The result is always he same — unwieldy, fragile, buggy.


Good architecture is a common goal


Fortunately, good architecture does not need to be re-invented for every project. Mobile apps share enough in common that a robust and well thought out architecture design can address many diverse use-cases in many different apps.


All apps have views or a user interface with which to interact with users. All apps have (or should have) an object model that orchestrates an app’s state. All apps work with data — either receiving it, saving it, processing it. Most apps interact with frameworks either native or third party. And most apps call out to the network.


The CleanStack solution


The CleanStack is a culmination of years of software industry experience and lessons learned. Optimized over time and drawing from many of the best resources on good design and best practices. The CleanStack is a full-stack consideration and can be used as a seed code base for any new project.


Features of the CleanStack:

  • Layered architecture

  • Domain-driven design

  • MVVM

  • Reactive

  • Offline/caching

  • Performance tuned

  • Configurable data sync

  • Testable

  • No third party frameworks


Layered Architecture


The CleanStack’s classes are grouped into loosely coupled logical layers. This allows for code isolation, adherence to single responsibility principle and ultimately makes the code easy to read, test and debug.


View Layer: The top-most layer consists of the app’s views, view models and view controller objects which are responsible for interacting with the user. The View Layer presents data to the user and takes user actions as input. The View Layer is loosely coupled to the layer below it, the Model Layer, via the Observer/Subscriber pattern. View Models subscribe to observable properties in the Model Layer and react to changes in the model by updating their views.


Model Layer: The next layer consists of the business rules for the app’s specific domain. For example, if the app is a ‘To-Do List’, we will see classes in this layer representing ‘List’ and ‘Task’ objects and all their properties and behaviors that make up those entities. Classes in the Model Layer are clean, by which is meant that they are technology or framework agnostic. There is no UIKit or CoreData code in this layer. The layer simply and purely represents the business objects and the orchestration of those objects and state when model functions are called. It should be very easy to understand exactly what the app’s functionality is simply by reading class names and their members signatures. The model makes itself available to the View Layer via observable public properties and public methods.


Data Layer: The CleanStack’s Data Layer is made up of a number of Repositories which store and retrieve data from a local data store, such as CoreData or SQLite. Repositories conform to a Repository protocol (or interface) which makes it easy to swap out the actual framework used to persist data on the client side depending on the needed use-case. The Model Layer interacts with the Repository classes so save and retrieve data via synchronous methods so that the app is super responsive and the user is never left waiting for data to be retrieved from the network. The Data Layer also includes a DataSync class whose sole responsibility is to keep the local data store synchronized with the backend database in the cloud. The DataSync can be configured at build time to sync in any time interval or simply at the beginning and end of a session.


Service Layer: In the CleanStack architecture, the Service Layer is where all the framework specific code will reside. Here you will find folders for each and every iOS framework an app will need to implement their features. For example, the CleanStack’s Service Layer will have CoreDataManager as well as a BlueToothManager for interacting with those native frameworks. The Service Layer will also provide classes for integrating with Web API’s and any external, third party services.


Network Layer: This layer is simply the app’s gateway to the network or internet. It’s the http networking layer and is fairly straightforward. It contains no business logic and its sole responsibility is to make http calls out to the network based on url and parameter inputs. The CleanStack’s network layer is devoid of any third party frameworks. All networking is performed using native iOS classes.


Domain-driven Object Model


The Model Layer of the CleanStack adheres to the principles laid out in Eric Evan’s book, “Domain-Driven Design”. The classes model real world business objects and should make sense to any business stakeholder if they were to chat with the developer about the classes of the Model Layer. The model is clean of any technical implementation or framework making use of only the Foundation iOS framework. The objects, properties, behaviors and states of the business are represented here cleanly and transparently. This makes it super easy to have real business discussions about what real world scenarios the app should enable without worry about the tech at all. Which is critical to the apps success as a business driven solution.

The Domain-driven Model Layer can therefore be modeled in any way that meets the business needs. The only thing needed for it work within the CleanStack architecture is to determine which methods are public and which properties should be observable to the View Layer. The rest is up to the business to decide.


MVVM


The CleanStack’s View Layer implements an MVVM paradigm. MVVM which stands for Model View, View, Model is an architecture that replaces the original MVC design pattern which allows for a more slim down View Controller as most of the data transform logic is relocated to the View Model class. MVVM has also gained popularity for making the view’s state testable.


Reactive


The CleanStack follows a “reactive” pattern much like the Web framework of the same name. The view ‘reacts’ to changes in the model state and updates itself. This design pattern lends itself to elegant, easy to understand architecture.


Offline Support


The CleanStack works 100% offline. Apps built on the CleanStack are fully functional while offline. A DataSync component can be added and configured to keep synchronize local data with the server as needed by the use-case.


Performance tuned


Performance must be designed for from the very beginning of the project. The CleanStack architecture has a number of features that optimize performance. The UI is driven synchronously from locally cached data, while a configurable DataSync batches and optimizes network calls to the server to keep the local cache fresh as needed. The result is a snappy and responsive user experience that never keeps the user waiting and doesn’t heat the device or drain its battery.


Configurable DataSync


A DataSync component is responsible for keeping the local cached or offline data in sync with the server when an internet connection is available. The DataSync can be configured at build time for any number of use-case — whether you need fresh polling of the server data within seconds or can simply sync at session start and end. The result is an efficient batched usage of networking operations which is key to mobile app performance.


Testable


Because the CleanStack adheres to CLEAN, MVVM, interface separation and dependency injection techniques; every class and function is highly testable. The CleanStack comes with suite of unit tests offering test coverage for all out of the box stack components. Testable code allows the developer to minimize regressions and ensure all components are passing successfully at every build.


No third party frameworks


The CleanStack does not make any use of third-party frameworks within its core architecture. This prevents issues that may arise by relying on someone else’s code within an unknown black-box. If third-party code is desired it can easily be added to the Service Layer and reside behind generic interfaces where it can be swapped out as needed modularly and not tightly coupled into the apps core code.

 
 
 

Comments


bottom of page