The document summarizes the refactoring of Wunderlist's Android architecture to improve separation of responsibilities and testability. It describes moving from a single-layer architecture to a multi-layer MVP architecture with separate presentation, model, and UI domain layers. Key changes included introducing use cases to encapsulate business logic, fetching data asynchronously using callbacks or an event bus rather than loaders, and decoupling layers through dependency rules. The goal was to make responsibilities clearer, dependencies looser, and testing easier.
2. Who is this guy?
Image Placeholder
César Valiente
Android Engineer @Wunderlist (@Microsoft)
Android Google Developer Expert (GDE)
+CesarValiente @CesarValiente
9. How is Wunderlist built?
Android
Layer
Presentation layer
(UI and Android stuff)
Android project
10. How is Wunderlist built?
Android
Layer
Presentation layer
(UI and Android stuff)
Android project
Sync
Layer
Model layer
(Business logic)
Java project
11. How is Wunderlist built?
Android
Layer
Presentation layer
(UI and Android stuff)
Android project
Sync
Layer
Model layer
(Business logic)
Java project
Network
Layer
Network layer
(Accessing to the API data)
Java project
12. How is Wunderlist built?
Android
Layer
Presentation layer
(UI and Android stuff)
Android project
Sync
Layer
Model layer
(Business logic)
Java project
Network
Layer
Network layer
(Accessing to the API data)
Java project
Sync boundaries
13. How is Wunderlist built?
Android
Layer
Presentation layer
(UI and Android stuff)
Android project
Sync
Layer
Model layer
(Business logic)
Java project
Network
Layer
Network layer
(Accessing to the API data)
Java project
Sync boundaries Network boundaries
23. Problems?
Activities/Fragments become GOD classes.
Responsibilities are messed up.
Difficult to test: framework dependencies.
Database in presentation layer (since it was our only Android related layer).
24. Problems?
Activities/Fragments become GOD classes.
Responsibilities are messed up.
Difficult to test: framework dependencies.
Database in presentation layer (since it was our only Android related layer).
Cache in the sync layer.
25. Problems?
Activities/Fragments become GOD classes.
Responsibilities are messed up.
Difficult to test: framework dependencies.
Database in presentation layer (since it was our only Android related layer).
Cache in the sync layer.
Complex data schemes used also in the presentation layer, not needed here.
26. Problems?
Activities/Fragments become GOD classes.
Responsibilities are messed up.
Difficult to test: framework dependencies.
Database in presentation layer (since it was our only Android related layer).
Cache in the sync layer.
Complex data schemes used also in the presentation layer, not needed here.
We wanted to do it better!
28. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
29. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
We are going to decouple the different core elements of our app.
30. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
We are going to decouple the different core elements of our app.
We are going to improve the way we fetch data.
31. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
We are going to decouple the different core elements of our app.
We are going to improve the way we fetch data.
We are going to make testing easier to do, and increase our test coverage.
32. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
We are going to decouple the different core elements of our app.
We are going to improve the way we fetch data.
We are going to make testing easier to do, and increase our test coverage.
We are going to improve our codebase.
33. What are we going to do?
We are going to separate responsibilities. Yes, Even more!
We are going to REFACTOR
We are going to decouple the different core elements of our app.
We are going to improve the way we fetch data.
We are going to make testing easier to do, and increase our test coverage.
We are going to improve our codebase.
43. VIEW
Activity/Fragment
PRESENTER
Man in the middle
MODEL
Business logic
Starts the
process
User interacts
with the app
Everything starts with the Model View Presenter (MVP) 😎
44. VIEW
Activity/Fragment
PRESENTER
Man in the middle
MODEL
Business logic
Starts the
process
Executes
use caseUser interacts
with the app
Everything starts with the Model View Presenter (MVP) 😎
45. VIEW
Activity/Fragment
PRESENTER
Man in the middle
MODEL
Business logic
Starts the
process
Executes
use case
Returns the result
User interacts
with the app
Everything starts with the Model View Presenter (MVP) 😎
46. VIEW
Activity/Fragment
PRESENTER
Man in the middle
MODEL
Business logic
Starts the
process
Executes
use case
Updates view Returns the result
User interacts
with the app
Everything starts with the Model View Presenter (MVP) 😎
53. VIEW PRESENTER
VIEWCALLBACK
USE CASE
implements and passes
it to the presenter
creates an
instance and passes it to the
presenter
will invoke it to
communicate back (when we have
the result)
will execute it to start
the process
123. Testing?
Views now don’t have business logic and/or data.
Presenters don’t have framework dependencies.
124. Testing?
Views now don’t have business logic and/or data.
Presenters don’t have framework dependencies.
Dependency injection make testing easier
125. Testing?
Views now don’t have business logic and/or data.
Presenters don’t have framework dependencies.
Use cases are very small and simple.
Dependency injection make testing easier
126. Testing?
Views now don’t have business logic and/or data.
Presenters don’t have framework dependencies.
Use cases are very small and simple.
We can test now every component independently.
Dependency injection make testing easier
127. Testing?
Views now don’t have business logic and/or data.
Presenters don’t have framework dependencies.
Use cases are very small and simple.
We can test now every component independently.
Dependency injection make testing easier
Now testing is easy peasy!
137. Lessons learned
Dependency Inversion Principle is key.
Following SOLID principles makes MVP easy to build.
Small use cases define what you want to do.
138. Lessons learned
Dependency Inversion Principle is key.
Following SOLID principles makes MVP easy to build.
Small use cases define what you want to do.
We have different alternatives to fetch data, choose yours.
139. Lessons learned
Dependency Inversion Principle is key.
Following SOLID principles makes MVP easy to build.
Small use cases define what you want to do.
We have different alternatives to fetch data, choose yours.
Decouple components makes testing easier.
142. License
(cc) 2016 César Valiente. Some rights reserved. This document is
distributed under the Creative Commons Attribution-ShareAlike 3.0
license, available in http://creativecommons.org/licenses/by-sa/3.0/
143. Image licenses
Wunderlist (Microsoft): permission granted.
Emojis by Emoji One (CC-BY): http://emojione.com/
Iceberg: http://science-all.com/iceberg.html
All images belong to their owners.