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