As the team growth or the business model get more and more complex, we need to think of charting a path toward app modularization with two key goals in mind: improving the ownership and reducing the building times. With modularization, we could have numerous benefits, such as decoupled codebases, empowerment of autonomous teams, and incremental upgrades.
To tackle modularization, we decide to separate into a set of layers that a module could live in for specific purposes or rules around modules in different layers. Meanwhile, they could depend on each other.
Usually, an modularized app will contains following parts:
1. Core framework, which contains: design framework, networking framework, and persistence layer.
2. Common Layer, which shared library/models/utils across the features.
3. Feature layer, which builds on top of those core libraries, handles all the feature rendering and business logic.
4. Application layer, which contains only the app module.
The dependency rules here are allowing modules to depend on anything below them and anything in the same layer.
After establishing these guidelines, the transition to modularization should proceed smoothly. I'd like to emphasize that we can leverage Gradle scripts to create a scanning tool, which will assist us in monitoring code ownership and module dependencies throughout the transition.
Furthermore, by incorporating various generic utilities into the core framework, we can reap additional benefits. This strategic move will not only reduce the initial workload and investigation required when developing new apps but also enhance efficiency.
While our modularization journey had its share of challenges, it was a valuable learning experience that ultimately achieved our primary goals of enhancing build times and clarifying code ownership. Breaking down our features into well-defined modules significantly improved our ability to determine who was responsible for what. This, in turn, has enabled us to continually refine our issue management processes and has given teams a better grasp of the quality of the code they oversee.
While our journey is ongoing, we've made substantial progress and gained a deeper understanding of the underlying dependencies we've encountered along the way. We remain vigilant in identifying areas for improvement, such as addressing shared Android resources and network models, with the aim of further enhancing autonomy, stability, and reducing build times.
Today, let's make an app modularized, divide it into different modules, such as: data, UI, tests and dependencies.
1. Creating a Monolithic App:
2. Separating the Data Module:
3. Separating the UI Module:
Final Note:
When running the app, be certain to designate the main app as the run target.
Additional Considerations:
Summary
As we add Data Module to the main app, and we also use data module's calss in the UI module. So, we have to add the data module in the UI module.
So, the main things is taht we are already using data module in UI module as embedded framework then no need to embed the Data module in the main app.
With judicious planning, modularization can significantly elevate code organization, testing capabilities, and build efficiency, thereby fostering a more maintainable and scalable iOS app.
Pros:
1. Better for testing, we could have own unit test target and UI test target.
2. Speed up build time, only framework will be rebuilt at next compiling time.
3. Reuse framework in different projects.
Cons:
1. More complex to understand to newbie.
2. May increase development cost as one requirement might involve multiple modules changes. For example, we could manage our frameworks in different repositories. The downside of this approach is that it makes us change more repositories, if a new feature requires changes to our framework layer, such as network layer.
Find out if MentorCruise is a good fit for you – fast, free, and no pressure.
Tell us about your goals
See how mentorship compares to other options
Preview your first month