# Modularization learning journey In this learning journey you will learn about the modularization strategy used to create modules in the Now in Android app. For the theory behind modularization, check out [the official guidance](https://developer.android.com/topic/modularization). **IMPORTANT:** Every module has a dependency graph in its README ([example for the app module](https://github.com/android/nowinandroid/tree/main/app)) which can be useful for understanding the overall structure of the project. ## Module types ```mermaid graph TB subgraph :core direction TB :core:data[data]:::android-library :core:database[database]:::android-library :core:model[model]:::jvm-library :core:network[network]:::android-library :core:ui[ui]:::android-library end subgraph :feature direction TB :feature:topic[topic]:::android-feature :feature:foryou[foryou]:::android-feature :feature:interests[interests]:::android-feature :feature:foo[...]:::android-feature end :app[app]:::android-application :app -.-> :feature:foryou :app -.-> :feature:interests :app -.-> :feature:topic :core:data ---> :core:database :core:data ---> :core:network :core:database ---> :core:model :core:network ---> :core:model :core:ui ---> :core:model :feature:topic -.-> :core:data :feature:topic -.-> :core:ui classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; ```
đź“‹ Graph legend ```mermaid graph TB application:::android-application -. implementation .-> feature:::android-feature library:::android-library -- api --> jvm:::jvm-library classDef android-application fill:#CAFFBF,stroke:#000,stroke-width:2px,color:#000; classDef android-feature fill:#FFD6A5,stroke:#000,stroke-width:2px,color:#000; classDef android-library fill:#9BF6FF,stroke:#000,stroke-width:2px,color:#000; classDef jvm-library fill:#BDB2FF,stroke:#000,stroke-width:2px,color:#000; ```
**Top tip**: A module graph (shown above) can be useful during modularization planning for visualizing dependencies between modules. The Now in Android app contains the following types of modules: ### The `app` module This contains app level and scaffolding classes that bind the rest of the codebase, such as `MainActivity`, `NiaApp` and app-level controlled navigation. A good example of this is the navigation setup through `NiaNavHost` and the bottom navigation bar setup through `TopLevelDestination`. The `app` module depends on all `feature` modules and required `core` modules. ### Feature modules These are feature-specific modules that handle a single responsibility in the app. For example, the `ForYou` feature handles all content and UI state for the "ForYou" screen. Feature modules aren't Gradle modules themselves, they are split into two submodules: * `api` - contains navigation keys * `impl` - contains everything else This approach allows features to navigate to other features by using the target feature's navigation keys. A feature's `api` and `impl` modules can be used by any app, including test or other flavoured apps. If a class is needed only by one feature module, it should remain within that module. If not, it should be placed into an appropriate `core` module. A feature's `api` module should not depend on another feature's `api` or `impl` module. A feature's `impl` should only depend on another feature's `api` module. Both submodules should only depend on the `core` modules that they require. ### Core modules These are common library modules containing auxiliary code and specific dependencies that need to be shared between other modules in the app. These modules can depend on other core modules, but they shouldn’t depend on feature nor app modules. ### Miscellaneous modules For example, `sync`, `benchmark` and `test` modules, as well as `app-nia-catalog` - a catalog app for displaying our design system quickly. ## Examples
Name Responsibilities Key classes and good examples
app Brings everything together required for the app to function correctly. This includes UI scaffolding and navigation. NiaApp, MainActivity
App-level controlled navigation via NiaNavHost, NiaAppState, TopLevelDestination
feature:1:api,
feature:2:api
...
Navigation keys and functions that other features can use to navigate to this feature.

For example: The :topic:api module exposes a Navigator.navigateToTopic function that the :interests:impl module uses to navigate from the InterestsScreen to the TopicScreen when a topic is clicked.
TopicNavKey
feature:1:impl,
feature:2:impl
...
Functionality associated with a specific feature or user journey. Typically contains UI components and ViewModels which read data from other modules.
Examples include:
  • feature:topic:impl displays information about a topic on the TopicScreen.
  • feature:foryou:impl which displays the user's news feed, and onboarding during first run, on the For You screen.
TopicScreen
TopicViewModel
core:data Fetching app data from multiple sources, shared by different features. TopicsRepository
core:designsystem Design system which includes Core UI components (many of which are customized Material 3 components), app theme and icons. The design system can be viewed by running the app-nia-catalog run configuration. NiaIcons NiaButton NiaTheme
core:ui Composite UI components and resources used by feature modules, such as the news feed. Unlike the designsystem module, it is dependent on the data layer since it renders models, like news resources. NewsFeed NewsResourceCardExpanded
core:common Common classes shared between modules. NiaDispatchers
Result
core:network Making network requests and handling responses from a remote data source. RetrofitNiaNetworkApi
core:testing Testing dependencies, repositories and util classes. NiaTestRunner
TestDispatcherRule
core:datastore Storing persistent data using DataStore. NiaPreferences
UserPreferencesSerializer
core:database Local database storage using Room. NiaDatabase
DatabaseMigrations
Dao classes
core:model Model classes used throughout the app. Topic
Episode
NewsResource
## Dependency graphs Each module has its own `README.md` file containing a module graph (e.g. [`:app` module graph](../app/README.md#module-dependency-graph)). When modules dependencies change, module graphs are automatically updated by the [Build.yaml](../.github/workflows/Build.yaml) workflow. You can also manually update the graphs by running the `graphUpdate` task. ## Further considerations Our modularization approach was defined taking into account the “Now in Android” project roadmap, upcoming work and new features. Additionally, our aim this time around was to find the right balance between overmodularizing a relatively small app and using this opportunity to showcase a modularization pattern fit for a much larger codebase, closer to real world apps in production environments. This approach was discussed with the Android community, and evolved taking their feedback into account. With modularization however, there isn’t one right answer that makes all others wrong. Ultimately, there are many ways and approaches to modularizing an app and rarely does one approach fit all purposes, codebases and team preferences. This is why planning beforehand and taking into account all goals, problems you’re trying to solve, future work and predicting potential stepping stones are all crucial steps for defining the best fit structure under your own, unique circumstances. Developers can benefit from a brainstorming session to draw out a graph of modules and dependencies to visualize and plan this better. Our approach is such an example - we don’t expect it to be an unchangeable structure applicable to all cases, and in fact, it could evolve and change in the future. It’s a general guideline we found to be the best fit for our project and offer it as one example you can further modify, expand and build on top of. One way of doing this would be to increase the granularity of the codebase even more. Granularity is the extent to which your codebase is composed of modules. If your data layer is small, it’s fine to keep it in a single module. But once the number of repositories and data sources starts to grow, it might be worth considering splitting them into separate modules. We are also always open to your constructive feedback - learning from the community and exchanging ideas is one of the key elements to improving our guidance.