DRY • 2 teams with no common language or architecture • Accidental differences resulting in tech debt • The more the codebases diverge the harder it is to maintain and update • We’re spending a lot of time on boilerplate and architecture • Cross platform code is the history of computing
you are attempting to solve • Evaluate your team, app and existing codebase • Code sharing doesn’t make sense for all projects • Avoid HDD and Whataboutisms. Do your own analysis Your App Multi Platform
the first step • Android and iOS developers need to understand basics and tradeoffs of each platform • VIPER, Clean Architecture, MVVM, MVP, MVI are all solving similar problems • We can’t share code until we start breaking down barriers
reduce risk • Integration with underlying platform should be default not exception • Choose the when and what to share. Empower not limit • Reuse one of the supported languages (Kotlin, Swift) Avoid introducing yet another language • Reuse existing skillsets, build tools, IDEs, libraries and tooling
users! They want to go shopping, lose weight, laugh, be entertained, get smarter, spend time with loved ones, go home on time, sleep better, eat good food and be happy Your product is only as good as the experiences it enables people to have
to different targets where virtual machines are not available such as iOS • One dependency: Kotlin stdlib • Memory management via reference counting and GC for cycles
Objective-C binary with header • CocoaPod integration • Common Kotlin code can access iOS platform APIs such as Foundation and UIKit • Ability to utilize all existing abstractions (classes, interfaces, lambdas, exceptions) • Kotlin Native is a library not a framework
Kotlin stdlib is not useful enough on its own • Kotlin MPP introduces expect and actual • expect defined in the common module defines behavior such as fun log(message: String) • actual provides declaration of how to fulfill the request using the platform specific APIs
on each platform • Android tests execute on JVM, iOS tests use xrun • IDE support for unit testing is still incomplete • No mockk support yet, need to create your own Mocks, Stubs & Spys
db: GreetingQueries ) { } suspend fun getGreeting(): Greeting { // check cache first val cache = db.select() if (cache != null) return cache // get from remote val greeting = api.getGreeting() // transform val result = greeting.copy( name = greeting.name.trim().toUpperCase() ) // update cache db.insertOrReplace(result) return result }
Podfile # Either use_frameworks! or use_modular_headers! must be specified. use_frameworks! platform :ios, '12.2' target 'ios-App' do pod 'lib', :path => '../lib' end
Simple in concept, difficult in practice • KN concurrency is not compatible with existing JVM based coroutines • Bridging the two worlds is challenging and can result in runtime errors • Ktor client has open defect where cannot be created on non-main thread (fixed in 1.3.0, Github #1183) • Coroutine Worker (Ben Asher), Reaktive (Badoo)
threads • 2 basic rules: • All mutable state is owned by one thread • All shared state is immutable (frozen) • Immutable data can be shared across threads safety • Only available in Native module
Frozen objects can be freely * shared between threads/workers. * * @throws FreezingException if freezing is not possible * @return the object itself * @see ensureNeverFrozen */ public fun <T> T.freeze(): T
future = worker.execute( TransferMode.SAFE, { "Hello Droidcon”.freeze() }, // producer { } ) kotlin/worker/WorkerTest.kt: (43, 29): kotlin.native.concurrent.Worker.execute must take an unbound, non- capturing function or lambda // bg thread. this will fail it + input
platforms will always be harder than a single platform. There is more surface area • Requires knowledge of Android, iOS and MPP tech • MPP solves some problems and introduces new problems • The community is still figuring out architecture and best practices • Just because things are hard doesn’t mean we shouldn’t do it
adopter phase, its usable but it still has some rough edges • 1st party libs (ktor, serialization), compiler still in beta • Documentation is lacking • The IDE support is still a work in progress • Debugging native code is challenging • No multi threaded coroutines
It provides a library for business logic and backend logic • Kotlin Native compliments the Native SDKs • Flutter is an alternative framework and language (Dart) • Flutter provides an alternative to the Native SDKs • Flutter maximizes code sharing, KN maximizes native platform interop
(Dart) • Integration with brownfield apps is not great (crashes, memory leaks, integration boilerplate, lifecycle issues) • Flutter excels for simple greenfield apps with common UI, small teams • Uncanny valley. Its very hard to provide a seamless experience in a brownfield app
• Prototype and experiment • Discuss with both iOS and Android teams • Be aware of the limitations • Plan your use cases, architecture and team, pick a feature-layer