# 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)