Infinum Android Talks #13 - Developing Android Apps Like Navy Seals by Ivan Kušt

Preview:

Citation preview

Developing Android apps like Navy Seals

Ivan Kušt, Android team leader

Infinum Android team

How it all began?

How it all began

First steps

• Android plugin for Eclipse

• tests? who needs them

• Activities with > 1k lines

First steps

• no segregation of duties

• no code review

• poor code structure

Aint nobody got time for that

Regression testing?

So what did we do?

• Improved implementation process

• Included testing to development process

• Improved release process and analytics

Implementation process

Working in a team

• git conflicts

• different code styles

• environment switching (test, production)

Working in a team

• bugfixing while developing a new feature

• weekly meetings and progress reports

branching / merging process

Pull Requests

debug staging release

obfuscated no yes yes

logs yes yes no

crash reporting no yes in most cases

Build types

Gradle

• Build types - debug, staging, release

• Product flavors - test API server, production API server

Product flavors

• number of flavours = number of API environments

Build variants

• flavor x buildType

• example productionDebug

• production API

• debuggable, unobfuscated, logs enabled

Model Presenter View

Code architecture

MVP

• a derivative from MVC

• Models and Views never communicate directly

Model Presenter View

View

• Activity, Fragment, View

• propagates UI events to presenter

• exposes methods that control presentation of data

Model Presenter View

Presenter

• middle man between View and Model

• updates the UI - difference to MVC

Presenter ViewModel Presenter

• Activity, Fragment, View

• propagates UI events to presenter

• exposes methods that control presentation of data

View

View

Model

• gateway towards the business logic

• methods for data retrieval

Model Presenter

ExampleshowLoading() hideLoading() setUsernameError() setPasswordError()

LoginPresenterlogin(username, pass)

LoginView LoginModellogin(username, pass, listener)

showLoading() hideLoading() setUsernameError() setPasswordError()

LoginActivityloginPresenter

login(username, pass)

LoginPresenterImplloginView loginModel

LoginModelImpl

login(username, pass, listener)

Testing

Instrument testing

• Robotium, Espresso

• runs on emulator or real device

Unit testing

• Robolectric

• write mock View and Interactor

• unit test Presenter

Dependency injection

• Dagger 2

• https://github.com/reisub/Dagger-2-Example

• simplifies writing tests

• Model / View / Presenter can easily be replaced

Without DI

@Overrideprotected void onCreate(Bundle savedInstanceState) { //... //dependencies loginPresenter = new LoginPresenterImpl(this, new LoginModelImpl());}

LoginView LoginPresenter LoginModel

LoginActivity LoginPresenterImpl LoginModelImpl

With DI

@Overrideprotected void onCreate(Bundle savedInstanceState) { //... //dependencies DaggerLoginComponent.builder() .loginModule(new LoginModule(this)) .build() .inject(this); }

With DI

• decoupling dependencies from implementation

• easier to replace dependencies

• more about Dagger:http://google.github.io/dagger/

Robolectric

• mock Android VM (tests run on desktop machine)

• View doesn’t have to be mocked

• full control of Activity / Fragment lifecycle

• http://robolectric.org/

MockWebServer

• part of OkHttp library

• server that runs on localhost

• responses can be enqueued

• https://github.com/square/okhttp/tree/master/mockwebserver

Mocking network layer

• network layer can be replaced with MockWebServer

• no additional mock classes

Continuous integration

• if not forced, you won’t run tests

Idea

• commit to a branch starts test execution

• CI server clones the repo, compiles and runs tests

• test results are archived and notified via mail / chat

CI servers

• Jenkins

• Travis

• Circle CI

• https://circleci.com/

• works only with GitHub

Static code checks

Findbugs

• http://findbugs.sourceforge.net/

• java.net.URL.hashCode()

Android Lint

• android related checks

• missing translations

• unused drawables

Checkstyle

Releasing and analytics

Infinum Labs

Infinum Labs

• internal app store

• gradle task increments version name

• upload app via web, CLI tool or AS plugin

• library that notifies when new version is available

Analytics

Recap

• Improved implementation process

• Included testing to development process

• Improved release process and analytics

Implementation process

• organise teamwork - git flow

• monitor code quality - pull requests

• one click build - build variants

• code structuring - MVP

Testing

• Unit testing

• Continuous integration

• Static code checks

Releasing and analytics

• internal store for clients

• automatic notification when new version is up

• analytics / crashlytics

• initial project setup takes more time

• steeper learning and onboarding curve

• developing new features initially takes more time to cover the code with unit test

Cons

• confidence in builds(so much that we believe we’re Navy Seals)

• more maintainable code

• regression testing

Pros

Implementation Testing Release Post Release

ArchitectureBuild Types

MVP

Dependency injection

Unit TestsRobolectric

MockWebServer

Manual testsHuman tester

Infinum Notifier lib

AnalyticsGoogle analytics

Crashlytics

Play Store

Ivan Kuštivan@infinum.co

• if you have any questions:

Recommended