Skip to content

ReadOnlyBroadcastChannel #532

Closed
Closed
@brettwillis

Description

@brettwillis

Consider the use case when an API/library exposes a channel that will be consumed in multiple locations within an app.

I have implemented this pattern as something like this:

class DataSource {
    private val _data: BroadcastChannel<Data> = ...
    
    // Public API
    val data: ReceiveChannel<Data>
        get() = _data.openSubscrption()
}

This is risky, as it is not obvious to consuming code that data returns a new channel instance which must be cancelled every time.

Another way is like this:

class DataSource {
    private val data: BroadcastChannel<Data> = ...
}

Now it is obvious what is happenning, because the consuming code must call openSubscription() itself. However, the downside is that consuming code can close or even inject elements into the BroadcastChannel which may break the API.

I propose to create ReadOnlyBroadcastChannel<E> and then modify BroadcastChannel<E> to inherit from ReadOnlyBroadcastChannel<E>, like so:

interface ReadOnlyBroadcastChannel<E> {
    fun openSubscription(): ReceiveChannel<E>
}

interface BroadcastChannel<E>: ReadOnlyBroadcastChannel<E>, SendChannel<E>  {
    ...
}

This way the library API can become like this:

class DataSource {
    private val _data: BroadcastChannel<Data> = ...
    
    // Public API
    val data: ReadOnlyBroadcastChannel<Data> = _data
}

Now, the BroadcastChannel is safe from being modified by client code (of course it can still be type-cast...), and the usage of the api is clearer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions