Slide 1

Slide 1 text

Flexible Dependency Erik Jhordan González Reyes Mobile Engineer at Segundamano [email protected] @ErikJhordan_Rey github.com/erikcaffrey

Slide 2

Slide 2 text

Talk Schedule ● Inheritance or Composition ● From STUPID to SOLID Code ● Inversion of Control (IoC) ● Dependency Inversion ● Dependency Injection

Slide 3

Slide 3 text

“I want to write test but I don't know what and how because my code is not testable”

Slide 4

Slide 4 text

/ SCHIBSTED MEDIA GROUP Inheritance or Composition

Slide 5

Slide 5 text

Inheritance

Slide 6

Slide 6 text

/ 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 ???????

Slide 7

Slide 7 text

/ 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 ???????

Slide 8

Slide 8 text

/ 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 ???????

Slide 9

Slide 9 text

/ SCHIBSTED MEDIA GROUP https://github.com/android/platform_frameworks_base

Slide 10

Slide 10 text

/ 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

Slide 11

Slide 11 text

Composition

Slide 12

Slide 12 text

/ 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.

Slide 13

Slide 13 text

/ 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

Slide 14

Slide 14 text

/ SCHIBSTED MEDIA GROUP From STUPID to SOLID code These are principles, not laws!

Slide 15

Slide 15 text

/ SCHIBSTED MEDIA GROUP

Slide 16

Slide 16 text

STUPID

Slide 17

Slide 17 text

/ SCHIBSTED MEDIA GROUP STUPID Singleton Invasion Tight Coupling Untestability Premature Optimization Indescriptive Naming Duplication

Slide 18

Slide 18 text

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); /*...*/ }

Slide 19

Slide 19 text

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() {/* … */ }

Slide 20

Slide 20 text

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); {/*...*/}

Slide 21

Slide 21 text

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( String articleId ) { if ( cache.contains( articleId ) { return Single.just( cache.retrieve( articleId )); } else { return urlResolver.urlFor( articleId ) .map( myApi::articlePreview ) .doOnNext( cache::store ); } }

Slide 22

Slide 22 text

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; } }

Slide 23

Slide 23 text

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) {}); }

Slide 24

Slide 24 text

SOLID

Slide 25

Slide 25 text

/ SCHIBSTED MEDIA GROUP Single Responsibility Principle Open / Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle

Slide 26

Slide 26 text

SOLID Single Responsibility Principle public class MainActivity extends Activity { public void onCreate() { articleApi.getArticles() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::renderArticleList); } }

Slide 27

Slide 27 text

SOLID Single Responsibility Principle A class must have a unique responsibility public class MainActivity extends Activity { public void onCreate() { presenter.getArticles(this::renderArticles); } }

Slide 28

Slide 28 text

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); } }

Slide 29

Slide 29 text

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(); }

Slide 30

Slide 30 text

SOLID Liskov Substitution Principle Child classes should never break the parent class' type definitions. public class CustomerRepositoryImpl implements CustomerRepository { @Override public List getCustomersWithIds(List ids) { ArrayList customers = api.getCustomers(ids); return customers; } }

Slide 31

Slide 31 text

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); }

Slide 32

Slide 32 text

SOLID Dependency Inversion Principle Depend upon abstractions. Do not depend upon concrete classes

Slide 33

Slide 33 text

/ SCHIBSTED MEDIA GROUP Inversion of Control (IoC)

Slide 34

Slide 34 text

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.

Slide 35

Slide 35 text

/ SCHIBSTED MEDIA GROUP Dependency Inversion

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

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.

Slide 38

Slide 38 text

Coupled Classes

Slide 39

Slide 39 text

/ 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.

Slide 40

Slide 40 text

What’s a Dependency?

Slide 41

Slide 41 text

/ 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(); ... } }

Slide 42

Slide 42 text

/ SCHIBSTED MEDIA GROUP Dependency Injection

Slide 43

Slide 43 text

/ 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.

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

/ SCHIBSTED MEDIA GROUP

Slide 49

Slide 49 text

Dependency Injection Advantages

Slide 50

Slide 50 text

/ 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.

Slide 51

Slide 51 text

Dependency Injection Smells

Slide 52

Slide 52 text

/ 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

Slide 53

Slide 53 text

Solution ….

Slide 54

Slide 54 text

Dependency Injector

Slide 55

Slide 55 text

/ 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

Slide 56

Slide 56 text

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(); }

Slide 57

Slide 57 text

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(); }

Slide 58

Slide 58 text

/ SCHIBSTED MEDIA GROUP https://github.com/erikcaffrey/Clean-Architecture-Android

Slide 59

Slide 59 text

/ SCHIBSTED MEDIA GROUP Dagger 2 Kata para android developers. http://erikcaffrey.github.io/2016/07/08/kata-dagger2/

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

● 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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

Questions? Find me Erik Jhordan González Reyes Mobile Engineer github.com/erikcaffrey [email protected] erikcaffrey.github.io @ErikJhordan_Rey +Erik Jhordan Rey

Slide 64

Slide 64 text

Thank You Androidinights!

Slide 65

Slide 65 text

/ 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.”

Slide 66

Slide 66 text

Dagger 2 Juan Pablo “Gianpa” Villa Head of Mobile at Segundamano [email protected] @ohbill github.com/juansimp

Slide 67

Slide 67 text

/ SCHIBSTED MEDIA GROUP bit.ly/kata-notes

Slide 68

Slide 68 text

Talk Schedule ● Refactor STUPID ● Dependency Inversion ● Dependency Injection ● Unit Testing ● Dagger ● Refactor & Test

Slide 69

Slide 69 text

SOLID Dependency Inversion $ git checkout 01-gateway

Slide 70

Slide 70 text

SOLID Dependency Injection $ git checkout 02-dependency-injection

Slide 71

Slide 71 text

UNIT Unit Testing $ git checkout 03-unit-testing $ git checkout 03-unit-testing-2

Slide 72

Slide 72 text

DAGGER Dependency Injection $ git checkout 04-dagger

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

Thank You Androidinights!

Slide 75

Slide 75 text

Questions? Find me Juan Pablo “Gianpa” Villa Head of Mobile github.com/juansimp [email protected] @ohbill