Flexible Dependency

Flexible Dependency

Dependencies coupled are dangerous because we couple both modules in a way that if we need to change one module with another, we necessarily need to modify the code of the coupled module that’s really bad if we want to create a testable app because unit testing requires that when we are testing a module, it is isolated from the rest of modules in our app. The solution is Depend upon abstractions. Do not depend upon concrete classes.

9f523401a845a29c93ff73cde4c3db2b?s=128

Erik Jhordan Rey

November 07, 2016
Tweet

Transcript

  1. Flexible Dependency Erik Jhordan González Reyes Mobile Engineer at Segundamano

    erik.gonzalez@schibsted.com.mx @ErikJhordan_Rey github.com/erikcaffrey
  2. Talk Schedule • Inheritance or Composition • From STUPID to

    SOLID Code • Inversion of Control (IoC) • Dependency Inversion • Dependency Injection
  3. “I want to write test but I don't know what

    and how because my code is not testable”
  4. / SCHIBSTED MEDIA GROUP Inheritance or Composition

  5. Inheritance

  6. / SCHIBSTED MEDIA GROUP https://github.com/android/platform_frameworks_base/blob/donut-release/core/java/android/app/Activity.java Android Donut - 3628 lines

    of code https://github.com/android/platform_frameworks_base/blob/jb-release/core/java/android/app/Activity.java Android Jelly Bean - 5200 lines of code https://github.com/android/platform_frameworks_base/blob/nougat-release/core/java/android/app/Activity.java Android Nougat - 7177 lines of code https://github.com/android/platform_frameworks_base/blob/lollipop-release/core/java/android/app/Activity.java Android Lollipop - 6209 lines of code Android O - WTF ???????
  7. / SCHIBSTED MEDIA GROUP https://github.com/android/platform_frameworks_base/blob/ics-mr1-release/core/java/android/app/Fragment.java Android ICS-MR1-Release - 1563 lines

    of code https://github.com/android/platform_frameworks_base/blob/jb-release/core/java/android/app/Fragment.java Android Jelly Bean - 1601 lines of code https://github.com/android/platform_frameworks_base/blob/nougat-release/core/java/android/app/Fragment.java Android Nougat - 2633 lines of code https://github.com/android/platform_frameworks_base/blob/lollipop-release/core/java/android/app/Fragment.java Android Lollipop - 2291 lines of code Android O - WTF ???????
  8. / SCHIBSTED MEDIA GROUP https://github.com/android/platform_frameworks_base/blob/donut-release/core/java/android/widget/TextView.java Android Donut - 7317 lines

    of code https://github.com/android/platform_frameworks_base/blob/jb-release/core/java/android/widget/TextView.java Android Jelly Bean - 8768 lines of code https://github.com/android/platform_frameworks_base/blob/nougat-release/core/java/android/widget/TextView.java Android Nougat - 10402 lines of code https://github.com/android/platform_frameworks_base/blob/lollipop-release/core/java/android/widget/TextView.java Android Lollipop - 9476 lines of code Android O - WTF ???????
  9. / SCHIBSTED MEDIA GROUP https://github.com/android/platform_frameworks_base

  10. / SCHIBSTED MEDIA GROUP Inheritance Smells A lot Coupled Code

    Infinite levels of Inheritance Extends non abstract class Base classes with hundreds of lines code. (code not maintainable) Architecture based on Inheritance Difficult to add new functionality
  11. Composition

  12. / SCHIBSTED MEDIA GROUP In an object-oriented design the way

    in which you model objects that contain other objects is with composition, the act of composing a class out of references to other objects.
  13. / SCHIBSTED MEDIA GROUP Composition Composition offers better test-ability of

    a class than Inheritance. Flexibility Requires of use of design Patterns Java doesn't support multiple inheritance
  14. / SCHIBSTED MEDIA GROUP From STUPID to SOLID code These

    are principles, not laws!
  15. / SCHIBSTED MEDIA GROUP

  16. STUPID

  17. / SCHIBSTED MEDIA GROUP STUPID Singleton Invasion Tight Coupling Untestability

    Premature Optimization Indescriptive Naming Duplication
  18. STUPID Singleton Invasion It is when you think the Singleton

    pattern is the most appropriate pattern for the current use case you have. In other words, you use it everywhere. //All MyActivities or Fragments.java If (M.DataManager.getInstance.getVehicles(context)) { Vehicle vehicle = M.DataManager.getInstance().getVehicle(context, vehicleId); /*...*/ }
  19. STUPID Tight Coupling Tight coupling, also known as strong coupling,

    is the degree to which each program module relies on each one of the other modules. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); {/* … */ } dribbblePrefs = DribbblePrefs.get(this); designerNewsPrefs = DesignerNewsPrefs.get(this); filtersAdapter = new FilterAdapter(this,SourceManager.getSources(this), new FilterAdapter.FilterAuthoriser() {/* … */ }
  20. STUPID Untestability Whenever you don’t write any tests because you

    don’t have time, the real issue is that your code is bad it is not testable. https://github.com/google/iosched/blob/master/android/src/m ain/java/com/google/samples/apps/iosched/explore/ExploreIO Fragment.java CollectionView.Inventory inventory = new CollectionView.Inventory(); CollectionView.InventoryGroup inventoryGroup; // BEGIN Add Message Cards. // Message cards are only used for onsite attendees. if (SettingsUtils.isAttendeeAtVenue(getContext())) { // Users are required to opt in or out of whether //they want conference message cards. if (!ConfMessageCardUtils.hasAnsweredConfMessageCardsPrompt(getContext())){ // User has not answered whether they want to opt in. // Build a opt-in/out card. inventoryGroup = new CollectionView.InventoryGroup(GROUP_ID_MESSAGE_CARDS); {/*...*/}
  21. STUPID Premature Optimization Premature optimization is the root of all

    evil. There is only cost, and no benefit. // This code works fine but maybe is premature public Single<ArticlePreview> articlePreview( String articleId ) { if ( cache.contains( articleId ) { return Single.just( cache.retrieve( articleId )); } else { return urlResolver.urlFor( articleId ) .map( myApi::articlePreview ) .doOnNext( cache::store ); } }
  22. STUPID Indescriptive Naming Any fool can write code that a

    computer can understand. Good programmers write code that humans can understand. public class NewsDataSourceImp extends ManagerData{ //This code return an instance of object News private News get(String number) { News value = map.get(number); if(value != null && value.getType() == 2) { return value; } else { return null; } }
  23. STUPID Duplication Duplicated code is bad, so please Don’t Repeat

    Yourself, and also Keep Simple Design. observable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(String value) {}); }
  24. SOLID

  25. / SCHIBSTED MEDIA GROUP Single Responsibility Principle Open / Closed

    Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle
  26. SOLID Single Responsibility Principle public class MainActivity extends Activity {

    public void onCreate() { articleApi.getArticles() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::renderArticleList); } }
  27. SOLID Single Responsibility Principle A class must have a unique

    responsibility public class MainActivity extends Activity { public void onCreate() { presenter.getArticles(this::renderArticles); } }
  28. SOLID Open / Closed Principle public class FeedAdapter extends RecyclerView.Adapter

    { public void onBindViewHolder (ViewHolder holder, int position) { FeedEntry feedEntry = entries.get(position); if (feedEntry instanceOf ArticleEntry) { renderArticle(feedEntry); } else { renderImage(feedEntry); } }
  29. SOLID Open / Closed Principle Every module should be open

    for extension but closed for modification. public class FeedAdapter extends RecyclerView.Adapter { public void onBindViewHolder (ViewHolder holder, int position) { FeedEntry feedEntry = entries.get(position); FeedRow row = feedFactory.get(feedEntry); row.render(); }
  30. SOLID Liskov Substitution Principle Child classes should never break the

    parent class' type definitions. public class CustomerRepositoryImpl implements CustomerRepository { @Override public List<Customer> getCustomersWithIds(List<Integer> ids) { ArrayList<Customer> customers = api.getCustomers(ids); return customers; } }
  31. SOLID Interface Segregation Principle States that clients should not be

    forced to implement interfaces they don't use. public static interface AnimatorListener { void onAnimationStart (Animator animation); void onAnimationEnd (Animator animation); void onAnimationCancel (Animator animation); void onAnimationRepeat (Animator animation); }
  32. SOLID Dependency Inversion Principle Depend upon abstractions. Do not depend

    upon concrete classes
  33. / SCHIBSTED MEDIA GROUP Inversion of Control (IoC)

  34. The natural evolution of the structured and imperative programming and

    the usage of reusable frameworks. The execution point where you software takes the control is not defined by programmer.
  35. / SCHIBSTED MEDIA GROUP Dependency Inversion

  36. “Depend upon abstractions. Do not depend upon concrete classes”

  37. One of the most important S.O.L.I. D principles. Abstractions should

    not depend on details. details should depend on abstractions. Provide implementation details depending on abstractions can be tedious.
  38. Coupled Classes

  39. / SCHIBSTED MEDIA GROUP Dependencies coupled are dangerous because we

    couple both modules in a way that if we need to change one module with another, we necessarily need to modify the code of the coupled module that’s really bad if we want to create a testable app. because unit testing requires that when we are testing a module, it is isolated from the rest of modules in our app.
  40. What’s a Dependency?

  41. / SCHIBSTED MEDIA GROUP A dependency is a coupling between

    two modules of our code usually because one of them uses the other to do something. public class ModuleA{ private ModuleB moduleB; public ModuleA(ModuleB moduleB){ this.moduleB = moduleB } public void doSomething(){ ... moduleB.doSomethingElse(); ... } }
  42. / SCHIBSTED MEDIA GROUP Dependency Injection

  43. / SCHIBSTED MEDIA GROUP Software Design Pattern used to facilitate

    the usage of Dependency Inversion. It consists of passing dependencies (inject them) via constructor or setter in order to extract the task of creating modules out from other modules. Objects are instantiated somewhere else and passed as constructor attributes when creating the current object.
  44. public class Android { private final Dependency dependency; public Android()

    { dependency = new Dependency(); } } Dependency Injection Sample public class Android { private final Dependency dependency; public Android(Dependency dependency) { this.dependency = dependency; } } VS
  45. public class Android { private final Dependency dependency; public Android()

    { dependency = new Dependency(); } } Dependency Injection Sample public class Android { private final Dependency dependency; public Android(Dependency dependency) { this.dependency = dependency; } } VS
  46. Constructor Injection public class Android { private final Dependency dependency;

    public Android(Dependency dependency) { this.dependency = dependency; } }
  47. Setter Injection public class Android { private Dependency dependency; public

    Android() { } public void setDependency(Dependency dependency) this.dependency = dependency; }
  48. / SCHIBSTED MEDIA GROUP

  49. Dependency Injection Advantages

  50. / SCHIBSTED MEDIA GROUP • Since dependencies can be injected

    and configured externally we can reuse those components. • We can just change the implementation of any object without having to make a lot of changes in our codebase, since that object instantiation resides in one place isolated and decoupled. • Dependencies can be injected into a component: it is possible to inject mock implementations of these dependencies which makes testing easier.
  51. Dependency Injection Smells

  52. / SCHIBSTED MEDIA GROUP • But here it comes a

    new problem. If we can’t create modules inside modules, there must be a place where those modules are instantiated. • Modules with huge constructors including lots of dependencies, code will become dirty and hard to read. • You can not access the constructor of an activity
  53. Solution ….

  54. Dependency Injector

  55. / SCHIBSTED MEDIA GROUP We can consider it as another

    module in our app that is in charge of providing instances of the rest of modules and inject their dependencies. • Guice - https://github.com/google/guice • Dagger - http://square.github.io/dagger/ • Dagger2 - http://google.github.io/dagger/ JSR-330: Dependency Injection Standar
  56. public class TeamsActivity extends BaseActivity implements TeamsPresenter.View { private TeamsPresenter

    presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TeamsRepository teamsRepository = new TeamsRepository( new TeamDataSourceFactory(this), new TeamToTeamEntityMapper()); GetEuroTeams getEuroTeams = new GetEuroTeams(teamsRepository); presenter = new TeamsPresenter(getEuroTeams, new TeamViewModelToTeamMapper()); presenter.setView(this); presenter.initialize(); }
  57. public class TeamsActivity extends BaseActivity implements TeamsPresenter.View { @Inject TeamsPresenter

    presenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter.setView(this); presenter.initialize(); }
  58. / SCHIBSTED MEDIA GROUP https://github.com/erikcaffrey/Clean-Architecture-Android

  59. / SCHIBSTED MEDIA GROUP Dagger 2 Kata para android developers.

    http://erikcaffrey.github.io/2016/07/08/kata-dagger2/
  60. Why use IoC, DIP and DI? The usage of IoC,

    Dependency Inversion and Dependency Injection provides give us the following benefits: • Testability • Decoupling • Modularity (Flexible) • Maintainability
  61. • Depend on abstractions do not depend on concrete class

    • Use design patterns on smart way • Avoid coupled code and strive for loosely coupled design between objects that interact • Avoid expensive tasks executed on main thread • Maintain a clean code style • Write Clean and Solid Code • Favor composition over inheritance • If your code is coupled the Refactor is your friend • Write test is your responsibility Advices
  62. 01 02 http://martinfowler.com/articles/dipInTheWild.html Brett L. Schuchert - DIP in the

    Wild http://martinfowler.com/articles/injection.html Martin Fowler - Inversion of Control Containers and the Dependency Injection pattern 03 Further Reading 04 https://www.youtube.com/watch?v=_3mHaG0A42g Jorge Barroso - Mobile "The (BEST) good practices" https://goo.gl/6mWjBg Txus Ballesteros - Herencia o Composición, esa es la cuestión. 05 http://erikcaffrey.github.io/2016/04/26/dependency-injection/ Erik Jhordan Rey - Dependency Injection
  63. Questions? Find me Erik Jhordan González Reyes Mobile Engineer github.com/erikcaffrey

    erik.gonzalez@schibsted.com.mx erikcaffrey.github.io @ErikJhordan_Rey +Erik Jhordan Rey
  64. Thank You Androidinights!

  65. / SCHIBSTED MEDIA GROUP EJEMPLO DE PORTADA NO.3 “La forma

    más rápida y sencilla para que gente como tú pueda vender y comprar cosas usadas.”
  66. Dagger 2 Juan Pablo “Gianpa” Villa Head of Mobile at

    Segundamano gianpa@segundamano.mx @ohbill github.com/juansimp
  67. / SCHIBSTED MEDIA GROUP bit.ly/kata-notes

  68. Talk Schedule • Refactor STUPID • Dependency Inversion • Dependency

    Injection • Unit Testing • Dagger • Refactor & Test
  69. SOLID Dependency Inversion $ git checkout 01-gateway

  70. SOLID Dependency Injection $ git checkout 02-dependency-injection

  71. UNIT Unit Testing $ git checkout 03-unit-testing $ git checkout

    03-unit-testing-2
  72. DAGGER Dependency Injection $ git checkout 04-dagger

  73. REFACTOR Refactor & Test $ git checkout 05-list-notes

  74. Thank You Androidinights!

  75. Questions? Find me Juan Pablo “Gianpa” Villa Head of Mobile

    github.com/juansimp gianpa@segundamano.mx @ohbill