Slide 1

Slide 1 text

DESIGNING FOR DEVELOPERS Ty Smith uber.github.io @tsmith

Slide 2

Slide 2 text

Building for Developers Ty Smith uber.github.io @tsmith

Slide 3

Slide 3 text

Overview — Developer Product Research — Developer Usability Focuses — Library Quality Standards — Best Practices for Releases — Managing Communities @tsmith

Slide 4

Slide 4 text

Product Research @tsmith

Slide 5

Slide 5 text

Standard product workflow @tsmith

Slide 6

Slide 6 text

Developer Tool workflow @tsmith

Slide 7

Slide 7 text

People Need Focus @tsmith | https://twitter.com/marcos_placona/status/882487720597237760

Slide 8

Slide 8 text

Expertise Bias @tsmith

Slide 9

Slide 9 text

Product's role in a developer world @tsmith

Slide 10

Slide 10 text

Finding the right job for your product @tsmith | https://hbr.org/2016/09/know-your-customers-jobs-to-be-done

Slide 11

Slide 11 text

Finding the right job for your product @tsmith | https://hbr.org/2016/09/know-your-customers-jobs-to-be-done

Slide 12

Slide 12 text

Finding the right job for your product Crash Reporting -Stability -Time to build features -Insight into instability @tsmith | CC-BY-2.0 - Bill Ward | https://hbr.org/2016/09/know-your-customers-jobs-to-be-done

Slide 13

Slide 13 text

Developer Customers @tsmith

Slide 14

Slide 14 text

Developer Demographics @tsmith | Search Engine Guide

Slide 15

Slide 15 text

Developer Personas Name Role Company Frank CS Student University Betty Founder Seed Startup João Engineer Emerging Market Series A Paul Product Manager Hypergrowth Series C Sharon Staff Engineer Public SV Company Hannah Consultant Enterprise Company @tsmith | https://wiki.mozilla.org/DeveloperExperience/Personas

Slide 16

Slide 16 text

Developer Research — Watch them integrate — Dig into expectations — Survey @tsmith

Slide 17

Slide 17 text

Success Objectives — Developer Productivity — Developer Happiness — Developer Trust @tsmith

Slide 18

Slide 18 text

@tsmith

Slide 19

Slide 19 text

Usability @tsmith | CC-BY-2.0 - Sherman Paggi

Slide 20

Slide 20 text

Autodispose Automatic binding+disposal of RxJava 2 streams. @tsmith | https://github.com/uber/AutoDispose

Slide 21

Slide 21 text

Easy to Integrate dependencies { implementation 'com.uber.autodispose:autodispose:x.y.z' } observable .doStuff() .as(autoDisposable(this)) //<--Here's the magic. .subscribe(s -> ...) @tsmith | https://github.com/uber/AutoDispose

Slide 22

Slide 22 text

Concise observable .doStuff() .as(autoDisposable(this)) .subscribe(s -> ...) @tsmith | https://github.com/uber/AutoDispose

Slide 23

Slide 23 text

Intuitive //-------------------Vanilla RXJava---------------- fun doStuff() { subcription = observable.doStuff().subscribe(s -> ...) } override fun onDestroy() = subscription.unsubscribe() //-------------------Autodispose------------------- observable.doStuff() .as(autoDisposable(this)) .subscribe(s -> ...) @tsmith | https://github.com/uber/AutoDispose

Slide 24

Slide 24 text

Consistency public interface ScopeHandler { @CheckReturnValue Function, FlowableSubscribeProxy> forFlowable(); @CheckReturnValue Function, ObservableSubscribeProxy> forObservable(); @CheckReturnValue Function, MaybeSubscribeProxy> forMaybe(); @CheckReturnValue Function, SingleSubscribeProxy> forSingle(); @CheckReturnValue Function forCompletable(); } @tsmith | https://github.com/uber/AutoDispose

Slide 25

Slide 25 text

Composition public interface ObservableSubscribeProxy { Disposable subscribe(); Disposable subscribe(Consumer onNext); ... TestObserver test(); ... } @tsmith | https://github.com/uber/AutoDispose

Slide 26

Slide 26 text

Resilient and Defensive @Override public ObservableSubscribeProxy apply(final Observable upstream) { return new ObservableSubscribeProxy() { @Override public Disposable subscribe() { return new AutoDisposeObservable<>(upstream, scope).subscribe(); } ... }; } @tsmith | https://github.com/uber/AutoDispose

Slide 27

Slide 27 text

Flexibility public interface LifecycleScopeProvider { Observable lifecycle(); Function correspondingEvents(); E peekLifecycle(); } @tsmith | https://github.com/uber/AutoDispose

Slide 28

Slide 28 text

Flexibility dependencies { implementation 'com.uber.autodispose:autodispose-android:x.y.z' implementation 'com.uber.autodispose:autodispose-android-archcomponents:x.y.z' implementation 'com.uber.autodispose:autodispose-kotlin:x.y.z' implementation 'com.uber.autodispose:autodispose-rxlifecycle:x.y.z' } @tsmith | https://github.com/uber/AutoDispose

Slide 29

Slide 29 text

Testability dependencies { implementation 'com.uber.autodispose:autodispose-android-archcomponents:x.y.z' testImplementation 'com.uber.autodispose:autodispose-android-archcomponents-test:x.y.z' } TestLifecycleOwner lifecycle = TestLifecycleOwner.create(); subject.as(autoDisposable(from(lifecycle))).subscribe(o); lifecycle.emit(Lifecycle.Event.ON_CREATE); ... lifecycle.emit(Lifecycle.Event.ON_DESTROY); subject.onNext(1); o.assertNoMoreEvents(); @tsmith | https://github.com/uber/AutoDispose

Slide 30

Slide 30 text

Debugability public final class AutoDisposePlugins { public static void lockdown() { lockdown = true; } public static void setOutsideLifecycleHandler( @Nullable Consumer handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } outsideLifecycleHandler = handler; } } @tsmith | https://github.com/uber/AutoDispose

Slide 31

Slide 31 text

Documentation /** * Entry point for auto-disposing streams from a {@link ScopeProvider}. *

* Example usage: *


* Observable.just(1)
* .as(AutoDispose.autoDisposable(scope))
* .subscribe(...)
* 
* * @param provider the target scope provider * @param the stream type. * @return an {@link AutoDisposeConverter} to transform with operators like * {@link Observable#as(ObservableConverter)} */ public static AutoDisposeConverter autoDisposable(final ScopeProvider provider) {...} @tsmith | https://github.com/uber/AutoDispose

Slide 32

Slide 32 text

Example Code @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Using automatic disposal, this should determine that the correct time to // dispose is onDestroy (the opposite of onCreate). Observable.interval(1, TimeUnit.SECONDS) .doOnDispose((value) -> { Log.i(TAG, "Disposing subscription from onCreate()")) }) .as(autoDisposable(from(this))) .subscribe((value) -> { Log.i(TAG, "Started in onCreate(), running until onDestroy(): " + num); }); } @tsmith | https://github.com/uber/AutoDispose

Slide 33

Slide 33 text

@tsmith

Slide 34

Slide 34 text

Quality Primum non nocere @tsmith

Slide 35

Slide 35 text

Quality Stability @tsmith

Slide 36

Slide 36 text

Performance @tsmith

Slide 37

Slide 37 text

Size @tsmith| source: https://www.youtube.com/watch?v=CVQ8cg_WIwY

Slide 38

Slide 38 text

Data usage @tsmith

Slide 39

Slide 39 text

Transitive Dependencies @tsmith

Slide 40

Slide 40 text

@tsmith

Slide 41

Slide 41 text

Releases @tsmith

Slide 42

Slide 42 text

Semantic Versioning - X.Y.Z Decimal Use Example X - Major API Change Changed Public Method Name Y _ Minor Feature Added New Functionality Z - Patch Fix Fixed Crash @tsmith

Slide 43

Slide 43 text

Changelogs @tsmith

Slide 44

Slide 44 text

Deprecation — Be thoughtful about introducing new APIs — Respect semantic versioning — Mark methods as deprecated — Set expected timeline or version for removal — Incentivize updates @tsmith

Slide 45

Slide 45 text

Deprecation /** * Extension that proxies to [Observable.as] + [AutoDispose.autoDisposable] */ @Deprecated( level = ERROR, message = "Replaced with autoDisposable() to match top level APIs.", replaceWith = ReplaceWith("autoDisposable(scope)", "com.uber.autodispose.kotlin.autoDisposable") ) @CheckReturnValue inline fun Observable.autoDisposeWith(scope: Maybe<*>): ObservableSubscribeProxy = this.`as`(AutoDispose.autoDisposable(scope)) @tsmith | https://github.com/uber/AutoDispose

Slide 46

Slide 46 text

Community @tsmith | CC-BY-4.0 - Billie Grace Ward | http://uk.droidcon.com/skillscasts/11019-open-source-and-building-communities

Slide 47

Slide 47 text

Issues @tsmith

Slide 48

Slide 48 text

Contributors @tsmith

Slide 49

Slide 49 text

Wrap up — Developer Product Research — Developer Usability Focuses — Library Quality Standards — Best practices for Releases — Managing Communities @tsmith

Slide 50

Slide 50 text

BUILDING FOR DEVELOPERS Ty Smith uber.github.io @tsmith