KMP Architecture: Share the Contract, Keep the Platform Details
The first difficult Kotlin Multiplatform decision is often not how much code to share. It is where platform behavior should enter the shared code. Take an article reader that opens an external link. Android needs an appropriate Context and intent. iOS needs its own application APIs. Shared presentation logic only needs to request an action and handle its outcome. That is a useful place for a…
The biggest challenge in Kotlin Multiplatform projects is determining which code should be shared across platforms. The key is to identify where platform-specific behavior should be introduced within the shared codebase. For instance, when handling external links, Android requires a Context and intent, while iOS needs its own application APIs. The ideal place to define a small contract is where the caller's needs intersect with platform-specific requirements.
This contract can be encapsulated in a shared module, such as the `OpenLinkResult` enum class and the `ExternalLinkOpener` interface. The `OpenLinkResult` enum defines two possible outcomes: `Opened` or `Unavailable`, while the `ExternalLinkOpener` interface specifies a suspend function to open a URL and return an `OpenLinkResult`.
Additionally, a `ArticleActions` class can be created within the shared module, which takes an instance of `ExternalLinkOpener` as a parameter and provides a `openSource` function to handle opening an external link.
By following this approach, the shared module only exposes the necessary capabilities without leaking platform-specific details like Android Context or iOS application objects. Developers can then define how these capabilities are implemented on each platform, such as creating an Android `AndroidLinkOpener` or an iOS `IOSLinkOpener` and passing them to an instance of `ArticleActions`.
This design ensures that platform-specific thread requirements, lifecycle handling, and native error translation are managed within the adapter layer, keeping the shared module focused on its core responsibilities.
In summary, when designing a Kotlin Multiplatform project, start by defining a clear contract within the shared module, keeping platform-specific behavior at the boundaries. This allows for a more maintainable and portable codebase, with platform-specific implementations focusing on their respective native ecosystems.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.