Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

HELLO I’m Hannes

Slide 4

Slide 4 text

ANDROID ARCHITECTURE BY EXAMPLE

Slide 5

Slide 5 text

SLOWED DOWN BY BAD CODE?

Slide 6

Slide 6 text

FEAR CHANGING CODE!

Slide 7

Slide 7 text

SOLID Robert C. Martins
 „Uncle Bob“

Slide 8

Slide 8 text

SINGLE RESPONSIBILITY “A class should only have one reason to change” Book 
 currentPage() nextPage() print()

Slide 9

Slide 9 text

SINGLE RESPONSIBILITY “A class should only have one reason to change” Book 
 currentPage() nextPage() print() Book 
 currentPage() nextPage() Printer 
 print(Book)

Slide 10

Slide 10 text

FUNCTIONAL PROGRAMMING

Slide 11

Slide 11 text

FOCUS ON WHAT NOT ON HOW

Slide 12

Slide 12 text

public Map xxx(String[] words){
 Map countMap = new HashMap();
 
 for (String word : words ) {
 Integer count = countMap.get(word);
 if (count == null)
 countMap.put(word, 1);
 else
 countMap.put(word, count + 1);
 }
 return countMap;
 }

Slide 13

Slide 13 text

public Map countWords(String[] words){
 Map countMap = new HashMap();
 
 for (String word : words ) {
 Integer count = countMap.get(word);
 if (count == null)
 countMap.put(word, 1);
 else
 countMap.put(word, count + 1);
 }
 return countMap;
 }

Slide 14

Slide 14 text

fun countWords(words: Array) : Map { val grouped: Map> = words.groupBy { word -> word }
 val countMap: Map = grouped.mapValues { entry -> entry.value.size }
 return countMap }


Slide 15

Slide 15 text

fun countWords(words: Array) : Map { return words.groupBy { word -> word } .mapValues { entry -> entry.value.size } }


Slide 16

Slide 16 text

public Pair mostFrequent( String[] words, int threshold) {
 Pair mostFrequent = null;
 Map countMap = countWords( words );
 
 for (Map.Entry entry : countMap.entrySet() ) {
 if (entry.getValue() < threshold)
 continue;
 if (mostFrequent == null || entry.getValue() > mostFrequent.second)
 mostFrequent = new Pair(entry.getKey(), entry.getValue());
 }
 
 return mostFrequent;
 }

Slide 17

Slide 17 text

fun mostFrequent(words: Array, threshold: Int) : Pair { return countWords(words) // Map
 .toList() // List>
 .sortedBy { pair -> pair.second }
 .filter { pair -> pair.second > threshold }
 .first()
 }

Slide 18

Slide 18 text

IMMUTABILITY

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

You want an 
 immutable hot dog

Slide 21

Slide 21 text

AUTOVALUE @AutoValue public abstract class HotDog { }

Slide 22

Slide 22 text

AUTOVALUE @AutoValue public abstract class HotDog implements Parcelable { }

Slide 23

Slide 23 text

AUTOVALUE @AutoValue public abstract class HotDog implements Parcelable {
 @Json public abstract double getPrice(); }

Slide 24

Slide 24 text

AUTOVALUE @AutoValue public abstract class HotDog implements Parcelable {
 @Json public abstract double getPrice(); @ColumnName public abstract boolean hasKetchup(); }

Slide 25

Slide 25 text

AUTOVALUE @AutoValue public abstract class HotDog implements Parcelable {
 @Json public abstract double getPrice(); @ColumnName public abstract boolean hasKetchup(); public abstract static HotDog(double p, boolean k) { return new AutoValue_HotDog(p, k); } }

Slide 26

Slide 26 text

MVC Model-View-Controller

Slide 27

Slide 27 text

MVC Trygve Reenskaug View Model Controller observes changes

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

ARCHITECTURE BY EXAMPLE

Slide 30

Slide 30 text

OMNI-NOTES • https://github.com/federicoiosue/Omni-Notes • 506 Stars on Github • Last commit: 31st of May 2016 • 4,4 Rating • 100.000 - 500.000 installs 2nd June 2016

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

OMNI-NOTES • Fragments + Activities • AsyncTask with WeakReference as Callback • AsyncTask with EventBus • Database + File Storage 2nd June 2016

Slide 33

Slide 33 text

REDUX Predictable State Container

Slide 34

Slide 34 text

REDUX • Store • Action • Reducer

Slide 35

Slide 35 text

REDUX • Store - state container of the Model (immutable) • Action • Reducer

Slide 36

Slide 36 text

REDUX • Store - state container of the Model (immutable) • Action - command to change Model’s state • Reducer

Slide 37

Slide 37 text

REDUX • Store - state container of the Model (immutable) • Action - command to change Model’s state • Reducer - function (action , oldState) 㱺 newState

Slide 38

Slide 38 text

PURE FUNCTION public class Calculator {
 
 int result = 0;
 
 public int add(int x){
 result = x + result;
 return result;
 }
 }

Slide 39

Slide 39 text

–Robert C. Martins „The root of all evil is the assignment statement“

Slide 40

Slide 40 text

PURE FUNCTION public class PureCalculator {
 
 public int add(int x, int y){
 return x + y;
 }
 }

Slide 41

Slide 41 text

REDUX • Store - state container of the Model (immutable) • Action - command to change Model’s state • Reducer - function (action , oldState) 㱺 newState

Slide 42

Slide 42 text

OmniModel notes […],

Slide 43

Slide 43 text

OmniModel notes […], AddNoteAction title, description …

Slide 44

Slide 44 text

OmniModel notes […] AddNoteAction title, description … public OmniModel reduce(Action a, OmniModel old){
 if (a instance AddNoteAction){ OmniModel newModel = oldModel.withNotes(old.notes + a.newNode) return newModel; }
 …

Slide 45

Slide 45 text

AddNoteAction title, description … Store reduce(a, m) OmniModel notes […]

Slide 46

Slide 46 text

Store AddNoteAction title, description … reduce(a, m) OmniModel notes […] store.subscribe(this)

Slide 47

Slide 47 text

Store reduce(a, m) OmniModel notes […] store.subscribe(this) store.dispatch( )

Slide 48

Slide 48 text

Store reduce(a, m) OmniModel notes […] store.subscribe(this)

Slide 49

Slide 49 text

Store reduce(a, m) OmniModel notes […] store.subscribe(this) notify(model)

Slide 50

Slide 50 text

Store reduce(a, m) OmniModel notes […], orderBy: … notify(model) OrderByAction order: last modification store.dispatch()

Slide 51

Slide 51 text

Store reduce(a, m) OmniModel notes […], orderBy: … notify(model) OrderByAction order: last modification store.dispatch() notify(model)

Slide 52

Slide 52 text

REDUX • Immutability • Unidirectional data flow • pure function

Slide 53

Slide 53 text

TELEGRAM • https://github.com/DrKLO/Telegram • 4999 Stars on Github • Last commit: 26th of May 2016 • 4,2 Rating • 100.000.000 - 500.000.000 installs 2nd June 2016

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

TELEGRAM • MessageController, ContactsController … • Singletons, no dependency injection • Many classes are using these „Controllers“ • Classes with 1000+ lines of code

Slide 56

Slide 56 text

FLUX

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

ShowListAction

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

MessageStore ContactsStore

Slide 61

Slide 61 text

PushNotification
 MessageReceivedAction

Slide 62

Slide 62 text

FLUX • only public getters in Store API • Unidirectional data flow

Slide 63

Slide 63 text

FLUX VS. MVC* • Store ≈ Model • View ≈ Controller • unidirectional dataflow! *Not Reenskaug MVP

Slide 64

Slide 64 text

TWIDERE • https://github.com/TwidereProject/Twidere-Android • 873 Stars on Github • Last commit: 16th of May 2016 • 4,1 Rating • 100.000 - 500.000 installs 2nd June 2016

Slide 65

Slide 65 text

No content

Slide 66

Slide 66 text

TWIDERE • AbstractTask ≈ AsyncTask + WeakReference + EventBus • ContentResolver + ContentObserver • Tasks are doing a lot • Fragments & Activities are small ( < 500 Lines of Code) • Dependency Injection (Dagger 2)

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

MVVM Model-View-ViewModel

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

public class TweetModel {
 
 public ObservableString message;
 
 public ObservableInt stars;
 } Not immutable! Code in XML?
 Error State? Loading Indicator?

Slide 72

Slide 72 text

REACTIVE PROGRAMMING

Slide 73

Slide 73 text

java.util.Observable

Slide 74

Slide 74 text

https://www.youtube.com/watch?v=uNZnftSksYg

Slide 75

Slide 75 text

RxBus

Slide 76

Slide 76 text

MVVMC Model-View-ViewModel-Controller

Slide 77

Slide 77 text

FeedController HomeFeedViewModel loadCommand() : Observable HomeFeedActivity TwitterApi

Slide 78

Slide 78 text

FeedController HomeFeedViewModel loadCommand() : Observable HomeFeedActivity TwitterApi subscribe to loadCommand() ContentProvider

Slide 79

Slide 79 text

PLAID • https://github.com/nickbutcher/plaid • 5170 Stars on Github • Last commit: 1st of June 2016 • 5.000 - 10.000 installs 2nd June 2016

Slide 80

Slide 80 text

No content

Slide 81

Slide 81 text

PLAID • No clear Separation of responsibilities • AsyncTask • Android Services • Shared Preferences for persistency 2nd June 2016

Slide 82

Slide 82 text

CLEAN ARCHITECTURE Robert C. Martins

Slide 83

Slide 83 text

CLEAN ARCHITECTURE Entity Entity Entity Interactor
 Presenter
 View


Slide 84

Slide 84 text

CLEAN ARCHITECTURE Entity Entity Entity Interactor
 Presenter
 View
 Break the Rules! https://publicobject.com/2016/04/20/deliberate-disobedience/

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

MVI Model-View-Intent

Slide 87

Slide 87 text

cycle.js.org

Slide 88

Slide 88 text

intent( )

Slide 89

Slide 89 text

model( intent( ) )

Slide 90

Slide 90 text

view( model( intent( ) ) )

Slide 91

Slide 91 text

view( model( intent( ) ) ) new Model displayed by View Intent changes Model UI Events start intents

Slide 92

Slide 92 text

interface SearchView {
 Observable searchIntent();
 void showResult(SearchResult res);
 }

Slide 93

Slide 93 text

interface SearchView {
 Observable searchIntent();
 void showResult(SearchResult res);
 } class SearchResult {
 List result; boolean loading; boolean error;
 }

Slide 94

Slide 94 text

interface SearchView {
 Observable searchIntent();
 void showResult(SearchResult res);
 } class SearchResult {
 List result; boolean loading; boolean error;
 } class SearchEngine {
 Observable search(Observable s){ … } }

Slide 95

Slide 95 text

interface SearchView {
 Observable searchIntent();
 void showResult(SearchResult res);
 } class SearchResult {
 List result; boolean loading; boolean error;
 } class SearchEngine {
 Observable search(Observable s){ … } } class SearchPresenter {
 void attachView(SearchView v){ searchEngine.search(v.searchIntent()) .subscribe(v::showResult) } }

Slide 96

Slide 96 text

No content

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

No content

Slide 99

Slide 99 text

No content

Slide 100

Slide 100 text

-Someone Smart „If you like the code you have written a year ago you haven’t learned enough this year“

Slide 101

Slide 101 text

REFERENCES • https://github.com/reactjs/redux • http://facebook.github.io/flux/ • https://www.youtube.com/watch?v=uNZnftSksYg&t=757s • https://github.com/bkase/cyklic • http://cycle.js.org/

Slide 102

Slide 102 text

THANK YOU QUESTIONS? hannesdorfmann.com @sockeqwe