SlideShare a Scribd company logo
1 of 73
Download to read offline
Mobile at Scale
Dor Samet | 19.12.2019
Lessons from taking a startup approach at a big company
● Developer for 6+ years
● Co-founder of the KotlinTLV
community
● Scotch enthusiast
● Android Developer at Booking.com
Machine Learning site
Quick Introduction
Dor Samet
Azrieli
sarona
50+
people
and
growing
opened
2017
only centre
outside of
AMS
ML center
P13N
TLV Center.
Startup
Structured chaos
● Informal
● Small group to coordinate with
● One time zone, one-to-one communication
Startup == “One-Table” Decision Process
1996
Founded in
Amsterdam
in 220+
countries
& territories
29+ million
listings
including
6+ million
listing in homes,
apartments and other
unique places to stay.
43
supported
languages
24/7
customer
service
200+offices
in over
70countries
17,500+
dedicated
employees
1,550,000
room nights
booked
every 24 hours
187
million+
verified
guest reviews
online
17,500+
affiliate partners
145+ million
destination
recommendations
Company
highlights.
30
different
property
types
2005
Became a part of
Booking Holdings
Inc. (then Priceline
Group)
Stakeholders
70+ People
20+ countries
Stakeholders
● Amsterdam
● London
● Shanghai
● New York
● Tel Aviv
Lessons learned.
What will we discuss today?
1. Modules
2. Automatic Checks
3. Experimentation
4. Soft Skills
Modularize
Build time
> 260K methods
Cold start (after clean): ~14 minutes
Incremental build (changes in a few modules up the chain): ~ 3
minutes
Incremental build (changes in one modules): ~700 milliseconds
● Module scopes a certain entity in
the app
● Prepare for the future (instant apps,
fast iterations)
● Makes your gradle build FAST
● Gradle caches what is already built
Why modularization?
Layers - Grouping of module
Current structure:
Presentation
screens
UI Components
AppServices
data, models, etc.
CoreServices
monitoring, localization, network, icons, experiment management, etc.
● Place org.gradle.caching=true
In your gradle.properties file*
● Create a new module
● Develop in the new module
● Include like another dependency
(gradle)
○ implementation
project(path:`yourModuleName`)
How modularization?
● Module scopes a certain entity in
the app
● Prepare for the future (instant apps,
fast iterations)
● Makes your gradle build FAST
● Scale through fast iterations, and
decoupled logic
Why modularization?
Automatic Checks
● Avoid common bugs through
known patterns
○ Syntactically correct code - but isn’t
● Code reviews
○ Only occur once the checks and tests
allow
● Run on CI
○ Asynchronous testing
● Synchronize teams to standards
○ Teams in London, Shanghai, Amsterdam
and Tel Aviv
Why Automatic Checks?
How Automatic Checks?
● Static Analysis tools
○ e.g. Lint
○ Avoid common bugs
○ Push to use company tools
○ Run on CI for asynchronicity
○ Super easy to implement:
Time for some code
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
context.report(
asyncTaskStaticReference, node, context.getLocation(node),
)
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
context.report(
asyncTaskStaticReference, node, context.getLocation(node),
)
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
context.report(
asyncTaskStaticReference, node, context.getLocation(node),
)
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
context.report(
asyncTaskStaticReference, node, context.getLocation(node),
"Do not reference `AsyncTask` in a `static` context, use an object with lifecycle instead"
)
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() {
override fun visitField(node: UField) {
val evaluator = context.evaluator
if (node.isStatic
&& evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false)
) {
context.report(
asyncTaskStaticReference, node, context.getLocation(node),
"Do not reference `AsyncTask` in a `static` context, use an object with lifecycle instead"
)
}
}
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
"MORE_DETAILED_ERROR_GOES_HERE"
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
"MORE_DETAILED_ERROR_GOES_HERE",
Category.CORRECTNESS,
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
"MORE_DETAILED_ERROR_GOES_HERE",
Category.CORRECTNESS,
5,
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
"MORE_DETAILED_ERROR_GOES_HERE",
Category.CORRECTNESS,
5,
Severity.ERROR,
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
"ERROR_STRING",
"MORE_DETAILED_ERROR_GOES_HERE",
Category.CORRECTNESS,
5,
Severity.ERROR,
Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE)
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
" `AsyncTask` in a `static` context might leak memory",
"""`AsyncTask` usually have a reference to one or more `Context` instances
|(e.g. `Activity`) which might leak if a reference is held without a lifecycle.""".trimMargin(),
Category.CORRECTNESS,
5,
Severity.ERROR,
Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE)
)
}
// ..
// ..
}
class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner {
companion object Issues {
@JvmField
val asyncTaskStaticReference = Issue.create(
"async-task-static-reference",
" `AsyncTask` in a `static` context might leak memory",
"""`AsyncTask` usually have a reference to one or more `Context` instances
|(e.g. `Activity`) which might leak if a reference is held without a lifecycle.""".trimMargin(),
Category.CORRECTNESS,
5,
Severity.ERROR,
Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE)
)
}
// ..
// ..
}
Wait a minute…
How Automatic Checks?
● Tests
○ Unit
○ UI automation
○ Manual Regression for critical flows
● Automatic checks are easy to
implement
● Write once
● Runs asynchronously
● Scale through independence
Conclusion Automatic
Checks
Experimentation
Why experimentation?
● Safety net for feature release
● Basis for “Data-Driven” decisions
● Commercial improvement through
metrics
A/B Tests!
Scientific Method!
Hypothesis!
Typical approaches to hypotheses
I have a feeling that placing our app in the
Amazon store is a good idea.
Our CEO wants us to work on a chatbot for
better engagement.
Based on what I saw in our analytics, our
users tend to be younger, so we should
put our app on ads in Instagram.
Build
Create a thing that answers a
hypothesis
Measure
Does it answer my original hypothesis?
Is my target audience correctly
organized?
Learn
Was my hypothesis answered? How can
I improve upon it?
Experimentation
definition
Build
M
easure
Learn
Hypothesis + Success
metrics
I have a feeling that placing our app in the
Amazon store is a good idea. We will
increase user acquisition by at least 10%.
We’ll learn if it’s a good idea.
Our CEO wants us to work on a chatbot for
better engagement. User retention
increased by at least a week. Let’s see if
that’s a good use of our time.
Based on what I saw in our analytics, our
users tend to be younger, so we should
put our app on ads in Instagram.
Segmented audience increased by at least
23%. We’ll see if young users like the app.
Build
Create a thing that answers a
hypothesis
Measure
Does it answer my original hypothesis?
Is my target audience correctly
organized?
Learn
Was my hypothesis answered? How can
I improve upon it?
How experimentation?
if (newFeatureEnabled) {
// new feature code
} else {
// old solution
}
How experimentation?
● Pick a metric
● Segment your audience
● Run the experiment
● Measure results
● Learn and Repeat
Conclusion
experimentation
● Safety net for feature release
● Basis for “Data-Driven” decisions
● Scientific method
● Scale
○ Release controlled features
○ Knowledge
Soft Skills
Soft, but critical skills.
● Build more capable products
● Be humble
● Celebrate differences
● Take ownership
● Take initiative
Soft, but critical skills.
Recap
What did we discuss today?
1. Modules
2. Automated Checks
3. Experimentation
4. Soft Skills
Lessons learned.
Dor Samet
dor.samet@booking.com
Questions?
Dor Samet
dor.samet@booking.com

More Related Content

Similar to Mobile at Scale: from startup to a big company - Dor Samet, Booking.com

TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidCodemotion
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Mahmoud Hamed Mahmoud
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)jeffz
 
Elasticsearch und die Java-Welt
Elasticsearch und die Java-WeltElasticsearch und die Java-Welt
Elasticsearch und die Java-WeltFlorian Hopf
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)Chris Richardson
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackNelson Glauber Leal
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...GeeksLab Odessa
 
Migrating Objective-C to Swift
Migrating Objective-C to SwiftMigrating Objective-C to Swift
Migrating Objective-C to SwiftElmar Kretzer
 
«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...Mail.ru Group
 
Asynchronous Programming at Netflix
Asynchronous Programming at NetflixAsynchronous Programming at Netflix
Asynchronous Programming at NetflixC4Media
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...GITS Indonesia
 
OpenStack Horizon: Controlling the Cloud using Django
OpenStack Horizon: Controlling the Cloud using DjangoOpenStack Horizon: Controlling the Cloud using Django
OpenStack Horizon: Controlling the Cloud using DjangoDavid Lapsley
 
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...WSO2
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Chris Richardson
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureJorge Ortiz
 
Funtional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTFuntional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTVasil Remeniuk
 

Similar to Mobile at Scale: from startup to a big company - Dor Samet, Booking.com (20)

TDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with AndroidTDD and mobile development: some forgotten techniques, illustrated with Android
TDD and mobile development: some forgotten techniques, illustrated with Android
 
Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development Windows Store app using XAML and C#: Enterprise Product Development
Windows Store app using XAML and C#: Enterprise Product Development
 
The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)The Evolution of Async-Programming (SD 2.0, JavaScript)
The Evolution of Async-Programming (SD 2.0, JavaScript)
 
Elasticsearch und die Java-Welt
Elasticsearch und die Java-WeltElasticsearch und die Java-Welt
Elasticsearch und die Java-Welt
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Ajax-Tutorial
Ajax-TutorialAjax-Tutorial
Ajax-Tutorial
 
NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)NodeJS: the good parts? A skeptic’s view (devnexus2014)
NodeJS: the good parts? A skeptic’s view (devnexus2014)
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
 
Migrating Objective-C to Swift
Migrating Objective-C to SwiftMigrating Objective-C to Swift
Migrating Objective-C to Swift
 
«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...«Управление логикой переходов между экранами приложения с помощью координатор...
«Управление логикой переходов между экранами приложения с помощью координатор...
 
Asynchronous Programming at Netflix
Asynchronous Programming at NetflixAsynchronous Programming at Netflix
Asynchronous Programming at Netflix
 
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
Fundamental Node.js (Workshop bersama Front-end Developer GITS Indonesia, War...
 
OpenStack Horizon: Controlling the Cloud using Django
OpenStack Horizon: Controlling the Cloud using DjangoOpenStack Horizon: Controlling the Cloud using Django
OpenStack Horizon: Controlling the Cloud using Django
 
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...
WSO2Con USA 2015: WSO2 Analytics Platform - The One Stop Shop for All Your Da...
 
Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...Futures and Rx Observables: powerful abstractions for consuming web services ...
Futures and Rx Observables: powerful abstractions for consuming web services ...
 
Dynamic C#
Dynamic C# Dynamic C#
Dynamic C#
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
 
Node.js
Node.js Node.js
Node.js
 
Funtional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWTFuntional Reactive Programming with Examples in Scala + GWT
Funtional Reactive Programming with Examples in Scala + GWT
 

More from DroidConTLV

Mobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, NikeMobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, NikeDroidConTLV
 
Doing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra TechnologiesDoing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra TechnologiesDroidConTLV
 
No more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola SolutionsNo more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola SolutionsDroidConTLV
 
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, ClimacellLiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, ClimacellDroidConTLV
 
MVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, LightricksMVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, LightricksDroidConTLV
 
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)DroidConTLV
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaDroidConTLV
 
New Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy ZukanovNew Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy ZukanovDroidConTLV
 
Designing a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, GettDesigning a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, GettDroidConTLV
 
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, PepperThe Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, PepperDroidConTLV
 
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDevKotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDevDroidConTLV
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalDroidConTLV
 
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bisReactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bisDroidConTLV
 
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevelFun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevelDroidConTLV
 
DroidconTLV 2019
DroidconTLV 2019DroidconTLV 2019
DroidconTLV 2019DroidConTLV
 
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, MondayOk google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, MondayDroidConTLV
 
Introduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, WixIntroduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, WixDroidConTLV
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneDroidConTLV
 
Educating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz TamirEducating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz TamirDroidConTLV
 
Constraint-ly motion - making your app dance - John Hoford, Google
Constraint-ly motion - making your app dance - John Hoford, GoogleConstraint-ly motion - making your app dance - John Hoford, Google
Constraint-ly motion - making your app dance - John Hoford, GoogleDroidConTLV
 

More from DroidConTLV (20)

Mobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, NikeMobile Development in the Information Age - Yossi Elkrief, Nike
Mobile Development in the Information Age - Yossi Elkrief, Nike
 
Doing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra TechnologiesDoing work in the background - Darryn Campbell, Zebra Technologies
Doing work in the background - Darryn Campbell, Zebra Technologies
 
No more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola SolutionsNo more video loss - Alex Rivkin, Motorola Solutions
No more video loss - Alex Rivkin, Motorola Solutions
 
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, ClimacellLiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
 
MVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, LightricksMVVM In real life - Lea Cohen Tannoudji, Lightricks
MVVM In real life - Lea Cohen Tannoudji, Lightricks
 
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice NinjaBuilding Apps with Flutter - Hillel Coren, Invoice Ninja
Building Apps with Flutter - Hillel Coren, Invoice Ninja
 
New Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy ZukanovNew Android Project: The Most Important Decisions - Vasiliy Zukanov
New Android Project: The Most Important Decisions - Vasiliy Zukanov
 
Designing a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, GettDesigning a Design System - Shai Mishali, Gett
Designing a Design System - Shai Mishali, Gett
 
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, PepperThe Mighty Power of the Accessibility Service - Guy Griv, Pepper
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
 
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDevKotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
 
Flutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, TikalFlutter State Management - Moti Bartov, Tikal
Flutter State Management - Moti Bartov, Tikal
 
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bisReactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
 
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevelFun with flutter animations - Divyanshu Bhargava, GoHighLevel
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
 
DroidconTLV 2019
DroidconTLV 2019DroidconTLV 2019
DroidconTLV 2019
 
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, MondayOk google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
 
Introduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, WixIntroduction to React Native - Lev Vidrak, Wix
Introduction to React Native - Lev Vidrak, Wix
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGeneBang-Bang, you have been hacked - Yonatan Levin, KolGene
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
 
Educating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz TamirEducating your app – adding ML edge to your apps - Maoz Tamir
Educating your app – adding ML edge to your apps - Maoz Tamir
 
Constraint-ly motion - making your app dance - John Hoford, Google
Constraint-ly motion - making your app dance - John Hoford, GoogleConstraint-ly motion - making your app dance - John Hoford, Google
Constraint-ly motion - making your app dance - John Hoford, Google
 

Recently uploaded

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfjimielynbastida
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 

Recently uploaded (20)

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Science&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdfScience&tech:THE INFORMATION AGE STS.pdf
Science&tech:THE INFORMATION AGE STS.pdf
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 

Mobile at Scale: from startup to a big company - Dor Samet, Booking.com

  • 1. Mobile at Scale Dor Samet | 19.12.2019 Lessons from taking a startup approach at a big company
  • 2. ● Developer for 6+ years ● Co-founder of the KotlinTLV community ● Scotch enthusiast ● Android Developer at Booking.com Machine Learning site Quick Introduction Dor Samet
  • 4. Startup Structured chaos ● Informal ● Small group to coordinate with ● One time zone, one-to-one communication
  • 5. Startup == “One-Table” Decision Process
  • 6.
  • 7. 1996 Founded in Amsterdam in 220+ countries & territories 29+ million listings including 6+ million listing in homes, apartments and other unique places to stay. 43 supported languages 24/7 customer service 200+offices in over 70countries 17,500+ dedicated employees 1,550,000 room nights booked every 24 hours 187 million+ verified guest reviews online 17,500+ affiliate partners 145+ million destination recommendations Company highlights. 30 different property types 2005 Became a part of Booking Holdings Inc. (then Priceline Group)
  • 9. Stakeholders ● Amsterdam ● London ● Shanghai ● New York ● Tel Aviv
  • 10.
  • 11.
  • 13. What will we discuss today? 1. Modules 2. Automatic Checks 3. Experimentation 4. Soft Skills
  • 15. Build time > 260K methods Cold start (after clean): ~14 minutes Incremental build (changes in a few modules up the chain): ~ 3 minutes Incremental build (changes in one modules): ~700 milliseconds
  • 16. ● Module scopes a certain entity in the app ● Prepare for the future (instant apps, fast iterations) ● Makes your gradle build FAST ● Gradle caches what is already built Why modularization?
  • 17. Layers - Grouping of module Current structure: Presentation screens UI Components AppServices data, models, etc. CoreServices monitoring, localization, network, icons, experiment management, etc.
  • 18. ● Place org.gradle.caching=true In your gradle.properties file* ● Create a new module ● Develop in the new module ● Include like another dependency (gradle) ○ implementation project(path:`yourModuleName`) How modularization?
  • 19. ● Module scopes a certain entity in the app ● Prepare for the future (instant apps, fast iterations) ● Makes your gradle build FAST ● Scale through fast iterations, and decoupled logic Why modularization?
  • 21. ● Avoid common bugs through known patterns ○ Syntactically correct code - but isn’t ● Code reviews ○ Only occur once the checks and tests allow ● Run on CI ○ Asynchronous testing ● Synchronize teams to standards ○ Teams in London, Shanghai, Amsterdam and Tel Aviv Why Automatic Checks?
  • 22. How Automatic Checks? ● Static Analysis tools ○ e.g. Lint ○ Avoid common bugs ○ Push to use company tools ○ Run on CI for asynchronicity ○ Super easy to implement:
  • 24. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { }
  • 25. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { }
  • 26. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator } }
  • 27. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { } } }
  • 28. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { } } }
  • 29. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { } } }
  • 30. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { } } }
  • 31. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { context.report( asyncTaskStaticReference, node, context.getLocation(node), ) } } }
  • 32. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { context.report( asyncTaskStaticReference, node, context.getLocation(node), ) } } }
  • 33. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { context.report( asyncTaskStaticReference, node, context.getLocation(node), ) } } }
  • 34. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { context.report( asyncTaskStaticReference, node, context.getLocation(node), "Do not reference `AsyncTask` in a `static` context, use an object with lifecycle instead" ) } } }
  • 35. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. override fun createUastHandler(context: JavaContext): UElementHandler? = object : UElementHandler() { override fun visitField(node: UField) { val evaluator = context.evaluator if (node.isStatic && evaluator.isVariableExtendClass(node, ClassNameConstants.Android.ASYNC_TASK, false) ) { context.report( asyncTaskStaticReference, node, context.getLocation(node), "Do not reference `AsyncTask` in a `static` context, use an object with lifecycle instead" ) } } }
  • 36. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { // .. // .. }
  • 37. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( ) } // .. // .. }
  • 38. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( ) } // .. // .. }
  • 39. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( ) } // .. // .. }
  • 40. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", ) } // .. // .. }
  • 41. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", ) } // .. // .. }
  • 42. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", "MORE_DETAILED_ERROR_GOES_HERE" ) } // .. // .. }
  • 43. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", "MORE_DETAILED_ERROR_GOES_HERE", Category.CORRECTNESS, ) } // .. // .. }
  • 44. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", "MORE_DETAILED_ERROR_GOES_HERE", Category.CORRECTNESS, 5, ) } // .. // .. }
  • 45. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", "MORE_DETAILED_ERROR_GOES_HERE", Category.CORRECTNESS, 5, Severity.ERROR, ) } // .. // .. }
  • 46. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", "ERROR_STRING", "MORE_DETAILED_ERROR_GOES_HERE", Category.CORRECTNESS, 5, Severity.ERROR, Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE) ) } // .. // .. }
  • 47. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", " `AsyncTask` in a `static` context might leak memory", """`AsyncTask` usually have a reference to one or more `Context` instances |(e.g. `Activity`) which might leak if a reference is held without a lifecycle.""".trimMargin(), Category.CORRECTNESS, 5, Severity.ERROR, Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE) ) } // .. // .. }
  • 48. class AsyncTaskStaticReferenceCheck : Detector(), Detector.UastScanner { companion object Issues { @JvmField val asyncTaskStaticReference = Issue.create( "async-task-static-reference", " `AsyncTask` in a `static` context might leak memory", """`AsyncTask` usually have a reference to one or more `Context` instances |(e.g. `Activity`) which might leak if a reference is held without a lifecycle.""".trimMargin(), Category.CORRECTNESS, 5, Severity.ERROR, Implementation(AsyncTaskStaticReferenceCheck::class.java, Scope.JAVA_FILE_SCOPE) ) } // .. // .. } Wait a minute…
  • 49.
  • 50. How Automatic Checks? ● Tests ○ Unit ○ UI automation ○ Manual Regression for critical flows
  • 51. ● Automatic checks are easy to implement ● Write once ● Runs asynchronously ● Scale through independence Conclusion Automatic Checks
  • 53.
  • 54.
  • 55.
  • 56. Why experimentation? ● Safety net for feature release ● Basis for “Data-Driven” decisions ● Commercial improvement through metrics
  • 60. Typical approaches to hypotheses I have a feeling that placing our app in the Amazon store is a good idea. Our CEO wants us to work on a chatbot for better engagement. Based on what I saw in our analytics, our users tend to be younger, so we should put our app on ads in Instagram.
  • 61. Build Create a thing that answers a hypothesis Measure Does it answer my original hypothesis? Is my target audience correctly organized? Learn Was my hypothesis answered? How can I improve upon it? Experimentation definition Build M easure Learn
  • 62. Hypothesis + Success metrics I have a feeling that placing our app in the Amazon store is a good idea. We will increase user acquisition by at least 10%. We’ll learn if it’s a good idea. Our CEO wants us to work on a chatbot for better engagement. User retention increased by at least a week. Let’s see if that’s a good use of our time. Based on what I saw in our analytics, our users tend to be younger, so we should put our app on ads in Instagram. Segmented audience increased by at least 23%. We’ll see if young users like the app. Build Create a thing that answers a hypothesis Measure Does it answer my original hypothesis? Is my target audience correctly organized? Learn Was my hypothesis answered? How can I improve upon it?
  • 63. How experimentation? if (newFeatureEnabled) { // new feature code } else { // old solution }
  • 64. How experimentation? ● Pick a metric ● Segment your audience ● Run the experiment ● Measure results ● Learn and Repeat
  • 65. Conclusion experimentation ● Safety net for feature release ● Basis for “Data-Driven” decisions ● Scientific method ● Scale ○ Release controlled features ○ Knowledge
  • 67. Soft, but critical skills. ● Build more capable products ● Be humble ● Celebrate differences
  • 68. ● Take ownership ● Take initiative Soft, but critical skills.
  • 69. Recap
  • 70. What did we discuss today? 1. Modules 2. Automated Checks 3. Experimentation 4. Soft Skills