https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
a

adam-mcneilly

09/26/2019, 3:25 PM
Hey y'all, if I have an Android project that's using Room, and I wanted to put some of these model objects into the shared library, I run into some issues because of some of the annotations like ignore/embedded/etc. Would you: 1) Keep the data classes in the Android app and just write a mapping method to parse MPP models? 2) Add the room annotations as
expect
values in the MPP and then typealias it to the real thing? I got that idea from seeing how this post handled parcelize:
<https://aakira.app/blog/2019/04/kotlin-mpp-android-parcelable-en/>
2️⃣ 1
Mainly the problem is if I replace a model object that had another model nested inside, Room doesn't know how to save it. Here's what I have now:
Copy code
data class User(
  @Embedded val location: Location
)

data class Location(
  @Embedded val details: LocationDetails
)
If I swap out Location, room yells at me.
l

Lou Morda

09/26/2019, 4:09 PM
i would say 2 or some other method, def want to keep the data classes shared right? also just interested why not use sqldelight for both platforms, or is it only using sql caching in android side?
a

adam-mcneilly

09/26/2019, 4:14 PM
I certainly think that would be the end goal, I'm just looking at how MPP integrates into my current projects. So for now I might actually just remove the room implementation so I can play around with sharing model classes (none of this is getting merged it's just exploratory). That's not a bad thing if I end up using sqldelight though because I'll have to get rid of it anyways. 🙂
j

Jeremy

09/26/2019, 6:34 PM
1) I generally separate models into dto (json, db) and ui. Android is view layer and should have different models anyways to avoid coupling 🤷‍♂️
Mapping also does translation like : fname, mname, lname fields into a single name field like "John H. Doe"
a

adam-mcneilly

09/26/2019, 7:30 PM
Is there really a point then? Why write once if I'm just gonna rewrite a new data class myself?
j

Jeremy

09/26/2019, 7:47 PM
If you are using exactly the same data class from db/network/ui then no
That can be a thorny path though 🤷‍♂️
a

adam-mcneilly

09/26/2019, 7:49 PM
So you would have three different
User
entities that serve different purposes, but in many cases may be the same? 🤔
j

Jeremy

09/26/2019, 7:50 PM
Generally yes but they usually aren't the same. The UI model is usually different than what comes from JSON and decoupling them means they can change independently. The UI model is often a composite of several other models
UI models often have different requirements like formatting etc. that needs to be done somewhere. I try to keep out of view layer like fragment/adapter
a

adam-mcneilly

09/26/2019, 7:56 PM
Yeah I agree. For a lot of our custom components we have an associated ViewModel. So I end up with something like:
Copy code
class UserCardViewModel { 
   private val user: User? = null
}
So I get the abstraction you're talking about for UI stuff. I guess the problem in question now is data. I want a class that I can annotate with room annotations, but that I don't necessarily want to share because iOS doesn't care. So I guess I have to decide if I'd want to pursue a different persistence idea like sqlite or maybe I should have my own implementation of a User that can support being persisted to a database.
j

Jeremy

09/26/2019, 7:58 PM
Yah if you want exactly the same model used for db and ui
What happens if it gets updated to use multiple like: User->Person->List<Addresses>
And UI displays 3 fields : full name, user status, city
a

adam-mcneilly

09/26/2019, 8:03 PM
That's what
UserCardViewModel
would do. The POJO should strictly just have the data I want, and that class is responsible for translating it to something to display inside a card view. But I guess I'm answering my own question now, because the same idea would also apply for persistence. If we don't need both platforms to know about a Room annotation, then maybe just the platform that does should implement it? 🤔 Idk I feel like it can go either way I just might have to pick one and go down the rabbit hole a little bit.
👌 2
Semantic question: Would you use the package names to tell the difference between them, and rely on class comments, or would you consider having
User.kt
and
PersistableUser.kt
?
j

Jeremy

09/26/2019, 8:09 PM
Both generally. I call them "dto" data transfer objects. I put in different packages/modules. Data classes that know about things like json models aren't visible to ios as its implementation detail
Personally I consider data classes that are visible to android/ios part of a public api 🤷‍♂️
When anything in api changes it affects multiple platforms and can possibly break things, need to be aware of what gets exported to objc also
kotlin != objc != swift
a

adam-mcneilly

09/26/2019, 8:14 PM
Yeah, but it just seems like MPP isn't gonna save me a lot of time then. Sure, I can write a KTOR call that returns a user, and that is now written once, but if each platform just maps that user class to their own user class then sooner or later we're not really sharing all that much. 🤔 Maybe I will just have to pick your brain IRL the next time we're both at a meetup here hahaha
j

Jeremy

09/26/2019, 8:18 PM
Yah MPP def has tradeoffs. If you have already drank the clean architecture modular koolaid and are ok w/ the boilerplate its great
But if things aren't strictly modularized won't get the full benefits
l

Lou Morda

09/26/2019, 8:50 PM
Seems like MPP works great if you use something like Ktor + SQLDelight and the same models for db/network/ui? For a simple REST app just showing and saving basic data types, both to a remote server and a local db, i think the koolaid is tastey
j

Jeremy

09/26/2019, 9:36 PM
I drank the clean arch koolaid before mpp 😆
You can def share models as long as there is no jvm dependencies
Just be careful and aware of how it will translate to ObjC
l

Lou Morda

09/26/2019, 9:40 PM
interesting... ok cool i will keep an eye out for that. thanks!!
k

kpgalligan

09/27/2019, 2:28 AM
A lot of reading there. In general, sharing a db data object and a json data object is seductive, but they’re not really the same thing, especially as you get into more hierarchical data structures.
I’m not sure why you’d need to translate to data objects per platform if you’re using sqldelight.
If you’re using Room and trying to map something with annotations, and use core data on iOS? Nightmare. You’ll hate life.
👍 1
I’m available to chat this stuff, btw. If you’re seriously taking a look at it, we can sit down and really go over it. Trying to learn how teams are approaching eval.
a

adam-mcneilly

09/27/2019, 1:51 PM
Will let you know. This was our "hackweek" where we get to explore new things that may not ever get published. So I wanted to tackle this. So for the time being I cared less about best practices, but this did help me understand spots in both codebases that are tightly coupled and question how I would do things if I were to start over for example.
k

kpgalligan

09/27/2019, 2:16 PM
Assume the week ends today? Well, if you have questions, ask away 🙂
a

adam-mcneilly

09/27/2019, 2:37 PM
Yes 😂 I was able to get one shared network call and currently just mapping those classes to the corresponding platforms which is a start and good enough for demo day. I learned a lot this week though. Setting it up was a PITA, so was publishing an Android lib, I should probably write about all of my lessons learned here
k

kpgalligan

09/27/2019, 2:40 PM
In our company slack I was just pitching a blog post called “Your KMP hack week” that would start with a project you can clone that will build libraries (or a standalone one). The goal would be getting past that stuff on day 1. I would like to know more about how you’re publishing that android lib. Is that just locally, or to an internal dependency setup?
a

adam-mcneilly

09/27/2019, 2:47 PM
I did it locally. I would like to test putting something in jcenter or bintray. I also don't know the right way to do it on iOS. Right now I'm just referencing the framework on my machine. Is there a way to export KMP to a cocoapod or something similar? I would definitely be willing to help out with that post some time.
k

kpgalligan

09/27/2019, 2:49 PM
With iOS, there are strategies. I think for a hack week, you want to do everything local. Also, I don’t like the idea of publishing something that the iOS devs can’t edit. That can be problematic. However, different places are doing different things.
a

adam-mcneilly

09/27/2019, 2:49 PM
Well the shared library would be in its own repo that iOS devs can submit PRs to, right? Or do you think the right way would be to have one repo with all three projects?
I went the first route because we already had two existing GitHub repos for the two platforms
k

kpgalligan

09/27/2019, 2:50 PM
Tough call. It’ll be situation dependent, most likely. I’m on a call right now with a client trying to walk through how to build with the iOS dev.
a

adam-mcneilly

09/27/2019, 2:52 PM
Let's sync up early next week. Right now I'm trying to put together my demo for this afternoon. I'm also in Michigan for the weekend to volunteer at the hackathon at my alma mater - I'll channel my inner hackathon spirit and throw a sample from the shared lib template on GitHub. I'll throw in some of my initial thoughts, how I'd go about importing that into another project locally, and you can help me smooth out the details.
k

kpgalligan

09/27/2019, 2:56 PM
👍
a

adam-mcneilly

09/27/2019, 3:01 PM
While we're on the topic - a huge thanks to everyone in this thread though and also cc @Kris Wong. Even though I only had a week I would not have gotten as far without the responsiveness of this channel. I learned a lot and while it's probably not something I'm going to push for at OkCupid this is a tool I will definitely keep my eye on moving forward and I'll try to stay active in here too and help more beginners like this. 🙂
🍻 1
👍 1
Oh and @russhwolf deserves a call out in the appreciation notes too. 🙂
❤️ 1