https://kotlinlang.org logo
c

Colton Idle

05/27/2021, 9:27 PM
Curious what you all would name this sort of class/method in Kotlin/compose The gist is that I have a class that can convert a domain model to a composable
Copy code
class DomainToComposeConverter {
    @Composable
    fun from(domainModel: MyDomainModel) {
Now I don't think this is really idiomatic kotlin/compose because 1.
from
breaks the rule "Composable functions that return Unit should start with an uppercase letter" 2. Would this be better as an "object"/singleton or do you all think that this should just be an extension function on
MyDomainModel
?
d

dimsuz

05/27/2021, 9:35 PM
Why would you make this kind of function
Composable
? Isn't the architecture layer mapping functions simply... mappers? Like one data class is the input, another is the output -> plain old function 🙂
c

Colton Idle

05/27/2021, 9:36 PM
So MyDomainModel is actually an interface and depending on a value in the interface the "converter" knows which composable to convert it to. Sorry for not calling that out before hand, but yeah I'm basically dealing in a system that I won't really know until runtime what types of composables I will need to draw on the screen.
d

dimsuz

05/27/2021, 9:42 PM
To me this sounds a bit like on overabstraction, but not sure. In our codebase we simply have domain module to have
Copy code
fun SomeStorageDbModel.toDomainModel() = SomeDomanModel(field1 = this.fieldX + 3)
and call where appropriate. Our UI module has
Copy code
fun SomeDomainModel.toUiModel() = SomeUiModel(text = this.field1.format())
In each place where we call those functions we know input layer and output layer, so no need for "clever" tricks. But maybe I'm driving this conversation in different direction, sorry. You didn't ask about architecture.
a

Adam Powell

05/27/2021, 9:48 PM
what does "convert" mean in this context? is it just emitting UI for the given
MyDomainModel
?
c

Colton Idle

05/27/2021, 9:53 PM
So this is basically what it's doing. It's converting based on the Type that it actually is
Copy code
class DomainToComposeConverter {
    @Composable
    fun from(domainModel: MyDomainModel) {
        when (domainModel) {
            is Type1 -> { return MyComposable1(it.value)}
            is Type2 -> { return MyComposable2(it.value)}
            is Type3 -> { return MyComposable3(it.value)}
so basically in my fragment I have
things = List<MyDomainModel>,
and then I have a
Copy code
Column {
  things.forEach{
    DomainToComposeConverter().from(it)
  }
}
a

Adam Powell

05/27/2021, 9:55 PM
I assume that doesn't actually need
return MyComposable1
etc.
the
return
part anyway since this is all
Unit
in any case this is the sort of thing I'd expect to be just a top-level
Copy code
@Composable
fun MyDomain(domainModel: MyDomainModel) {
name the composable function for the UI entity it represents when composed, not for its processing of specific parameters
c

Colton Idle

05/27/2021, 9:58 PM
Interesting. Okay. I'll see if I can make that work. Basically what I'm doing is what Airbnb is doing here

https://youtu.be/f8j4CqImf0U?t=483

I linked to the timestamp in that video.
"We're just using one fragment" So that's basically where I'm at where I'm mocking out all of my items in my Column to essentially just be a base type called BaseType (Airbnb calls them "Row") and then I just need to convert them, hence the
when
statement.
a

Adam Powell

05/27/2021, 10:00 PM
sure I get it, I'm taking issue with the proliferation of verbs in a declarative context. 🙂
as well as what looks like an unnecessary object instance
c

Colton Idle

05/27/2021, 10:08 PM
@Adam Powell that worked! It seems so simple/straightforward of a solution now. I don't know how I didn't think about that before. I got rid of the class. I just have a Composable now that takes in the interface type, and depending on the type, just calls the right composable to create internally. Removed all return statements too. I knew something seemed off. Thanks for your advice. It looks much better now. 😄
👍 1