# Android Architecture ## Intro Project architecture based on CLEAN architecture with feature based package structure. This approach helps to retain code consistency for a large code base and provides ability for splitting up project in modules. ## Layer structure Code consists of 6 layers: - Cache - Remote - Data - Domain - Presentation - View The dependency structure is following: ![Layers structure](https://i.imgur.com/fCsuGMQ.png) For now all layers lay down in the same gradle module but there are plans to **split them between distinct gradle modules** after code migration will be finished. In code each layer represented by root package. ![Root packages](https://i.imgur.com/5YOAvWy.png =240x) ### Feature by package Layers package consists basically consists of `base` package with some base code and feature packages along with some layer specific packages. `base` package should have **the same structure** as the feature packages of this level. Feature package of current level can depend on another feature packages of this level and on feature packages of levels that current level depends on. Example: ```kotlin= class CourseInteractor @Inject constructor( CourseRepository, // course feature package LessonRepository // lesson feature package of domain level ) ``` ### Models and mappers You'll see a lot of models and mappers in this architecture but you shouldn't use all of them if you don't need to. For example if you have object like this ```kotlin= class Data( @SerializedName("name") val name: String ) ``` that came from API in the same way, can be stored to db without changes and passed to view you can declare it in domain layer and skip all mappers and models on other layers. ## Layers ### Cache Cache layer contains everything you need to work with local db storage. All packages are optional as the layer itself. So you should not create cache level for feature with no caching logic and in the same way you don't need to create mapper package or model package if data layer model can be stored without changes. ![Cache packages](https://i.imgur.com/HA6Q4hW.png =460x) #### CacheDataSource Cache data source implementation connects `cache` layer with `data` layer. Naming convention: feature name + `CacheDataSourceImpl` suffix Example: `VideoCacheDataSourceImpl` #### dao Package with dao implementations for each object. Naming convention: object name + `EntityDao` suffix Example: `VideoEntityDao` #### mapper Package with mappers to map from data layer models to cache models Naming convention: object name + `EntityMapper` suffix Example: `VideoEntityMapper`, `CourseEntityMapper` #### model Package with pojo classes that represents database entities. Naming convention: object name + `Entity` suffix Example: `VideoEntity`, `VideoUrlEntity`, `CourseEntity` #### structure Package with table schemes constants Naming convention: object name + `DbScheme` #### Dependency map ![Cache dependendecy map](https://i.imgur.com/aTZ8qug.png) ### Remote In global context remote layer serves the similar role to cache layer -- it's another data source. `remote` package has the same structure with feature base package and `base` package. ![Remote packages](https://i.imgur.com/NR1RqSI.png =460x) #### RemoteDataSource Remote data source implementation connects `remote` layer with `data` layer. Naming convention: feature name + `RemoteDataSourceImpl` suffix Example: `VideoRemoteDataSourceImpl` #### mapper Package with mappers to map from remote models to data layer models Naming convention: object name + `Mapper` suffix Example: `VideoMapper`, `CourseMapper` #### model Package with pojo classes that represents request structures and will be parsed with gson. Naming convention: object name + `Request`/`Response` suffix Example: `CourseRequest`, `EnrolmentRequest`, `CourseResponse` #### service Package with retrofit services interfaces. Naming convention: feature name + `Service` suffix Example: `EnrolmentService` #### Dependency map ![Remote dependency map](https://i.imgur.com/QLpJADb.png) ### Data Main goal of data layer is to manages data within available sources. ![Data packages](https://i.imgur.com/vccR52c.png =460x) #### mapper Package with mappers to map from data models to domain layer models Naming convention: object name + `Mapper` suffix Example: `VideoMapper`, `CourseMapper` #### model Package with pojo classes that represents data layer models. Naming convention: object name Example: `Course`, `Enrolment` #### repository Package with repositories interfaces implementations. Repository contains logic that manages data between sources. Naming convention: feature name + `RepositoryImpl` suffix Example: `CourseRepositoryImpl` #### source Package with source interfaces. Naming convention: feature name + source type + `DataSource` suffix Example: `CourseRemoteDataSource`, `CourseCacheDataSource` #### Dependency map ![Data dependency map](https://i.imgur.com/rX6JAHY.png) ### Domain Domain layer contains all business logic of application. ![Domain packages](https://i.imgur.com/cSjVXmj.png =460x) #### exception Package with bussiness logic exceptions. Those exceptions could be thrown from `domain`, `data` or sources levels and should be handled in `presentation` level. Naming convention: case name + `Exception` suffix Example: `NotAuthorizedException` #### interactor Package with bussiness logic. Interactor should unite common case logic. Interactor could be splat up in disctinct interactors that carries less logic. Naming convention: case name + `Interactor` suffix Example: `CourseInteractor`, `CourseEnrolmentInteractor`, `CourseBillingInterctor` #### mapper Package with mappers to map data from another domain packages. Naming convention: target object name + `Mapper` suffix Example: `CourseContentMapper`, `CourseInfoMapper` #### model Package with pojo classes that represents domain layer models. Naming convention: object name Example: `CourseContent`, `CourseInfo`, `EnrolmentStatus` #### repository Package with repositories interfaces. Naming convention: object name + `Repository` suffix Example: `CourseRepository` #### resolver Package with different resolvers and helpers in order to simplify interactors in some cases. Naming convention: case name + `Resolver` suffix Example: `DeadlinesResolver` #### Dependency map ![Domain dependency map](https://i.imgur.com/IjlpiH6.png) ### Presentation Presentation layer connects `view` level with `domain` level and manages view states. ![Presentation packages](https://i.imgur.com/WPcwPLs.png =460x) #### mapper Package with mappers to map data from domain or presentation layers. This can be useful to map view states. Naming convention: target object name + `Mapper` suffix Example: `CourseContentItemsMapper` #### model Package with pojo classes that represents models which is used in view states. Naming convention: object name Example: `DeadlineState` #### Presenter Presenter that manages current view state and fetches data from interactors. Naming convention: feature name + `Presenter` suffix Example: `CoursePresenter` #### View View contract. Naming convention: feature name + `View` suffix Example: `CourseView` #### Dependency map ![Presentation dependency map](https://i.imgur.com/isGSo9k.png) ### View View is the last layer in this architecture which consists of platform related implementations of displaying content. In global terms this layer characterize application. Along with view implementations it contains DI components needed to build application. ![View packages](https://i.imgur.com/fEQSDIx.png =460x) #### injection Injection package contains everything related to dependency injection as components, modules and scopes. It structured in the same way as layer package with `base` package and **feature packages**. Usually feature package consists of: - `FeautureNameDataModule` -- module that provides data layer of feature (if exists) with repository implementation - `FeatureNameModule` -- module with presenters bindings and other feauture related components - `FeatureNameRoutingModule` -- module with feature specific routers - `FeatureNameScope` -- scope of feauture if needed - `FeatureNameComponent` -- component of feauture if needed Usually there are a lot of features that have only `FeatureNameDataModule` that is included in another components. #### mapper Package with mappers to map data from domain or presentation layers to view level models. Naming convention: target object name + `Mapper` suffix Example: `CourseContentItemsMapper` #### model Package with pojo classes that represents models which is used in views, like `RecyclerView` adapter items and etc. Naming convention: object name Example: `DeadlineState` #### routing Package with routers specific to current feature, like `branch` routers or deeplink routers. Naming convention: feature name + case name + `Router` Example: `CourseDeeplinkRouter` :::info TBD ::: #### ui Package with everything related to ui like activities, fragments, adapters, delegates, views etc. #### Dependency map ![View dependency map](https://i.imgur.com/gBJhIy5.png) ## Where should I put that code? If after reading the previous paragraph you still have question: "Where should I put that code?" just keep in mind that code structure should be easy splittable by layers and by features. ![All features diagram](https://i.imgur.com/222YOpE.png) As can be seen from this diagram code base is easy splittable and each code block can be extended to distinct gradle module and be **reused** in different target or application. Dashed arrows means optional dependencies. ## All elements dependency map ![All dependencies map](https://i.imgur.com/DPUPUmR.png)