Half way to clean architecture - Dmytro Voronkevych - Droidcon Berlin

Post on 14-Apr-2017

176 views 2 download

Transcript of Half way to clean architecture - Dmytro Voronkevych - Droidcon Berlin

HALF WAY TO CLEAN ARCHITECTURE

BADOO

BADOO

• 100K lines

BADOO

• 100K lines

• 185 Activities

BADOO

• 100K lines

• 185 Activities

• 23 Services

BADOO

• 100K lines

• 185 Activities

• 23 Services

• 4 Whitelabels

BADOO

• 100K lines

• 185 Activities

• 23 Services

• 4 Whitelabels

• 4 Applications

NETWORK

CACHE

ACTIVITY

EVENT BUS

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

EVENT BUS

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS

NETWORK

CACHE

ACTIVITY

EVENT BUS

ACTIVITY

ACTIVITY

ACTIVITY

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

NETWORK

CACHE

ACTIVITY

EVENT BUS SERVICE

GLOBAL LISTENER

— Decomposition rule? ;)

DIVIDE AND CONQUER

HelperContract

Controller

Facade

Provider

Delegate

Wrapper

PresenterBuilder

Factory

Cache

Handler Task

View

Strategy

Adapter

Loader

STANDARDISE

CLEAN ARCHITECTURE

LAYERS

LAYER 1

LAYER 2

LAYER 3

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

MODEL 2

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

MODEL 2

MODEL 3

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

MODEL 2

MODEL 3

PRESENTATION

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

MODEL 2

MODEL 3

PRESENTATION

DOMAIN

LAYERS

LAYER 1

LAYER 2

LAYER 3

package layer1

import layer2 import layer3

package layer2

import layer1 import layer3

package layer3

import layer1 import layer2

MODEL 1

MODEL 2

MODEL 3

PRESENTATION

DOMAIN

DATA

Farm Layer Transportation Layer Consumer Layer

Farm Layer Transportation Layer Consumer Layer

Farm Layer Transportation Layer Consumer Layer

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA REPOSITORY

REPOSITORY (DATA LAYER)

REPOSITORY

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query)

void remove(query)

void insert(item)

void update(item) }

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query) }

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query) }

CreateUserQuery

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query) }

CreateUserQuery

RemoveUserQuery

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query) }

CreateUserQuery

RemoveUserQuery

UpdateUserQuery

REPOSITORY (DATA LAYER)

REPOSITORY

interface Repository {

Observable query(query) }

CreateUserQuery

RemoveUserQuery

UpdateUserQuery

SelectUserQuery

QUERY

QUERYCreateUserQuery(id, name, gender)

QUERY

interface Query {

boolean equals(other)

int hashCode() }

CreateUserQuery(id, name, gender)

QUERY

interface Query {

boolean equals(other)

int hashCode() }

CreateUserQuery(id, name, gender)

Map<Query, Result>

QUERY

interface Query {

boolean equals(other)

int hashCode() }

CreateUserQuery(id, name, gender)

Map<Query, Result>

Map<Query, Execution>

REPOSITORY (DATA LAYER)

REPOSITORY

REPOSITORY (DATA LAYER)

REPOSITORY

MEMORY DATA SOURCE

REPOSITORY (DATA LAYER)

REPOSITORY

MEMORY DATA SOURCE

FILE DATA SOURCE

REPOSITORY (DATA LAYER)

REPOSITORY

MEMORY DATA SOURCE

FILE DATA SOURCE

NETWORK DATA SOURCE

REPOSITORY (DATA LAYER)

REPOSITORY

MEMORY DATA SOURCE

FILE DATA SOURCE

NETWORK DATA SOURCE

SINGLETON

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA

USE CASE

USE CASES (DOMAIN LAYER)

SESSION

USE CASES (DOMAIN LAYER)

SESSIONSingle<Session> login(id, pass)

Completable logout()

USE CASES (DOMAIN LAYER)

SESSIONSingle<Session> login(id, pass)

Completable logout()

REPOSITORY

USE CASES (DOMAIN LAYER)

SESSION

REPOSITORY

logout()

USE CASES (DOMAIN LAYER)

SESSION

REPOSITORY

logout()

delete

USE CASES (DOMAIN LAYER)

SESSION

REPOSITORY

MESSAGES

logout()

delete

clear

USE CASES (DOMAIN LAYER)

SESSION

REPOSITORY

MESSAGES

REPOSITORY

logout()

delete

clear

delete

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA

LAYERS

LAYER 1

LAYER 2

LAYER 3

PRESENTATION

DOMAIN

DATA

MVP

MVP (PRESENTATION LAYER)

PRESENTER

VIEW

MODEL

MVP (PRESENTATION LAYER)

PRESENTER

VIEW

MODELUSE CASE(S)

MVP (PRESENTATION LAYER)

PRESENTER

VIEW

MODEL

interface LoginPresenter {

interface View { void showError(visible, code); void showProgress(visible); void showSuccess(); }

void onUserLogin(name, pass); void onUserAttemptedRetry(); }

USE CASE(S)

VIEW

VIEW

CLEAN PRESENTER

VIEW

CLEAN PRESENTER LEGACY PRESENTER

VIEW

CLEAN PRESENTER LEGACY PRESENTER

MOCK PRESENTER

PRESENTER

PRESENTER

DIALOG VIEW

PRESENTER

DIALOG VIEW TOAST VIEW

PRESENTER

DIALOG VIEW TOAST VIEW

SNACKBAR VIEW

RISKS

RISKS

• Might not work

RISKS

• Might not work

• Overcomplicated

RISKS

• Might not work

• Overcomplicated

• Too slow

RISKS

• Might not work

• Overcomplicated

• Too slow

• Boring

COST

COST

• Learning curve

COST

• Learning curve

• Refactoring cycles

COST

• Learning curve

• Refactoring cycles

• Differences in ideas

COST

• Learning curve

• Refactoring cycles

• Differences in ideas

• Have fun, never deliver :)

BENEFITS

BENEFITS

• Testability

BENEFITS

• Testability

• Standardisation

BENEFITS

• Testability

• Standardisation

• Code separation

BENEFITS

• Testability

• Standardisation

• Code separation

• Maintainability

SAFELY

HOW WE MIGRATED

SAFELY

HOW WE MIGRATED

• Discuss

SAFELY

HOW WE MIGRATED

• Discuss• Assign 2 people

SAFELY

HOW WE MIGRATED

• Discuss• Assign 2 people• Never rewrite everything

SAFELY

HOW WE MIGRATED

• Discuss• Assign 2 people• Never rewrite everything• Keep old code to revert

SAFELY

HOW WE MIGRATED

• Discuss• Assign 2 people• Never rewrite everything• Keep old code to revert• Discuss

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

• Follow ups

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

• Follow ups• Code reviews

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

• Follow ups• Code reviews• Tutorials

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

• Follow ups• Code reviews• Tutorials• Samples

SPREAD THE KNOWLEDGE

CODE IS NOT ENOUGH

• Follow ups• Code reviews• Tutorials• Samples• Tech talks

@badootech

@openzloy

HTTPS://TECHBLOG.BADOO.COM

Danke!https://github.com/badoo/Chateau