A guide to make crashproof libraries.
Collection of tips and tricks for developers wanted to make better libraries. Based on my professional experience.
2. A guide to make crashproof libraries
It's always your fault
2
3. 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
4. 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
5. How your SDK should look like
Be universal
Work in every provided configuration
Be robust
Work in any environment
Be defensive
5
8. 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"
}
9. 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
11. Create new task for each configuration.
Gradle
11
task buildAll (
dependsOn:
["assembleFreeRelease,
assemblePaidRelease"]
)
12. 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
14. Java
catching Exception doesn’t solve problem
often hides real cause
tempting but dangerous
14
try {
network.getClients();
} catch (Exception e) {
// handle exception
}
15. 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”)
16. 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>();
}
}
17. Java
Usually library is started by one static method
… and next versions provide more functionality
Init interface becomes complex
17
19. Java
Builder pattern organize configuration
Easier data validation
Pass only parameters user wants
Handling default values
19
20. 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
25. 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
26. 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
27. 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
be transparent to ProGuard.
Configuration vs Transparency?
Transparency!
27