This review of Kotlin Multiplatform Guidelines is going to focus on the project architecture and design aspect.
The motivation for project modularization
Kotlin Multiplatform makes it possible to maintain a project containing a code shared across different target platforms such as backend, web frontend, Android and iOS apps, and more. That’s why such multiplatform projects require a high level of modularization:
To achieve a satisfying level of code reusability
To provide a clean architecture for a big and complex project
There are various advantages for sharing the code between different targets. In the case of common backend - frontend code the profit is the consistency of data models which are being used for data communication. For the Android, iOS and web frontend all those targets can share a business logic layer responsible for things like user inputs detecting and handling, network communication, data processing, data persisting. The UI layer should be implemented for each platform individually.
There might be also a need to extract some additional multiplatform code into a module containing utility functions and generic types models required by other different project modules. They can be extracted and kept outside the project and linked as external multiplatform dependencies.
The need for modules versioning
In order to make the simultaneous development of the various platform-related modules possible there is a need to introduce versioning of the common (shared) modules.
Let’s consider the following example of a project containing 3 modules: A, B, C, where the A consists of a shared business logic code consumed by B and C platform-related modules.
The B and C modules are using A module dependency internally. The shared code from the A module is compiled to the target platforms accordingly (e.g. jar file for Android, framework or static library for iOS) and linked to the final product. Whenever there are some changes made to the API exposed by the A module and pushed to the master branch there is a need to adapt the B and C modules immediately in order to allow the whole project to be built. As the result, if the B and C modules are tightly coupled withthe latest A module state the project is impossible to maintain as a whole. To make the development more flexible the changes made to the A module should be released as the versioned artifacts without a need to adopt all the dependent modules immediately.
Modules versioning in action
Publishing to Maven local repository
Kotlin-multiplatform Gradle plugin cooperates well with the standard Gradle maven-publish plugin:
apply plugin: 'maven-publish'
// Publication metadata
The config above is sufficient to provide painless versioning and publication of the module artifacts locally. The modules artifacts are published under the local maven repository directory (~/.m2).
Publishing artifacts to maven-local repository is perfect for new modules versions development and testing.
Publishing to Bintray repository
When the new version of a module is ready to be released it’s time to upload it to an external repository. This is required to allow integrating the new module release in other layers of the project and to make the project build successfully on CI.
While working with the projects under the Kotlin Everywhere working group we are using Bintray repository to upload ready artifacts. The following publish-bintray.gradle script is applied to each of the project modules.
The upload is invoked using ./gradlew bintrayUpload command. Which handles building the project, generating the correct artifact, and finally, uploading it to the Bintray maven repository.
In order to provide a documentation for the APIs exposed by modules the KDoc can be used https://kotlinlang.org/docs/reference/kotlin-doc.html.
Multiplatform library artifact architecture
Kotlin-multiplatform plugin allows building shared libraries for the following set of platforms:
Java VM - standard .jar file
Android VM - At the moment (Jan 2019) there is an issue with generating .aar Android libraries using kotlin-multiplatform plugin and some hacks are required to implement it (more details are available under the following link: https://youtrack.jetbrains.com/issue/KT-27535 )
Kotlin/Native (iOS, x86, STM32 targets) - The .klib package is generated for the native platforms like iOS. Klib native library artifact can be linked to other kotlin-multiplatform and platform-native modules. More info here: https://kotlinlang.org/docs/tutorials/native/working-with-klib.html
Kotlin-multiplatform plugin integrates seamlessly with maven-publish plugin. It generates proper artifacts for each of the targets defined in module-level build script automatically.