five android architecture

103
Intro to Five Architecture 29.09.2016@Five #IzSveSnage [email protected] Or zero to clean…. Tomislav Homan, Five

Upload: tomislav-homan

Post on 15-Apr-2017

205 views

Category:

Engineering


1 download

TRANSCRIPT

Intro to Five Architecture

29.09.2016@Five #[email protected]

Or zero to clean….

Tomislav Homan, Five

Overview● Earlier fails

● General Clean Architecture

● Clean Adjusted for Android

● Is it better?

● No code, just philosophy

Software Architecture ● “Intellectually graspable” abstraction of a complex system (wiki)

● (which helps us plan, design and construct software)

Software Architecture ● “Intellectually graspable” abstraction of a complex system (wiki)

● Multitude of stakeholders

● Separation of concerns - one reason to change

● Run away from the real world (Android, DB, Internet)

● Testability

● SRP + Testability + … = Maintainability, Scalability, etc...

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

NOT testable

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

NOT testable

Stakeholders?

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

NOT testable

Stakeholders?

SRP?

The olden times - God activitypublic final class UsersActivity extends ListActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask<Void, Void, Void> {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

// MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);

// showData(user);

return null;

}

}

}

NOT testable

Stakeholders?

SRP? Mixed with

Android!

The olden times - MVP● Better

The olden times - MVP● Better

The olden times - MVP● Better

The olden times - MVP● Better

SRP

The olden times - MVP● Better

SRP Testable-ish

The olden times - MVP● Better

SRP Testable-ish

Stakeholders?

The olden times - MVP● Better

SRP Testable-ish

Mixed with

Android!Stakeholders?

The olden times - MVP + Managers● Sorta OK

Manager this

Manager that

The olden times - MVP + Managers● Sorta OK

Manager this

Manager that

SRP - meh ok

The olden times - MVP + Managers● Sorta OK

Manager this

Manager that

SRP - meh ok

Stakeholders

The olden times - MVP + Managers● Sorta OK

Manager this

Manager that

SRP - meh ok

Stakeholders

Mixed with

Android!

The olden times - MVP + Managers● Sorta OK

Manager this

Manager that

SRP - meh ok

Stakeholders

Mixed with

Android!Testable-ish

Tend to be HUGE!!!

The Clean Architecture

The Clean ArchitectureOnion

The Clean Architecture

Ports and Adapters

The Clean Architecture

● Dependency rule

● Abstraction

● Communication between layers

Dependency rule

Dependency rule

Dependency rule

Dependency rule

Dependency rule

Abstraction

Abstraction

Abstraction

All dependencies go to the database

Core of the app

3 tier Clean

All dependencies go to the business layer

Abstraction

Business is the core of the app

Communication

Communication

I

Communication

O

Communication

I

O

Communication

I

O

Communication

I

O

Communication

I

O

Communication

I

O

Communication

I

O

Communication

I

Dependency always pointing inwards

O

Communication

I

Communication can go both inwards and outwards

O

Adjusted for Android

Adjusted for Android

Entities

Entities● AKA Domain Objects, Business Objects

● No interaction with the gritty details, no database, no Internet

● Simple business logic constrained to itself or its children

● Immutable

● No persistence methods (stay tuned)

EntitiesExample: News app

● Category

● Article

● Commercial

EntitiesExample: News app with user subscriptions

● Category

● Article

● Commercial

● User

● Subscription

Use Cases

Use Cases● AKA Interactors, Business Services

● Small piece of business logic acting on one or more entities

● Must be able to describe its job by using common language (no details)

● Don’t skip use cases

Use CasesExample: Transfer money to account use case

● Load two accounts

● Do some validation

● If OK transfer money

● Save the changes

Note the simple common language

Repositories

Repositories● Perform CRUD operations on entities

● Additionally: filtering, aggregate operations, etc…

● Repository is abstract (output port)

● Concrete implementation in outer layers (DAO, API, Cache, Combination)

● Can handle entity’s whole object tree

Presenters

Presenters● Always have accompanied view

● Gather info and send them to view

● Don’t know concrete view implementation (view as output port)

● But tied to its lifecycle

● User input delegated to presenters

● Usually map entities to viewmodels

PresentersExample: Screen showing details of an account - abstraction

View

● onTransactionButtonClicked

● onUserItemSelected

● setUserListPanelVisible

● setGenderBoxEnabled

Presenter

● doTransaction

● selectUser

● showUsers

● activateGenderView

Device

Device● Gritty Android stuff

● NOT Db, Internet or UI - separate component

● Sensors, alarms, notifications, players, etc…

● Define wrappers around Android objects in Device component

● Define interface that wrapper will be implementing in domain component

to serve as an output port

Device

LocationManager

NotificationManager

AlarmManager

MediaPlayer

LocationManagerWrapper

NotificationManagerWrapper

AlarmManagerWrapper

MediaPlayerWrapper

Locations

Notifications

Alarms

Player

Use case 1

Use case 2

Use case 3

Use case 4

Device Domain

DB & API

DB & API● Also access to the real world

● This time real world are a database and the Internet

● Classes such as SQLiteOpenHelper, DbModels, DAOs, Retrofit interfaces

and services, API models, JSON parsers…

● If you are using database only, DAO can implement a repository

● Inner layers use entities, so you should also return entities -> mappers

UI

UI● Android classes used for interacting with user via display

● Fragments, Activities, Adapters, Views, Animations, etc…

● Display logic only

Modules

Modules

Domain

Modules

Device

Modules

Data

Modules

UI (app)

Modules

MVP still here

Is it better?

Is it better?

Manager this

Manager that

SRP - meh ok

Stakeholders

Mixed with

Android!Testable-ish

Is it better?

Manager this

Manager that

Is it better?

Is it better?

Is it better?Use case 1

Use case 2

Use case 3

...

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

Domain

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

DataDomain

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

Device

DataDomain

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

Device

Outer worldDataDomain

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

UI

Device

Outer worldDataDomain

SRP

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Not mixed with

Android!

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Not mixed with

Android!

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Not mixed with

Android!

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!UI designer cares about this

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!UI designer cares about this

UX designer cares about this

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!UI designer cares about this

UX designer cares about this

BA, QA, PM care about this

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!UI designer cares about this

UX designer cares about this

BA, QA, PM care about this

Nobody cares about this

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!UI designer cares about this

UX designer cares about this

BA, QA, PM care about this

Backend guys care about this

Nobody cares about this

Is it better?Use case 1

Use case 2

Use case 3

...

Repository

Location

Notifications

...

SRP

Testable

Not mixed with

Android!Stakeholders

are satisfied

http://five.agency/about/careers/