It's always your fault. Poznań ADG 2016

Post on 22-Jan-2018

486 views 2 download

Transcript of It's always your fault. Poznań ADG 2016

Android Technical Lead

Applause Inc.

Przemek Jakubczyk

pjakubczyk

@pjakubczyk

1

A guide to make crashproof libraries

It's always your fault

2

Background

At Applause I am responsible for quality

Applause SDK is crash and bug reporting library

shipped to over 1000 customers

SDK works with apps around the world

3

History

Joined 2 years ago to project with no QA

Today ~1800 unit tests covering 3k methods

82% lines covered

Last major problem was support for Marshmallow

4

Other than that over 6 months of no customer complain

How your SDK should look like

Be universal

Work in every provided configuration

Be robust

Work in any environment

Be defensive

5

GRADLE

6

Just use it.

7

because it’s the base for Android build system

Gradle

use simple tricks to protect your

styling

8

android {

resourcePrefix 'applause_'

}

or pass custom values to source

code via DSL

defaultConfig {

resValue "string","applause_library_version”, "$version"

}

Gradle

easier integration with your Groovy

scripts

for example create own distribution

task

task buildAll (

dependsOn: 'assembleRelease',

type: Copy) {

from “build/outputs/”

into “another_path”

}

9

Gradle

10

Not possible :)

Often heard question. How to pass arguments to tasks?

Create new task for each configuration.

Gradle

11

task buildAll (

dependsOn:

["assembleFreeRelease,

assemblePaidRelease"]

)

Gradle

With great power comes great responsibility

Mind the execution time

Common trick is to use VCS for versionNumber, each run takes time

If possible (please!) don’t make http calls - huge delay, timeout, offline?

Use only in tasks, not in build script evaluation.

12

Java

13

Java

catching Exception doesn’t solve problem

often hides real cause

tempting but dangerous

14

try {

network.getClients();

} catch (Exception e) {

// handle exception

}

Java

Null Object Pattern

instead constantly checking for not null

value

15

public interface Api {

void post(String action);

Api NULL = new Api() {

void post(String action){}

};

}

getApi().post(“Works”)

Java

NPE

Null Pointer Exception is the most popular

exception thrown in runtime.

NullObject pattern partially solves the problem.

Use empty objects, collections etc;

16

List<User> fetchUsers(){

try {

return api.getAllUsers();

} catch (IOException e){

return new

ArrayList<Users>();

}

}

Java

Usually library is started by one static method

… and next versions provide more functionality

Init interface becomes complex

17

Java

public static void start(

String baseUrl,

String defaultUser,

String defaultPassword,

boolean cacheRequests,

boolean forceHttps,

int timeout

)

18

Conf conf = new Conf.Builder()

.withUrl(“http://api.github.com”)

.withUser(“pjakubczyk”)

.withPassword(“droidcon2015Krakow”)

.withCache(false)

.withHttps(true)

.withTimeout(15)

.build();

Library.start(conf);

Java

Builder pattern organize configuration

Easier data validation

Pass only parameters user wants

Handling default values

19

Java

methods, fields, constructors

default, private, protected, public

Might sound a bit controversial

I use default or public

A.Reflection

B.Allow developers to override, it’s their responsibility 20

Android

21

Android

View.inEditMode() determines if view is drawn in Android Studio

Usually to disable other components

Let’s invert the usage

22

23

public void onFinishInflate(){

TextView title = findViewById(R.id.title);

if(inEditMode()) {

int count = title.getText().length();

if(count > 30){

title.setTextSize(24.0f);

} else {

title.setTextSize(30.0f);

}

}

}

Android

Build.VERSION.SDK_INT

ApplicationInfo.targetSdkVersion

the library doesn’t know where it’s run

24

Android

usually interface for loading pictures from to web to Widget looks like this:

pictureLoader.load(“url_to_resource”, imageView);

passing arguments extending from View, Activity etc.

often lead to Memory leak

queue is flooded with requests holding all references

25

Android

Android Studio is bundled with great profilers

Use memory usage graph to monitor you cache logic

Use cpu usage graph to monitor your custom views behaviour.

Use network traffic graph to check if your code doesn’t call web for stuff which

suppose to be in cache

26

Android

ProGuard is outstanding tool to shrink code and inject bytecode optimizations

While shipping your code you must either provide:

copy&paste configuration to ProGuard (latest plugin supports auto-configuration)

be transparent to ProGuard.

Configuration vs Transparency?

Transparency!27

Android http://www.methodscount.com/

28

Product Method count

com.squareup.okhttp3:okhttp:3.0.1 2704

io.relayr:android-sdk:1.0.2 5413

io.reactivex:rxjava:1.1.0 4605

com.google.code.gson:gson:2. 1341

com.applause:applause-sdk:3.4.0 5041

com.fasterxml.jackson.core:jackson-databind:2.7.0 10732

com.parse:parse-android:1.13.0 4543

The End

29

License

30

Licence

31

by default you own the copyright

no licence doesn’t conclue you can use it in your project

open code (found online) != open source movement

transferring code goes along with transferring the ownership

Check the licence

Check if it infects yours

(Apache, MIT vs GPL v2, LGPL, BSD)

Thank you

32

A guide to make crashproof libraries

It's always your fault

33