[113] lessons from realm

63
DEVELOPING ANDROID LIBRARIES: LESSONS FROM REALM EMANUELE ZATTIN (@EMANUELEZ) DEVIEW, SEPTEMBER 14, 2015

Transcript of [113] lessons from realm

DEVELOPING ANDROID LIBRARIES: LESSONS FROM REALM

EMANUELE ZATTIN (@EMANUELEZ)

DEVIEW, SEPTEMBER 14, 2015

THANK YOU NAVER!

LET me KNOW YOU

WHAT IS REALM?

REALM IS A MOBILE

DATABASE

REALM IS AZERO-COPY

OBJECT STORE

REALM FOR ANDROID WAS FIRST RELEASED ONE YEAR

AGO HERE AT DEVIEW

SOME OF OUR USERS* IN KOREA

* Find out more at http://realm.io/kr/users

WHY WOULD YOU WRITE A LIBRARY?

MODULARITYThe ability to split your code base into several units with well defined interface. This allows to focus on smaller problems, producing more

testable code

REUSABILITYA consequence of modularity. Now you can use that unit again in several

places in your projects or accross several different ones

SHAREABILITYA consequence or reusability. You found a nice way to solve a particular

issue. Why now helping other developers? Get your name out there!

WHY WOULD YOU WRITE AN ANDROID LIBRARY?

▸ UI▸ Looper/Handler▸ Sensors▸ Native code▸ Many more!

WHY WOULD REALM WRITE AN ANDROID LIBRARY?

▸ UI▸ Looper/Handler▸ Sensors▸ Native code▸ Many more!

CHALLENGE 1HOW TO START AN ANDROID

LIBRARY PROJECT?

THE PROBLEMANDROID STUDIO ALLOWS YOU TO:

▸ Create a new Application project▸ Create a new Library project▸ Add a new Application module▸ Add a new Library module

SOLUTION 1From Android Studio:

1. Create a new Application project2. Add a new Library module

3. Remove the Application module

SOLUTION 2From the command line:

android create lib-project -t 1 -k kr.deview.awesomelib -p . -g -v 1.3.0

-t: target (Use android list targets to get a list of target ids)-k: package name-p: path to the project-g: make it a Gradle project (requires SDK >= 19)-v: version of the Android Gradle plugin to use

CHALLENGE 2API DESIGN

SOLUTIONDEFINE WHAT A GOOD API IS

▸ Easy to learn▸ Easy to use, even without documentation

▸ Hard to misuse▸ Easy to read and maintain code that uses it▸ Sufficiently powerful to satisfy requirements

▸ Easy to extend▸ Appropriate to audience

STAND ON THE SHOUDERS OF GIANTS▸ Effective Java 2 by Joshua Bloch

▸ How To Design A Good API and Why it Matters by Joshua Bloch

CHALLENGE 3TESTING

TESTING IS EVEN MORE IMPORTANT FOR LIBRARIES THAN FOR APPLICATIONS

BECAUSE YOU HAVE NO IDEA HOW YOUR CUSTOMERS ARE GOING TO USE IT.

SOLUTION 1PREFER JUNIT41 OVER JUNIT3

1 Because parametric tests will save your life!

SOLUTION 2AUTOMATE ALL THE THINGS!

LET JENKINS BECOME YOUR BEST FRIEND

USEFUL JENKINS PLUGINS

▸ Job Config History▸ Git

▸ Android Emulator▸ Matrix Job2

▸ Junit2

2 It comes preloaded with Jenkins

SOLUTION 3WRITE SAMPLE APPS!

▸ Additional integration tests▸ Showcase how to use your library▸ Validate your core principles

CHALLENGE 4JAR OR AAR?

DO YOU WANT TO SUPPORT ECLIPSE?SHOW ME YOUR HANDS ONCE AGAIN

SOLUTIONUSE AAR

CHALLENGE 5WHERE TO PUBLISH?

SOLUTIONBINTRAY

HOW TO PRODUCE A SOURCE JARtask androidSourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs}

HOW TO PRODUCE A JAVADOC JARandroid.libraryVariants.all { variant -> task("javadoc${variant.name.capitalize()}", type: Javadoc) { description "Generates Javadoc for $variant.name." group 'Docs' source = variant.javaCompile.source ext.androidJar = files(project.android.getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' }}

Bintray also provides a Gradle plugin for the actual publishing

The configuration is not trivial, and in the beginning it might be easier to just do the release manually on the binary website

CHALLENGE 6INTROSPECTION IS SLOW

Sometimes libraries need to be smart behind the scenes to save the user from writing boilerplate code

SOLUTIONANNOTATION PROCESSING

! PROS:

▸ It allows you to write new Java files▸ It happens at compilation time

! CONS▸ It does not allow to modify existing code

▸ It's not very easy to use

SOME VERY cool libraries USE IT!▸ Dagger▸ Butter Knife

▸ AutoValue/AutoParcel▸ Realm

BAD NEWSAndroid does not include the package

javax.annotation.processing

WORKAROUNDCreate two Java sub-projects:

1. annotations (used both by the library and the processor)2. annotations processor

YOU NEED TO INCLUDE THE ANNOTATIONS IN THE JAVADOCandroid.libraryVariants.all { variant -> task("javadoc${variant.name.capitalize()}", type: Javadoc) { description "Generates Javadoc for $variant.name." group 'Docs' source = variant.javaCompile.source source "../annotations/src/main/java" // <-- Remember this! ext.androidJar = files(project.android.getBootClasspath()) classpath = files(variant.javaCompile.classpath.files) + ext.androidJar exclude '**/BuildConfig.java' exclude '**/R.java' }}

CHALLENGE 7SOMETIMES ANNOTATION

PROCESSING IS NOT POWERFUL ENOUGH

! PROS:

▸ It allows you to write new Java files▸ It happens at compilation time

! CONS▸ It does not allow to modify existing code

▸ It's not very easy to use

SOLUTIONBYTECODE WEAVING

! PROS:

▸ It allows to modify existing code ❤▸ It's easier to use compared to Annotation Processing

! CONS▸ You really need to know what you are doing▸ It might look weird in the debugger

TOOLS THAT ALLOW TO DO BYTECODE WEAVING▸ Javassist▸ ASM▸ AspectJ

THANK YOU STEPHANE NICOLAS!https://github.com/stephanenicolas/injects

CHALLENGE 8NATIVE CODE

THE BAD NEWSTHE ANDROID GRADLE PLUGIN

DOES NOT SUPPORT NDK ANYMORE

THE GOOD NEWSGOOGLE IS DEVELOPING AN

EXPERIMENTAL NEW PLUGIN THAT SUPPORTS NDK

HOW TO START USING ITbuildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle-experimental:0.2.0' }}

apply plugin: 'com.android.model.application'

THE DSL IS SLIGHTLY DIFFERENTmodel { // <-- This! android { compileSdkVersion = 22 // Now it's a property, not a method buildToolsVersion = "22.0.1" // Same here and the rest of the example

defaultConfig.with { // Use the with method applicationId = "com.example.user.myapplication" minSdkVersion.apiLevel = 15 // Use the apiLevel property targetSdkVersion.apiLevel = 22 // Same here versionCode = 1 versionName = "1.0" } }}

FIND OUT MORE ABOUT IThttp://tools.android.com/tech-docs/new-build-system/gradle-

experimental

ONE ANNOYING LIMITATIONNO SUPPORT FOR CREATING AND DEPENDING ON STATIC

LIBRARIES

THANK YOU!

REALM 부스에 많이 방문해주세요!

오늘만 열어요