https://kotlinlang.org logo
#amper
Title
# amper
w

Waldemar Kornewald

11/14/2023, 8:58 AM
Since all of the sample projects in the repo are trivially simple, maybe it could help in the design phase to also think of a more complex real-world use-case. At least, this build system topic has cost us so much time and left me with so many scars that I really want to see it finally solved. I even planned to create an open-source Gradle conventions plugin that solves this, but now you’re working on Amper already, so let’s use the opportunity. 😄 The following is an example similar to our project structure. Here you have several SDKs and apps for different clients with different feature sets: • libs ◦ common (APIs useful for all SDKs and apps; possibly also published as an XCFramework and JS/WASM Node.js lib) ▪︎ base-utils ▪︎ image (APIs for manipulating JPEG, PNG, etc.) ▪︎ pdf (PDF generation) ▪︎ xml (XML parsing) ▪︎ … ◦ foo-sdk (an SDK also published as XCFramework and JS/WASM Node.js lib) ▪︎ core ▪︎ notification ▪︎ profile ▪︎ … ◦ bar-sdk (SDK with XCFramework etc.) ▪︎ … ◦ … (other SDKs, possibly even depending on foo-sdk and bar-sdk) ◦ ui (the reusable UI library) ▪︎ core ▪︎ navigation ▪︎ foo (base UI for foo-sdk) ▪︎ whitelabel-flavor-xyz (a whole reusable app flavor, integrating foo, navigation, login/registration flow etc.) ▪︎ … • apps (Android, iOS, desktop - where some iOS and desktop apps could use a native or Electron UI while others could use Compose) ◦ client-a ▪︎ base (the main app code, building on top of whitelabel-flavor-xyz) ▪︎ app-prod (uses base and just configures the backend URL and other settings) ▪︎ app-dev-env ▪︎ app-test-env ▪︎ … ◦ client-b ▪︎ base (main app code, combining ui/foo and some bar-sdk features in a much more custom way, so whitelabel-flavor-xyz can’t be reused) ▪︎ … ◦ … • backends (reusing some of the
libs/*
APIs) ◦ … Either you develop the app for the client or they build it and integrate either your logic SDKs or ViewModels or your themable UI (or some combination). EDIT: For SDKs it’s important to have a simple way to expose the whole API, similar to the way it works on JVM with just public vs. private. The current JS/WASM export annotations are too painful and the XCFramework
export
build configs are also quite repetitive and error-prone when working with multiple SDKs and many modules. Let’s say there are 100+ modules overall. You need linting, Sonarqube, dependency update and security checks, snapshot and unit tests and code coverage, version consistency (e.g. BOM), API docs with real text and examples (not just Dokka-generated references, but more like Kotlin's docs), assets and translations (at
libs/*-sdk
,
libs/ui
and
apps/*
level, also overriding/customizing values from lower-level modules). Some consumers of your SDKs are allowed to see the source code, others only get the binaries - ideally with integrated API docs. Thus you’d want to keep the configuration as centralized as possible. Settings should ideally be transitive (e.g. iOS pods, webpack customizations, kotlinx.serialization, etc.). They should also be applied from the root and match on certain path patterns or module properties. With too much repetition you’ll lose yourself in complexity and will have a hard time updating configs and finding out how the build system is configured and which outputs there are at all (your different XCFrameworks, apps, etc.). Ideally you don’t have to look at 30 module.yaml files to understand which artifacts get built in the project. Side-problem: Your iOS apps with native UI need to integrate one or multiple XCFrameworks. Your iOS apps are modularized, too. So if foo-sdk and bar-sdk depend on common/oauth, the the iOS app’s modules need to reuse that common/oauth API and be able to pass objects to both foo-sdk and bar-sdk. That’s a huge problem because with the current build system SDKs become separate XCFrameworks/WASM/JS libs with their own incompatible copy (!) of common/oauth. So the resulting XCFrameworks/WASM/etc. need to be built and published in a modularized way somehow and this should ideally even work across multiple repos. I hope this is a useful example for discussing Amper’s solution. Is this even a use-case Amper wants to serve? Maybe a tiny similar project in the samples would be helpful, too (I think a lot of problems in the current Gradle based build system would’ve been avoided with such a more complex example).
s

Stylianos Gakis

11/14/2023, 9:13 AM
A great list of things to consider! Seeing this, I do wonder if Amper’s goal is in fact to be a solution for such vast situations too, or if Amper is trying to solve smaller scale problems? I’d love to hear more from Jetbrains regarding this.
a

Alexander Tsarev

11/14/2023, 2:29 PM
First, thanks a lot for the description of something real life scaled and complex, thats a nice example of what to target. Answering about templates - we had chosen this explicit approach (specifying in dedicated section) to avoid confusion about any implicitness. But this is subject to change (according to feedback). And about if we will support such cases - we will try out best, for sure 🙂
w

Waldemar Kornewald

11/15/2023, 5:29 PM
Sounds good. I’m curious to see your next iteration 🙂
2 Views