1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
# AdvancedPrivacy Development Guide
This guide contains development related information to help a developer in getting better understanding of project structure.
## Architecture
The architecture of AdvancedPrivacy is based on [clean architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html). For presentation layer, we use [Model-View-Intent](http://hannesdorfmann.com/android/model-view-intent/) design pattern which is a unidirectional reactive flow pattern. We use it in conjunction to ViewModel to make our features lifecycle aware. Our android app is having single activity multiple fragments.
### Clean Architecture
Clean architecture is the building block of AdvancedPrivacy. This architecture is based on the following principles:
1. **Independent of Frameworks**. The architecture does not depend on the existence of some library of feature laden software. This allows you to use such frameworks as tools, rather than having to cram your system into their limited constraints.
2. **Testable**. The business rules can be tested without the UI, Database, Web Server, or any other external element.
3. **Independent of UI**. The UI can change easily, without changing the rest of the system. A Web UI could be replaced with a console UI, for example, without changing the business rules.
4. **Independent of Database**. You can swap out Oracle or SQL Server, for Mongo, BigTable, CouchDB, or something else. Your business rules are not bound to the database.
5. **Independent of any external agency**. In fact your business rules simply don’t know anything at all about the outside world.
<img src="art/CleanArchitecture.jpg" width="580" height="425">
### Model-View-Intent
<img src="art/AbstractMVI.png" width="500" height="333">
MVI is used at the presentation layer of clean architecture. It is very much similar to [Redux](https://redux.js.org/) in terms of implementation and working. It has three main components.
- **View**: This is where activities, fragments and other android components live. It is responsible for publishing user intent/actions to the model and rendering the state returned by the model. In AdvancedPrivacy, it is just an interface which is implemented by android components.
- **Intent**: In context of our app, we call them actions. These are simple data classes having any extra payload like inputs, ids etc.
- **Model (data layer at presentation level)**: This is responsible for processing the actions, communicating with domain use-cases and mutating the state of the model. It acts as a Store from redux but for our use case, we call it a **Feature**.
#### Flow-MVI in Privacy Central App
In this app, we have implemented MVI using [Kotlin Flow](https://kotlinlang.org/docs/flow.html).
<img src="art/MVI-Feature.png" width="336" height="332">
Elements of a feature:
1. **Action**: The exhaustive list of user actions for a feature.
2. **State**: Simple POJO (kotlin data class) representing various UI states of the application.
3. **SingleEventProducer**: This is a function which is invoked by the reducer to publish single events (that can/should only be consumed once like displaying toast, snackbar message or sending an analytics event). This function takes action, effect, current state as input and it returns a `SingleEvent`. By default this function is null for any Feature.
### Architecture Overview of AdvancedPrivacy App
![](art/privacycentral-arch.png)
Looking at the diagram from right to left:
1. **Database, Preferences and API Helpers**: These are a set of classes with very specific responsibilities for each of them. They can perform some business logic, communicate with the database or make a call to third party API. These classes are implementation of abstract gateways and interfaces (see below).
2. **Abstract Gateways and Interfaces**: An abstraction layer that sits between repositories and framework implementations. The objective of this layer is to keep repositories independent from framework (like databases).
3. **Respositoy Implementation**: These classes provide the implementation of abstract repository defined in the domain.
4. **Repository**: They are the core part of our domain. Each repository is a just an interface whose implementation is provided by the data layer.
5. **Usecase/Interactors/Observers**: The act as the bridge between the presentation layer and data layer.
6. **Entities**: These are business objects for the application. They encapsulate the most general and high-level rules. They are the least likely to change when something external changes.
7. **Features**: MVI specific model (discussed above).
8. **ViewModel**: arch-component lifecycle aware viewmodel.
9. **Views**: Android high level components like activities, fragments, etc.
## Code Quality and Style
This project integrates a combination of unit tests, functional test and code styling tools.
To run **unit** tests on your machine:
```
./gradlew test
```
To run code style check and formatting tool:
```
./gradlew spotlessCheck
./gradlew spotlessApply
```
## State-of-The-Art
The project currently doesn't have exactly the same mentioned structure as it is just a POC and will be improved.
### Todo/Improvements
- [ ] Add unit tests and code coverage.
- [ ] Implement Hilt DI.
# References
1. [Kotlin Flow](https://kotlinlang.org/docs/flow.html)
2. [MVI](https://hannesdorfmann.com/android/mosby3-mvi-1/)
4. [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)
|