SlideShare a Scribd company logo
1 of 35
Download to read offline
Christian Panadero
http://panavtec.me
@PaNaVTEC
Github - PaNaVTEC
My way to clean Android
Fernando Cejas Jorge Barroso
Pedro Gomez Sergio Rodrigo
@fernando_cejas @flipper83
@pedro_g_s @srodrigoDev
Android developer @ Sound Cloud
Android developer @ Tuenti
Cofounder & Android expert @ Karumi
Android developer @ Develapps
Alberto Moraga Carlos Morera
@albertomoraga @CarlosMChica
iOS Developer @ Selltag Android Developer @ Viagogo
Acknowledgements
“My way to clean Android”
Why clean architecture?
• Independent of Frameworks
• Testable
• Independent of UI
• Independent of Database
• Independent of any external agency
Concepts
• Command pattern (Invoker, command, receiver)
• Interactors / Use cases
• Abstractions
• Data Source
• Repository
Abstraction levels
Presenters
Interactors
Entities
Repository
Data sources
UI
Abstractions
The dependency rule
Presenters
Interactors
Entities
Repository
Data sources
UI
Abstractions
Thinking in projects
• App (UI, DI and implementation details)
• Presentation
• Domain y Entities
• Repository
• Data Sources
Project dependencies
App
Presenters Domain Data
Entities
Repository
Flow
View
Presenter
Presenter
Interactor
Interactor
Interactor
Interactor
Repository
Repository
DataSource
DataSource
DataSource
UI: MVP
ViewPresenter(s)
Model
Events
Fill the view
Actions Actions output
UI: MVP - View
public class MainActivity extends BaseActivity implements MainView {
@Inject MainPresenter presenter;
@Override protected void onResume() {
super.onResume();
presenter.onResume();
}
@Override public void onRefresh() {
presenter.onRefresh();
}
UI: MVP - Presenter
public class MainPresenter extends Presenter {
private MainView mainView;
private Bus bus;
public void onResume() {
bus.register(this);
}
public void onPause() {
bus.unregister(this);
}
public void onRefresh() {
mainView.clearData();
…
}
public interface MainView {
void showGetContactsError();
void clearData();
}
UI: MVP - Presenter
Presentation - Domain
Presenter InteractorInvoker
Bus
Bus IMP
Invoker IMP
Presentation - Domain
public class MainPresenter extends Presenter {
public void onCreate() {
interactorInvoker.execute(getContactsInteractor);
}
public void onEvent(GetContactsEvent event) {
if (event.getError() == null) {
List<PresentationContact> contacts = event.getContacts();
mainView.refreshContactsList(contacts);
} else {
mainView.showGetContactsError();
}
}
public class GetContactsInteractor implements Interactor {
private Bus bus;
private ContactsRepository repository;
@Override public void execute() {
GetContactsEvent event = new GetContactsEvent();
try {
List<Contact> contacts = repository.obtainContacts();
event.setContacts(contacts);
} catch (RetrieveContactsException e) {
event.setError(e);
}
bus.post(event);
}
}
Domain - Interactor
Repository
Network
Data Source
BDD
Data Source
Repository
Model
Data
Repository Interface
public interface ContactsRepository {
List<Contact> obtainContacts() throws
CantRetrieveContactsException;
Contact obtain(String md5) throws
CannotObtainContactException;
}
Repository imp
@Override public List<Contact> obtainContacts() throws
RetrieveContactsException {
List<Contact> contacts = null;
try {
contacts = bddDataSource.obtainContacts();
} catch (ObtainContactsBddException | InvalidCacheException e) {
try {
contacts = networkDataSource.obtainContacts();
bddDataSource.persist(contacts);
} catch (UnknownObtainContactsException | ContactsNetworkException) {
throw new RetrieveContactsException();
} catch (PersistContactsBddException) {
e.printStackTrace();
}
}
return contacts;
}
Data source
Model
Data source Imp
Data source
Mapper
Data source Interface
public interface ContactsNetworkDataSource {
public List<Contact> obtainContacts() throws
ContactsNetworkException, UnknownObtainContactsException;
}
private ContactsApiService apiService;
private static final ApiContactMapper mapper = new ApiContactMapper();
@Override public List<Contact> obtainContacts() throws ContactsNetworkException
{
try {
ApiContactsResponse apiContactsResponse = apiService.obtainUsers(100);
List<ApiContactResult> results = apiContactsResponse.getResults();
<MAP APICONTACTS TO CONTACTS>
return contacts;
} catch (Throwable e) {
throw new ContactsNetworkException();
}
}
Data source imp
Caching Strategy
public interface CachingStrategy<T> {
boolean isValid(T data);
}
public TtlCachingStrategy(int ttl, TimeUnit timeUnit) {
ttlMillis = timeUnit.toMillis(ttl);
}
@Override public boolean isValid(T data) {
return (data.getPersistedTime() + ttlMillis) >
System.currentTimeMillis();
}
Caching Strategy
@Override public List<Contact> obtainContacts()
throws ObtainContactsBddException, UnknownObtainContactsException,
InvalidCacheException {
try {
List<BddContact> bddContacts = daoContacts.queryForAll();
if (!cachingStrategy.isValid(bddContacts)) {
deleteBddContacts(cachingStrategy.candidatesToPurgue(bddContacts));
throw new InvalidCacheException();
}
ArrayList<Contact> contacts = new ArrayList<>();
for (BddContact bddContact : bddContacts) {
contacts.add(transformer.transform(bddContact, Contact.class));
}
return contacts;
} catch (java.sql.SQLException e) {
throw new ObtainContactsBddException();
} catch (Throwable e) {
throw new UnknownObtainContactsException();
}
}
Repository adavantages
• Bussines logic doesn’t know where the data came
from
• It’s easy to change data source implementation
• If you change the data sources implementation the
business logic is not altered
– Uncle Bob
“Make implementation details swappable”
Picasso
public interface ImageLoader {
public void load(String url, ImageView imageView);
public void loadCircular(String url, ImageView imageView);
}
public class PicassoImageLoader implements ImageLoader {
private Picasso picasso;
public PicassoImageLoader(Picasso picasso) {
this.picasso = picasso;
}
public void load(String url, ImageView imageView) {
picasso.load(url).into(imageView);
}
@Override public void loadCircular(String url, ImageView imageView) {
picasso.load(url).transform(new CircleTransform()).into(imageView);
}
ErrorManager
public interface ErrorManager {
public void showError(String error);
}
public class SnackbarErrorManagerImp implements ErrorManager {
@Override public void showError(String error) {
SnackbarManager.show(Snackbar.with(activity).text(error));
}
}
public class ToastErrorManagerImp implements ErrorManager {
@Override public void showError(String error) {
Toast.makeText(activity, error,
Toast.LENGTH_LONG).show();
}
}
Tips
• ALWAYS Depend upon abstractions, NEVER
depend upon concretions
• Use a good naming, if there's a class you've
created and the naming does not feel right, most
probably it is wrong modeled.
• Create new shapes using the initial dartboard to
ensure that it's placed on the corresponding layer
– Uncle Bob
“Clean code. The last programming
language”
In Uncle Bob we trust
Show me the code!
https://github.com/PaNaVTEC/Clean-Contacts
References
• Fernando Cejas - Clean way
• Jorge Barroso - Arquitectura Tuenti
• Pedro Gomez - Dependency Injection
• Pedro Gomez - Desing patterns
• Uncle Bob - The clean architecture
¿Questions?
Christian Panadero
http://panavtec.me
@PaNaVTEC
Github - PaNaVTEC

More Related Content

What's hot

A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesDavid Wengier
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Ontico
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Loiane Groner
 
Lowering in C#: What really happens with your code?, from NDC Oslo 2019
Lowering in C#: What really happens with your code?, from NDC Oslo 2019Lowering in C#: What really happens with your code?, from NDC Oslo 2019
Lowering in C#: What really happens with your code?, from NDC Oslo 2019David Wengier
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Fabio Collini
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxLoiane Groner
 
Retrofit
RetrofitRetrofit
Retrofitbresiu
 
PROMAND 2014 project structure
PROMAND 2014 project structurePROMAND 2014 project structure
PROMAND 2014 project structureAlexey Buzdin
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFPierre-Yves Ricau
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformGregor Jarisch
 
Tips & Tricks Android
Tips & Tricks AndroidTips & Tricks Android
Tips & Tricks Androidintive
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorDavid Rodenas
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xTatsuya Maki
 
ASP.NET MVC Internals
ASP.NET MVC InternalsASP.NET MVC Internals
ASP.NET MVC InternalsVitaly Baum
 
Metaprogramming in .NET
Metaprogramming in .NETMetaprogramming in .NET
Metaprogramming in .NETjasonbock
 

What's hot (20)

A (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project FilesA (very) opinionated guide to MSBuild and Project Files
A (very) opinionated guide to MSBuild and Project Files
 
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
Паразитируем на React-экосистеме (Angular 4+) / Алексей Охрименко (IPONWEB)
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018Angular for Java Enterprise Developers: Oracle Code One 2018
Angular for Java Enterprise Developers: Oracle Code One 2018
 
Lowering in C#: What really happens with your code?, from NDC Oslo 2019
Lowering in C#: What really happens with your code?, from NDC Oslo 2019Lowering in C#: What really happens with your code?, from NDC Oslo 2019
Lowering in C#: What really happens with your code?, from NDC Oslo 2019
 
Android development
Android developmentAndroid development
Android development
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
 
Gerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRxGerenciamento de estado no Angular com NgRx
Gerenciamento de estado no Angular com NgRx
 
Retrofit
RetrofitRetrofit
Retrofit
 
Open sourcing the store
Open sourcing the storeOpen sourcing the store
Open sourcing the store
 
PROMAND 2014 project structure
PROMAND 2014 project structurePROMAND 2014 project structure
PROMAND 2014 project structure
 
Sharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SFSharper Better Faster Dagger ‡ - Droidcon SF
Sharper Better Faster Dagger ‡ - Droidcon SF
 
E.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot PlatformE.D.D.I - Open Source Chatbot Platform
E.D.D.I - Open Source Chatbot Platform
 
Tips & Tricks Android
Tips & Tricks AndroidTips & Tricks Android
Tips & Tricks Android
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
Automated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.xAutomated%20testing%20with%20Espresso2.x
Automated%20testing%20with%20Espresso2.x
 
Camunda@1&1
Camunda@1&1Camunda@1&1
Camunda@1&1
 
Gwt RPC
Gwt RPCGwt RPC
Gwt RPC
 
ASP.NET MVC Internals
ASP.NET MVC InternalsASP.NET MVC Internals
ASP.NET MVC Internals
 
Metaprogramming in .NET
Metaprogramming in .NETMetaprogramming in .NET
Metaprogramming in .NET
 
CDI: How do I ?
CDI: How do I ?CDI: How do I ?
CDI: How do I ?
 

Viewers also liked

My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionChristian Panadero
 
Realm or: How I learned to stop worrying and love my app database
Realm or: How I learned to stop worrying and love my app databaseRealm or: How I learned to stop worrying and love my app database
Realm or: How I learned to stop worrying and love my app databaseSergi Martínez
 
It's the arts! Playing around with the Android canvas
It's the arts! Playing around with the Android canvasIt's the arts! Playing around with the Android canvas
It's the arts! Playing around with the Android canvasSergi Martínez
 
[Android] 2D Graphics
[Android] 2D Graphics[Android] 2D Graphics
[Android] 2D GraphicsNikmesoft Ltd
 
Introduction to Android Fragments
Introduction to Android FragmentsIntroduction to Android Fragments
Introduction to Android FragmentsSergi Martínez
 

Viewers also liked (10)

My way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
 
Admob y yo
Admob y yoAdmob y yo
Admob y yo
 
Introducción a mobclix
Introducción a mobclixIntroducción a mobclix
Introducción a mobclix
 
Android master class
Android master classAndroid master class
Android master class
 
Realm or: How I learned to stop worrying and love my app database
Realm or: How I learned to stop worrying and love my app databaseRealm or: How I learned to stop worrying and love my app database
Realm or: How I learned to stop worrying and love my app database
 
It's the arts! Playing around with the Android canvas
It's the arts! Playing around with the Android canvasIt's the arts! Playing around with the Android canvas
It's the arts! Playing around with the Android canvas
 
[Android] 2D Graphics
[Android] 2D Graphics[Android] 2D Graphics
[Android] 2D Graphics
 
Android data binding
Android data bindingAndroid data binding
Android data binding
 
Introduction to Android Fragments
Introduction to Android FragmentsIntroduction to Android Fragments
Introduction to Android Fragments
 
Effective Android UI - English
Effective Android UI - EnglishEffective Android UI - English
Effective Android UI - English
 

Similar to My way to clean android (EN) - Android day salamanca edition

The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android JetpackAhmad Arif Faizin
 
Clean Architecture on Android
Clean Architecture on AndroidClean Architecture on Android
Clean Architecture on AndroidTianming Xu
 
The use case of a scalable architecture
The use case of a scalable architectureThe use case of a scalable architecture
The use case of a scalable architectureToru Wonyoung Choi
 
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...Fons Sonnemans
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Joe Keeley
 
Mail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - ItalyMail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - ItalyYahoo
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networkingVitali Pekelis
 
Droidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineDroidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineJavier de Pedro López
 
Architecture components - IT Talk
Architecture components - IT TalkArchitecture components - IT Talk
Architecture components - IT TalkConstantine Mars
 
Architecture Components
Architecture Components Architecture Components
Architecture Components DataArt
 
softshake 2014 - Java EE
softshake 2014 - Java EEsoftshake 2014 - Java EE
softshake 2014 - Java EEAlexis Hassler
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)Jose Manuel Pereira Garcia
 
Implement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoImplement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoToshiaki Maki
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasyJBug Italy
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileKonstantin Loginov
 
Introduction to R2DBC
Introduction to R2DBCIntroduction to R2DBC
Introduction to R2DBCRob Hedgpeth
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsHassan Abid
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responsesdarrelmiller71
 

Similar to My way to clean android (EN) - Android day salamanca edition (20)

The Best Way to Become an Android Developer Expert with Android Jetpack
The Best Way to Become an Android Developer Expert  with Android JetpackThe Best Way to Become an Android Developer Expert  with Android Jetpack
The Best Way to Become an Android Developer Expert with Android Jetpack
 
Clean Architecture on Android
Clean Architecture on AndroidClean Architecture on Android
Clean Architecture on Android
 
The use case of a scalable architecture
The use case of a scalable architectureThe use case of a scalable architecture
The use case of a scalable architecture
 
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
TechDays 2016 - Developing websites using asp.net core mvc6 and entity framew...
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
 
Mail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - ItalyMail OnLine Android Application at DroidCon - Turin - Italy
Mail OnLine Android Application at DroidCon - Turin - Italy
 
Advanced #2 networking
Advanced #2   networkingAdvanced #2   networking
Advanced #2 networking
 
Droidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offlineDroidcon ES '16 - How to fail going offline
Droidcon ES '16 - How to fail going offline
 
Architecture components - IT Talk
Architecture components - IT TalkArchitecture components - IT Talk
Architecture components - IT Talk
 
Architecture Components
Architecture Components Architecture Components
Architecture Components
 
softshake 2014 - Java EE
softshake 2014 - Java EEsoftshake 2014 - Java EE
softshake 2014 - Java EE
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Implement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyoImplement Service Broker with Spring Boot #cf_tokyo
Implement Service Broker with Spring Boot #cf_tokyo
 
May 2010 - RestEasy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
 
Mobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve MobileMobile Developers Talks: Delve Mobile
Mobile Developers Talks: Delve Mobile
 
Clean Architecture @ Taxibeat
Clean Architecture @ TaxibeatClean Architecture @ Taxibeat
Clean Architecture @ Taxibeat
 
Introduction to R2DBC
Introduction to R2DBCIntroduction to R2DBC
Introduction to R2DBC
 
RESTEasy
RESTEasyRESTEasy
RESTEasy
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Crafting Evolvable Api Responses
Crafting Evolvable Api ResponsesCrafting Evolvable Api Responses
Crafting Evolvable Api Responses
 

Recently uploaded

Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

My way to clean android (EN) - Android day salamanca edition

  • 2. Fernando Cejas Jorge Barroso Pedro Gomez Sergio Rodrigo @fernando_cejas @flipper83 @pedro_g_s @srodrigoDev Android developer @ Sound Cloud Android developer @ Tuenti Cofounder & Android expert @ Karumi Android developer @ Develapps Alberto Moraga Carlos Morera @albertomoraga @CarlosMChica iOS Developer @ Selltag Android Developer @ Viagogo Acknowledgements
  • 3. “My way to clean Android”
  • 4. Why clean architecture? • Independent of Frameworks • Testable • Independent of UI • Independent of Database • Independent of any external agency
  • 5. Concepts • Command pattern (Invoker, command, receiver) • Interactors / Use cases • Abstractions • Data Source • Repository
  • 8. Thinking in projects • App (UI, DI and implementation details) • Presentation • Domain y Entities • Repository • Data Sources
  • 11. UI: MVP ViewPresenter(s) Model Events Fill the view Actions Actions output
  • 12. UI: MVP - View public class MainActivity extends BaseActivity implements MainView { @Inject MainPresenter presenter; @Override protected void onResume() { super.onResume(); presenter.onResume(); } @Override public void onRefresh() { presenter.onRefresh(); }
  • 13. UI: MVP - Presenter public class MainPresenter extends Presenter { private MainView mainView; private Bus bus; public void onResume() { bus.register(this); } public void onPause() { bus.unregister(this); } public void onRefresh() { mainView.clearData(); … }
  • 14. public interface MainView { void showGetContactsError(); void clearData(); } UI: MVP - Presenter
  • 15. Presentation - Domain Presenter InteractorInvoker Bus Bus IMP Invoker IMP
  • 16. Presentation - Domain public class MainPresenter extends Presenter { public void onCreate() { interactorInvoker.execute(getContactsInteractor); } public void onEvent(GetContactsEvent event) { if (event.getError() == null) { List<PresentationContact> contacts = event.getContacts(); mainView.refreshContactsList(contacts); } else { mainView.showGetContactsError(); } }
  • 17. public class GetContactsInteractor implements Interactor { private Bus bus; private ContactsRepository repository; @Override public void execute() { GetContactsEvent event = new GetContactsEvent(); try { List<Contact> contacts = repository.obtainContacts(); event.setContacts(contacts); } catch (RetrieveContactsException e) { event.setError(e); } bus.post(event); } } Domain - Interactor
  • 19. Repository Interface public interface ContactsRepository { List<Contact> obtainContacts() throws CantRetrieveContactsException; Contact obtain(String md5) throws CannotObtainContactException; }
  • 20. Repository imp @Override public List<Contact> obtainContacts() throws RetrieveContactsException { List<Contact> contacts = null; try { contacts = bddDataSource.obtainContacts(); } catch (ObtainContactsBddException | InvalidCacheException e) { try { contacts = networkDataSource.obtainContacts(); bddDataSource.persist(contacts); } catch (UnknownObtainContactsException | ContactsNetworkException) { throw new RetrieveContactsException(); } catch (PersistContactsBddException) { e.printStackTrace(); } } return contacts; }
  • 21. Data source Model Data source Imp Data source Mapper
  • 22. Data source Interface public interface ContactsNetworkDataSource { public List<Contact> obtainContacts() throws ContactsNetworkException, UnknownObtainContactsException; }
  • 23. private ContactsApiService apiService; private static final ApiContactMapper mapper = new ApiContactMapper(); @Override public List<Contact> obtainContacts() throws ContactsNetworkException { try { ApiContactsResponse apiContactsResponse = apiService.obtainUsers(100); List<ApiContactResult> results = apiContactsResponse.getResults(); <MAP APICONTACTS TO CONTACTS> return contacts; } catch (Throwable e) { throw new ContactsNetworkException(); } } Data source imp
  • 24. Caching Strategy public interface CachingStrategy<T> { boolean isValid(T data); } public TtlCachingStrategy(int ttl, TimeUnit timeUnit) { ttlMillis = timeUnit.toMillis(ttl); } @Override public boolean isValid(T data) { return (data.getPersistedTime() + ttlMillis) > System.currentTimeMillis(); }
  • 25. Caching Strategy @Override public List<Contact> obtainContacts() throws ObtainContactsBddException, UnknownObtainContactsException, InvalidCacheException { try { List<BddContact> bddContacts = daoContacts.queryForAll(); if (!cachingStrategy.isValid(bddContacts)) { deleteBddContacts(cachingStrategy.candidatesToPurgue(bddContacts)); throw new InvalidCacheException(); } ArrayList<Contact> contacts = new ArrayList<>(); for (BddContact bddContact : bddContacts) { contacts.add(transformer.transform(bddContact, Contact.class)); } return contacts; } catch (java.sql.SQLException e) { throw new ObtainContactsBddException(); } catch (Throwable e) { throw new UnknownObtainContactsException(); } }
  • 26. Repository adavantages • Bussines logic doesn’t know where the data came from • It’s easy to change data source implementation • If you change the data sources implementation the business logic is not altered
  • 27. – Uncle Bob “Make implementation details swappable”
  • 28. Picasso public interface ImageLoader { public void load(String url, ImageView imageView); public void loadCircular(String url, ImageView imageView); } public class PicassoImageLoader implements ImageLoader { private Picasso picasso; public PicassoImageLoader(Picasso picasso) { this.picasso = picasso; } public void load(String url, ImageView imageView) { picasso.load(url).into(imageView); } @Override public void loadCircular(String url, ImageView imageView) { picasso.load(url).transform(new CircleTransform()).into(imageView); }
  • 29. ErrorManager public interface ErrorManager { public void showError(String error); } public class SnackbarErrorManagerImp implements ErrorManager { @Override public void showError(String error) { SnackbarManager.show(Snackbar.with(activity).text(error)); } } public class ToastErrorManagerImp implements ErrorManager { @Override public void showError(String error) { Toast.makeText(activity, error, Toast.LENGTH_LONG).show(); } }
  • 30. Tips • ALWAYS Depend upon abstractions, NEVER depend upon concretions • Use a good naming, if there's a class you've created and the naming does not feel right, most probably it is wrong modeled. • Create new shapes using the initial dartboard to ensure that it's placed on the corresponding layer
  • 31. – Uncle Bob “Clean code. The last programming language”
  • 32. In Uncle Bob we trust
  • 33. Show me the code! https://github.com/PaNaVTEC/Clean-Contacts
  • 34. References • Fernando Cejas - Clean way • Jorge Barroso - Arquitectura Tuenti • Pedro Gomez - Dependency Injection • Pedro Gomez - Desing patterns • Uncle Bob - The clean architecture