An iOS app architecture (Part I)

An iOS app architecture

The aim of this post (and the followed ones) is to expose an iOS app architecture that I have been using for developing iOS apps during last two years. In the end is not strictly one of the known ones: VIPER, MVVM, MVP…, but obviously with many commons concepts.

What is an architecture?

From wikipedia: Software architecture refers to the high level structures of a software system, the discipline of creating such structures, and the documentation of these structures. These structures are needed to reason about the software system. Each structure comprises software elements, relations among them, and properties of both elements and relations.[1] The architecture of a software system is a metaphor, analogous to the architecture of a building.[2]

In practice a software architecture allow to absorb the product owner requirements without increasing your app source code complexity. If does not, start to refactor before is too late.

Outlining the architecture

As a professional painter we have to outline the available canvas and decide which functionaly will be implemented in each part.

Once done, now is crystal-clear which part will be occupied by fingers, palm and wrist.

Moving to software engineering, I am talking about 3-tier architecture model, this model has been used for in other technologies (e.g web, client-server). It splits the app in 3 layers (View, Domain, Data), its philosophy is very clear:

  • Each layer has a very concrete purpose
  • Each layer has a defined interface for requesting its implemented services.
  • A layer can only interact with its adjacent one.

Rule number I. Visualize mentally that each component (and its subcomponents) from your architecture as an apartment in a building. A component can only interact with its immediate upper and lower components floor. If you want to go from 4th floor to 2nd one, you have go through 3rd.

For instance if we want to present ddbb query result in a view:

🚫 🙅 Forbidden. Access directly from a view to a database handler to make a request. Comming in to iOS context, figure out that you get the realm ddbb handler and implements the query from the ViewController that will present the results.

✅The approach. Define one interface method in the Data and Domains layer that returns the requested data (e.g. in form of array) to the view, so View layer unique responsibility is draw the data returned by domain layer.

With this simplistic example, Domain layer does nothing apart from calling Data layer, you would think that this layer is redundant, but truly believe me it is not. If some data processing has to be done, Domain layer is the place.

From this rule you will get the following benefits:

  • Use TDD for validating Domain and Data layers with unit tests
  • Reduce the number of code-lines in the view (Massive ViewControllers problem).

Rule II. No-shared responsibility. Every component has a concrete responsibility and no other component can perform it, but the designated one.

For instance in our app we have different screens and each one is presented information retrieved from a rest service.

🚫 🙅 Forbidden. Implement in every view the service call for retrieve the data to present.

✅The approach. Place all the service calls in a component, as this component is retrieving data, it will be placed in the Data layer. So the view will request to domain the rest data, and domain will request to data layer, finally the data will be returned to view via domain.

From this rule you will get the following benefits:

  • Use TDD for validating a component with a concrete responsibility.
  • In case that some component fails (e.g rest api’s), we have to review a file, not bunch of scattered code in all project.
  • Reduce the number of code-lines in the view (Massive ViewControllers problem).

The architecture

As you can see in the architecture block schema, there are from 5 up 7 seven levels, so is essential that each component only interacts with its upper and lower components.

iOS app architecture

The exception that confirms the rule

There is one case that Rule II will be overridden, and is the case when two (or more view are presenting some information) and this information is updated/deleted from Data Layer. In this case the presenters get subscribed to data events broadcasted by Data Manager, and when presenter gets the notification then fetchs for the latest data to present.

iOS app architecture

Implementation

iOS app architecture

Basically the implementation is an almost empty project, with the basic folder organisation for holding different layers ant its components that matches with architecture presented:

We have added a very basic app start up sequence, is very important to keep this part of code under a tight control, leave only necessary code in AppDelegate.swift:

InitAppSequencer is the responsible for the start up sequence, this class dispatches the different operations needed during start up app sequence.

Up to this moment the unique task (operation) that app must do is just present the main screen.

If you want to know more about sequencers you can find in my pot post Design iOS app start up sequence (with Operations)

Pods

The pods that highly recommend and will improve dramatically the quality of your code are:

  • R.Swfit. Get strong typed, autocompleted resources like images, fonts and segues in Swift projects
  • Swiftlint. A tool to enforce Swift style and conventions

You can download the code used in this post from here.

Conclusion

In this post has been presented the layered structured of this architecture and the rules that governs the communication between each component.

What’s Next

In the next posts will be presented in detail: View, Domain and Data layer.

References