5 min read
In this Article:
- What is a monolith
- µFeatures architecture by Tuist.io
- Microservices != silver bullet
- Other ways to split mobile apps
Writen by: By Bartłomiej Pichalski- Mobile Lead at KYOTU Technology
What is a monolith?
At the beginning of the article, I asked what a monolith is, well, there are many different definitions, but I will try to explain it with an example. Let’s imagine that we are creating an application for a client who would expect from us some functionality related to video streaming, as we have streamed it would probably also be useful to have some kind of logging.
Probably in front of your eyes, you can see such a scheme:
We have one target that contains our authentication and streaming functionality. Our application connects to 2 back-end solutions. For example, AWS and some libraries that allow video streaming. It is worth mentioning that monolith architecture is not an anti-pattern. For small applications like the one above it would be perfect. However, successful applications tend to grow. In the beginning, you probably work on this application by yourself:
Later the client comes and says, our app was a great success! Let’s add some e-commerce to it to monetize it.
And so the customer hires a new developer to develop the product faster.
The store has been a great success, we now need to add social media integrations, we need to add integrations for a new module with tutorials, we need to add… ~Customer
More meetings pass, and you go from a small application to a larger one:
From a single developer, all of a sudden entire teams are formed:
Eventually, you get to a point where further code development and application testing is very slow and painful = Monolith Hell.
The technology stack will become more and more complicated and obsolete, but as you know rewriting the whole thing is not an option. Okay, beautiful story, but what are the real problems with the monolith pattern? – The complexity of the code (and in fact the difficulty to keep it clean) – Compilation time – Changing anything can have big consequences – …
Okay, but do we, as mobile developers have any other option? Our IDEs are not designed to work with many applications that would connect in a nice way?
Microservices in mobile applications
There are many different ways how you can logically split your application into smaller parts, because of my specialization in iOS I will mainly talk about solutions when writing Apple applications. The main solution that completes this article is µFeatures architecture designed by the team at Tuist.io, there is nothing amazing about it but in this chapter, I will focus on telling you what it is. In later chapters, I will also mention other ways of splitting the application into smaller ones. So what do µFeatures offer? First of all scalability, thanks to the fact that each developer works in a separate microframework we can easily add/subtract new ones.
Here is an example from life, in one of the projects, we had to work at the same time on two applications that ultimately were to become one. (Part released earlier, the rest as an update). Due to the fact that we had a large team in the first one, there was no work for everyone so some of the team immediately started writing features that were in the second part. Thanks to µFeatures we could write using the same common code (e.g. same views, styles, etc) without creating two projects and in the end, we could choose only those micro-features which we want to build in our application.
The architecture has been planned so that each module has the necessary things to build it in isolation.
- Example – Start-point of our application, no matter how big code base we have and how many screens are in front of our target we can run it without running others.
- Tests – This probably doesn’t need to be explained
- Feature – Source code of our framework
- Testing– All mockups of our data (e.g. json from backend contract). Thanks to this we can run Example in isolation. (Not compiled while building the whole thing)
- Interface – All our inputs and outputs that our framework has.
Building in isolation is also connected with speeding up the time of building, we don’t have to build every time the whole application, which, when they are big monoliths, can take even a few minutes and we build only one isolated feature e.g. settings screen.
Flexibility in the product direction/ building like from blocks. Due to the fact that our modules are only small pieces of code, we can choose what composition our application will have. E.g. customer version, employer version, etc which all use the same code.
Encourages the reuse of code in applications and other products, such as extensions, using platforms or libraries. By creating µFeatures, reusing them is quite easy. We can build an iMessage extension, a Today extension, or a watchOS app simply by combining existing µFeatures and adding platform-specific UI layers (if needed).
Divide and conquer. Working in small modules allows for more focus and testing and trying out the feature in isolation. Furthermore, development cycles are much faster because we have a more selective compilation, compiling only those components that are necessary for our feature to work. Compiling the entire application is only necessary at the very end of our work when we need to integrate the function into the application.
When all the source code of an application is in the same destination, it is very easy to build implicit dependencies in the code and end up with that familiar spaghetti code. Everything is tightly coupled, code can be unpredictable, and making new changes becomes a nightmare. When we define functions in independent frameworks, we design public APIs within our function implementation. We have to decide what should be public, how our function should be consumed, and what should remain private. We have more control over how we want our function clients to use the function, and we can enforce best practices by designing secure APIs.
Micro-services != silver bullet
Like any solution, microservices are not for everything, where they can be useful for large applications so there is no point in putting them everywhere you can. They have their drawbacks, for example, when using µFeatures architecture, there are many conflicts with targets in Xcode (that’s why it is recommended to completely throw away the xcode project and generate it from scratch every time, but about that in another article). Another problem is to change the mindset of a person used to how monoliths are written or whether it is good to have good documentation of particular frameworks (with large projects there are really many of them).
Other ways to break down mobile apps
As I mentioned earlier in this post I will also present other ways to split mobile applications (iOS). Apart from micro modules where we go to extremes with the number of frameworks (each screen/dependency separately) we can divide our application into much larger frameworks that will contain the entire logic of the application such as one team is involved in creating the newsfeed with all its dependencies and another in creating a store. You can use this purpose-built-in Xcode XCFrameworks.
Yes, these are the same frameworks as in µFeatures but here we would create them ourselves because we don’t need to do too many of them. An equally good option if we want to split our repository into feature-specific ones is to use Swift Package Manager frameworks or Cocapods Frameworks. Currently, preferred rather SPM because of the adoption of this technology in Xcode itself directly, a great explanation of this team from Point-free which I wholeheartedly recommend if you want to explore more knowledge on the subject.
If you want to learn how to realistically split or start creating applications with Micro – frameworks, then the second part of the article is for you! I’ll be going in-depth there with step-by-step examples of how to start writing modular code.