Architecture question: Mutating data classes in Kotlin Flow

Hey everyone!
I have a question regarding updating/changing Kotlin data classes in a Flow. A shortened version of my data class looks like this:

data class MediaDevice(
    val name: String?,
    val model: String?,
    val identifier: UUID?,
    val location: URL?
)

A list of these classes is produced in a Kotlin Flow like so:

fun myMethod(): Flow<List<MediaDevice>> {
    return startDoingStuff()
            .someMap()
            .someOtherMap() // Here the result is a List<MediaDevice> for final return
}

Some initial information will be created in the flow, for example identifier, but most other fields will have to come from the endpoint located at location. The idea is to query the location endpoint via Ktor or OkHttp and then perform a .copy() method on each MediaDevice.

What is the best way to go about this? One thought I had was to add another step (like a map) in the flow and just kick off the endpoint calls, or is there a better approach? Thanks in advance!

If you have different data in different parts of your code, use different data classes to represent that different data.

data class MediaDeviceRequest(
    val identifier: UUID
    val location: URL
}

data class MediaDevice(
    val name: String,
    val model: String
)

Don’t be afraid to create classes. Several classes that each accurately define the data needed for some part of the code is much easier to understand than one class that could be/mean anything. Let the type system work for you by defining data as non-nullable in the places where it can’t be null and not bothering to define the property at all for places where that data is non known yet.

3 Likes

Hmmm this does give me an idea - thanks a bunch! So, just to maybe explain what I’m thinking, this project is for SSDP and some information comes from a socket, whilst a lot of other stuff comes from the XML endpoint. As a result, I can have something like (class names are just for post purposes):

data class SocketMediaDevice(
    val uuid: UUID?,
    val location: URL?
)

and then, I can have another model, which will be populated from the endpoint:

data class XMLMediaDevice(
    val modelName: String?,
    val modelNumber: Int?
)

and then just offload the XML request to the user space (at their request). I still need to have nulls, however, since in SSDP every single device/manufacturer just ends up doing whatever they want and not really follow spec. Thanks a bunch for the pointer - this helped!