Hi all! For those of you using gitportal in bi-dir...
# touchlab-tools
b
Hi all! For those of you using gitportal in bi-directional mode (for android and ios), I'm curious if/how you've ever had to answer the question, "does this affect the other platform too"? Say for example a defect gets filed due to some issue in the iOS app. The product team knows that we're leveraging KMP, so one of their first questions is, "Is this in the android app too?". Bidirectional mode makes the two applications VERY independent, due to it's "eventual consistency" model. So I don't think that question could be answered easily. The only real answer would be "I don't know, I'll have to go look at the android project and see if the code is in there". Is that a fair assessment, or is there something I'm missing? One advantage of pre-compiled binaries is that they are versioned, so I can very quickly and easily tell what version of the code is in each app. I think gitportal in unidirectional mode would also facilitate answers to these kinds of questions (though there is still some ambiguity there). Anyway, I'm just trying to evaluate the pros and cons of the different ways to setup KMP for our projects, and the above was one of the things that crossed my mind. I haven't used bidirectional mode extensively (yet), so I'm not certain that the above scenario is valid/accurate, so I wanted to ask the group.
k
I think gitportal in unidirectional mode would also facilitate answers
Unidirectional mode is versioned just like binaries, so it would be the same.
On the question in general, you'd need to find the source of the bug in Android and see if those changes had been merged to iOS or not.
Bidirectional mode makes the two applications VERY independent
Only if you let them. It's tooling, but process needs to be defined.
Forgetting gitportal specifically for a moment, the core analysis that needs to happen is understanding the issues that various KMP dev models will run into, and deciding for your team if those issues are sufficient to introduce the process complexity of "eventual consistency".
BTW, I am overdue on publishing an updated KMMBridge model that helps achieve a decoupled team workflow, similar in concept to GP bidirectional. It uses branches instead of versions for publishing. Not ideal, but kind of bridges the gap for teams who don't want to actually shared code and build locally. It wouldn't technically solve the problem you're asking about here, though. Again, that's team process rather than tools.
Anyway, the KMP workflow issues are related to team size, who edits KMP, and how often. Publishing a versioned binary is equivalent to publishing a versioned library. That's the model. Libraries have significantly higher burdens of API testing and stability than does code in a repo. Imagine if, say, ktor was undergoing a heavy refactor, and the team decided that they would make no effort to keep the public API stable, and they would publish minor versions arbitrarily directly from main (or their dev branch, or whatever). It wouldn't be great.
Now, zooming in, imagine an Android app. Forget KMP. You have your screens and view models in one repo, and you edit them at the same time. Those changes get pushed as PRs and reviewed. Now, imagine you pulled all of the view model logic out of that repo, put it in a different repo, and published with versions. You'd have PRs on the view model code, which would be merged and published, then the PR on the UI code against that published version. One dev? OK. Two? Well, maybe multiple view model PRs were merged and published in a version, but the UI code PR only has the changes from one dev. Whatever was in the other dev's PR isn't there, and could easily have broken other UI code that's in the UI PR of the first dev. Small teams "figure it out" by chatting on slack or whatever. Now imagine 10 devs, and two relatively siloed platform teams. Chaos.
So, library publishing mechanically restricts what's feasible to use KMP for. Self contained libraries. Because, versioned builds are how libraries work.
It's just not the right model.
I have an updated version of GP that's mid-flight, as I think the current version of bidirectional is a bit too opinionated. At the core, the whole concept is just a branching model to decouple the KMP so the two teams don't have to constantly chat with each other and release in lockstep. (Edit: to clarify, here I'm talking about moving to a monorepo)
Some team managers I've talked to said they explicitly want the two teams to be in lockstep, do a lot of pair coding, etc. OK. My only reply to that, is, that's a process decision. Before you radically change how current teams work, in a way that isn't reversible, try it now. That could just be the process the team is required to follow. See how it goes. A lot of my content on teams is aimed at team leads and managers making plans for KMP, and the golden rule is if you wouldn't do something without KMP, it might not be a good idea with KMP. With the library example, if you want to use KMP to build your view model code and publish libraries, before you do that, force the native teams to start doing that with their existing codebases. It'll be rough. With the monorepo idea, and the benefits of teams in lockstep, there's nothing stopping two native teams from trying that without KMP. If it's a good idea, why aren't they doing it already? It's a lot easier to change tech than human nature, if I may stretch the concepts I'm presenting. Anyway, I'm rambling 🙂
b
Thanks for all the info @kpgalligan! We have 2 (mobile app) dev teams. Each team works on both the android and iOS applications. I think "lockstep" is a little bit too strong of a word for how we work on the 2 apps. A team gets a feature and is tasked to implement it in both apps. In that sense we do try to keep them "in lockstep". But, we aren't overly concerned with it, to the point that we'll wait to release until both apps are ready. It's not that uncommon that to implement a feature say in the ios app, the team might need to do some refactoring of some architecture piece or something, while the android app doesn't need any of that. The ios work takes much longer. That's ok. When we're done with the feature for android, we'll test and release it (and then start work on the next feature, or address some tech debt etc). And then we'll release the feature in the ios app whenever it's done. So, we're definitely not big sticklers for lockstep, but we do try to keep them loosely "in sync". Our web teams have been working with the library model for years. They have a system where it works, but having worked in that world myself, it certainly has it's pitfalls. I would not be excited about using published binaries (a library) for our mobile apps. In addition to the other pitfalls, it also keeps the kotlin code as a "black box" for the ios devs, and doesn't encourage them to get involved in that part of the code. And having used gitportal in unidirectional mode a little it, I like how it's compiled source approach enables ios devs to do "real" debugging, stepping through source code, etc.
I'm really thinking the GP unidirectional mode might work pretty well for us. I've used it a little bit on my own, so I'm familiar with it. I may need to work out some CI details to enforce editing rules that work for our teams. But I think it'll allow the team(s) to have some freedom and flexibility to work on and share code for a feature at their own pace (i.e. not in lockstep), but also enforce some rules so that a release (the master branch) is always done on a specific version (tagged). And with a little bit of github actions creativity, I can log/publish release notes for each app that detail which version (tag) of the kmp code the app release was done with. 🤞
k
Our web teams have been working with the library model for years.
I guess my question here would be what code they use a library model for? It's not all-or-nothing on the mobile end either. For a simple mental model, the further from the screen, the easier it is to use a library model. In mobile, things that work well: • Networking code. Changes to the server API are not on the mobile team's timeline, and the API is fixed and defined by somebody else (generally). That very much is "library code" by definition. • Some logic modules. An example would be like a big tax calculation engine. It needs to be correct, so writing it twice is not a great idea. Changes to app screens really don't impact the tax library, except if maybe there's something a screen needs that isn't yet implemented. You probably don't want everybody editing the tax code when they feel like it. • Local db logic. Arguably this is impacted by app feature code. However, changes are less frequent, and in the case of sqlite specifically, and schema-based DB's in general, they are themselves versioned linearly. You can't just "merge" version 47 of the db from one branch and another branch. • Analytics. It's a weird one, but usually analytics is externally defined (this button should send this string), they're easy to get wrong (bad copy/paste from a spreadsheet, wrong case, etc), and I haven't met a dev who loves doing it. A typed library is usually preferred. That is in contrast to, say, view model code, or middle logic that sits right beneath the view model. That can change significantly in different PRs. Having that in versioned libraries is rather difficult. So, what code the web team puts in libraries matters. Say they're using React. If they kept JSX code in one repo, with pretty much no logic, and all JS/TS logic, including code that supports things the JSX needs and that changes with screen changes, well, I mean they could, but I can't imagine why they would. If they have server call logic or similar in libraries, that's the same thing as above.
That's the core distinction I've been trying to explain (blog posts, talks, etc), and it's kind of hard for some reason. Some code works as library code. Some does not. Not well, anyway. It is why virtually all existing teams that introduce KMP to existing apps generally stop with things like server calls and similar and don't get to view-support code. It's just not reasonable to do with libraries.
OTOH, I have found talking about this with teams who have tried get the concept immediately 🙂
b
For our mobile apps, the idea we're shooting for is to keep Views and ViewModels as native swift/android code, along with other platform specific architecture stuff (like navigation architecture, etc). Everything below the ViewModel layer (so repositories, networking, data storage, etc) goes in the KMP "library". All of the business logic goes there. The concept I'm trying to drive home to my teams is that the KMP library could be used in ANY application to add our business logic/functionality. In addition to our own application, we provide white label versions of it to several third parties. Some of them have already expressed a desire to integrate into their own app and not have to make users have 2 apps. If we build this correctly, we could publish the kmp library binaries, and sell them to these third parties and they could use all of the business logic and all they would need to do is build the UI's that they want to put on it. So in that sense, we DO want to be able to build/publish libraries, and I do have the KMP project setup that way, using KMMBridge. I can build and publish library versions. I can add the libraries as a dependency to our application and use it. We actually have one feature in our app working that way already. It was sort of our pilot/test project. But long term, for our own application, I think the compile source (gitportal) probably works better for our own app development, for all of the reasons that you have previously outlined in the Scaling KMP and Gitportal blog posts. So I think my end goal is probably some version of gitportal (right now I'm leaning toward unidirectional) for our own application, but also publishing precompiled binaries that we can "give" to third parties to integrate our business logic into their own applications.
k
OK. With that context, library makes sense. In my various conversations, the struggle I tend to have is getting people past the mental model of KMP code as "the KMP library". If the code being written checks the boxes of "library", then it can work well in a library. If it doesn't, then it won't. But, often, KMP is "the KMP library" first, and then teams attempt to do things with KMP that are extremely difficult as a library. It's a concept that is obvious outside of the KMP context, but somehow when KMP is in the mix, the model of it as primarily a library overrides why that will be a struggle.
In any case, there's a delayed post about an alternative model using KMMBridge. It's sort of a middle ground between "traditional" KMMBridge/binaries (and all of the bad parts of that), and sharing source and using a bidirectional flow.
It's not complicated. You can use KMMBridge and the xcode-kotlin plugin with published binaries, and debug them: https://touchlab.co/spm-kotlin-debugging. That changed the situation considerably. You can't directly edit the code that way, but it removes one of the major things I disliked about publishing binaries. The other part is publishing SPM to branches instead of versions, which removes one of the major problems of the library model when trying to do dev that shouldn't be a library. The workflow makes much more sense if the KMP code "lives" in the Android repo, and is consumed by iOS as a binary, but it's not necessarily required to work that way. In addition, if the goal was to have a separate library for some consumers, and to share "feature code" for the core app, the core app code would pull in the library code as a KMP dependency, then publish its own iOS framework. You'd almost certainly need/want different framework builds in that kind of situation anyway.
GitPortal has an in-flight refactor, which removes a lot of the bespoke git code and simplifies the mechanics. It also uses git submodules, but in an indirect way (I.E. the devs wouldn't need to interact with submodules directly), but my technical focus has shifted considerably over the past month+. Crazy UI stuff...
So, I don't know if/when the updated GP would see daylight. One only has so much time.
b
Interesting. I'll take a look at that post.
thanks for all your help an efforts on this stuff! I'm not sure KMP would really be a viable option at the enterprise level without all of your great work and tools.
gratitude thank you 1