O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
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 develope...
“My way to clean Android”
¿Por qué Clean?
• Desacoplado de los frameworks
• Testable
• Desacoplado de la UI
• Desacoplado de BDD
• Desacoplado de cu...
Conceptos
• Patrón command (Invoker, command, receiver)
• Interactors / Casos de uso
• Abstracciones
• Data Source
• Repos...
Niveles de abstracción
Presenters
Interactors
Entidades
Repository
Data sources
UI
Abstractions
Regla de dependencias
Presenters
Interactors
Entidades
Repository
Data sources
UI
Abstractions
Modelando el proyecto
• App (UI, DI y detalles de implementación)
• Presentation
• Domain y Entities
• Repository
• Data S...
Dependencias del proyecto
App
Presenters Domain Data
Entities
Repository
Flow
View
Presenter
Presenter
Interactor
Interactor
Interactor
Interactor
Repository
Repository
DataSource
DataSource
Data...
UI: MVP
ViewPresenter(s)
Model
Eventos
Rellena la vista
Acciones
Resultados de
esas acciones
UI: MVP - View
public class MainActivity extends BaseActivity implements MainView {
@Inject MainPresenter presenter;
@Over...
UI: MVP - Presenter
public class MainPresenter extends Presenter {
private MainView mainView;
private Bus bus;
public void...
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(ge...
public class GetContactsInteractor implements Interactor {
private Bus bus;
private ContactsRepository repository;
@Overri...
Repository
Network
Data Source
BDD
Data Source
Repository
Model
Data
Repository Interface
public interface ContactsRepository {
List<Contact> obtainContacts() throws
CantRetrieveContactsExcep...
Repository imp
@Override public List<Contact> obtainContacts() throws
RetrieveContactsException {
List<Contact> contacts =...
Data source
Model
Data source Imp
Data source
Mapper
Data source Interface
public interface ContactsNetworkDataSource {
public List<Contact> obtainContacts() throws
ContactsNe...
private ContactsApiService apiService;
private static final ApiContactMapper mapper = new ApiContactMapper();
@Override pu...
Caching Strategy
public interface CachingStrategy<T> {
boolean isValid(T data);
}
public TtlCachingStrategy(int ttl, TimeU...
Caching Strategy
@Override public List<Contact> obtainContacts()
throws ObtainContactsBddException, UnknownObtainContactsE...
Ventajas de Repository
• La lógica de negocio no sabe de donde vienen los
datos.
• Fácil de cambiar la implementación de l...
– Uncle Bob
“Make implementation details swappable”
Picasso
public interface ImageLoader {
public void load(String url, ImageView imageView);
public void loadCircular(String ...
ErrorManager
public interface ErrorManager {
public void showError(String error);
}
public class SnackbarErrorManagerImp i...
Consejos
• Trabaja siempre con abstracciones nunca con
concreciones.
• Usa un buen naming, si ves que hay alguna figura
que...
– Uncle Bob
“Clean code. The last programming
language”
In Uncle Bob we trust
Show me the code!
https://github.com/PaNaVTEC/Clean-Contacts
Referencias
• Fernando Cejas - Clean way
• Jorge Barroso - Arquitectura Tuenti
• Pedro Gomez - Dependency Injection
• Pedr...
¿Preguntas?
Christian Panadero
http://panavtec.me
@PaNaVTEC
Github - PaNaVTEC
Próximos SlideShares
Carregando em…5
×

My way to clean android - Android day salamanca edition

5.041 visualizações

Publicada em

My way to clean android implementation

Publicada em: Tecnologia
  • Seja o primeiro a comentar

My way to clean android - Android day salamanca edition

  1. 1. Christian Panadero http://panavtec.me @PaNaVTEC Github - PaNaVTEC My way to clean Android
  2. 2. Fernando Cejas Jorge Barroso Pedro Gomez Sergio Rodrigo @fernando_cejas @flipper83 @pedro_g_s @srodrigoDev Android developer en Sound Cloud Android developer en Tuenti Cofounder & Android expert en Karumi Android developer en Develapps Alberto Moraga Carlos Morera @albertomoraga @CarlosMChica iOS Developer en Selltag Android Developer en Viagogo Agradecimientos
  3. 3. “My way to clean Android”
  4. 4. ¿Por qué Clean? • Desacoplado de los frameworks • Testable • Desacoplado de la UI • Desacoplado de BDD • Desacoplado de cualquier detalle de implementación
  5. 5. Conceptos • Patrón command (Invoker, command, receiver) • Interactors / Casos de uso • Abstracciones • Data Source • Repository
  6. 6. Niveles de abstracción Presenters Interactors Entidades Repository Data sources UI Abstractions
  7. 7. Regla de dependencias Presenters Interactors Entidades Repository Data sources UI Abstractions
  8. 8. Modelando el proyecto • App (UI, DI y detalles de implementación) • Presentation • Domain y Entities • Repository • Data Sources
  9. 9. Dependencias del proyecto App Presenters Domain Data Entities Repository
  10. 10. Flow View Presenter Presenter Interactor Interactor Interactor Interactor Repository Repository DataSource DataSource DataSource
  11. 11. UI: MVP ViewPresenter(s) Model Eventos Rellena la vista Acciones Resultados de esas acciones
  12. 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. 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. 14. public interface MainView { void showGetContactsError(); void clearData(); } UI: MVP - Presenter
  15. 15. Presentation - Domain Presenter InteractorInvoker Bus Bus IMP Invoker IMP
  16. 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. 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
  18. 18. Repository Network Data Source BDD Data Source Repository Model Data
  19. 19. Repository Interface public interface ContactsRepository { List<Contact> obtainContacts() throws CantRetrieveContactsException; Contact obtain(String md5) throws CannotObtainContactException; }
  20. 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. 21. Data source Model Data source Imp Data source Mapper
  22. 22. Data source Interface public interface ContactsNetworkDataSource { public List<Contact> obtainContacts() throws ContactsNetworkException, UnknownObtainContactsException; }
  23. 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. 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. 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. 26. Ventajas de Repository • La lógica de negocio no sabe de donde vienen los datos. • Fácil de cambiar la implementación de los orígenes de datos. • En caso de cambio de orígenes de datos la lógica de negocio no se ve alterada.
  27. 27. – Uncle Bob “Make implementation details swappable”
  28. 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. 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. 30. Consejos • Trabaja siempre con abstracciones nunca con concreciones. • Usa un buen naming, si ves que hay alguna figura que has creado que no sabes que nombre poner, seguramente esté mal modelada. • Si creas nuevas figuras usa la diana inicial para asegurarte que las creas en la capa correspondiente
  31. 31. – Uncle Bob “Clean code. The last programming language”
  32. 32. In Uncle Bob we trust
  33. 33. Show me the code! https://github.com/PaNaVTEC/Clean-Contacts
  34. 34. Referencias • Fernando Cejas - Clean way • Jorge Barroso - Arquitectura Tuenti • Pedro Gomez - Dependency Injection • Pedro Gomez - Desing patterns • Uncle Bob - The clean architecture
  35. 35. ¿Preguntas? Christian Panadero http://panavtec.me @PaNaVTEC Github - PaNaVTEC

×