Skip to content

Trendyol/transmission

Repository files navigation

Transmission

Abstraction experiment. Kotlin library to create a communication network between different business logic blocks for your Android Projects.

Motivation

Business logic can accumulate for complex screens in Android quite quickly.

Business logic is abstracted to some controller class, UseCase, or something similar to control and maintain the complexity.

However, the reactive nature of the data we present on the screen often prevents us from genuinely decoupling this logic. For example, in scenarios where one part of the screen controls another, they must be updated together.

This library brings an additional layer to this complexity, intending to decouple the business logic blocks from each other.

You can read more about motivation and how the library works here.

Installation

The library is distributed through Jitpack.

Add the repository to the root build.gradle

repositories {
	maven { url("https://jitpack.io") }
}

Add the library to the dependencies block of your app's module build.gradle (And any module you need to use)

implementation("com.github.Trendyol:transmission:<latest_version>")

How to use it?

The library consists of the following building blocks:

  • Transmission: Unit of information being transferred. Three subtypes are: signal, effect, and data.
  • Transformer: Processes transmission. Might receive signal or effect and might produce either an effect or data.
  • TransmissionRouter: Processes incoming signals and effects and passes along the produced data. Responsible for distributing the signals and effects between Transformers.

Transmission interactions are depicted below:

graph TD;
	Signal --> Effect
	Signal --> Data
	Effect --> Data
	Effect --> Effect

How to create a Transformer

Transformers are responsible for handling signals and effects. They have an inner class called TransmissionHataHolder which can hold any Data type that is extended from Transmission.Data. Any update to the dataHolder automatically publishes the latest version to Data Channel.

class InputTransformer @Inject constructor() : DefaultTransformer() {

	private val holder = buildDataHolder(InputUiState())

	init {
		registerComputation<WrittenInput> {
			delay(1.seconds)
			WrittenInput(holder.value.writtenText)
		}
	}

	override val signalHandler = buildTypedSignalHandler<InputSignal> { signal ->
		when (signal) {
			is InputSignal.InputUpdate -> {
				holder.update { it.copy(writtenText = signal.value) }
				publish(effect = InputEffect.InputUpdate(signal.value))
			}
		}
	}

	override val effectHandler = buildGenericEffectHandler { effect ->
		when (effect) {
			is ColorPickerEffect.BackgroundColorUpdate -> {
				holder.update { it.copy(backgroundColor = effect.color) }
			}
		}
	}
}

How to use TransmissionRouter

Possibly in your ViewModel:

init {  
    transmissionRouter.initialize(onData = {}, onEffect = {})    
}

The TransmissionRouter takes a set of Transformers as a parameter. Building the Router heavily depends on your app's architecture and dependency injection choices. Here is an approach from the sample app using Hilt:

@InstallIn(ViewModelComponent::class)  
@Module  
interface FeaturesModule {  
  
    @Multibinds  
    fun bindTransformerSet(): Set<DefaultTransformer>  
  
    @Binds  
    @IntoSet    
    fun bindInputTransformer(impl: InputTransformer): DefaultTransformer
  
    @Binds    
    @IntoSet    
    fun bindOutputTransformer(impl: OutputTransformer): DefaultTransformer  
  
    @Binds    
    @IntoSet    
    fun bindColorPickerTransformer(impl: ColorPickerTransformer): DefaultTransformer  
  
    @Binds    
    @IntoSet    
    fun bindMultiOutputTransformer(impl: MultiOutputTransformer): DefaultTransformer
  
    companion object {  
       @Provides  
       fun provideRouter(
           transformerSet: @JvmSuppressWildcards Set<DefaultTransformer>
       ): DefaultTransmissionRouter {
          return TransmissionRouter(transformerSet)  
       }  
    }  
  
}

License

This library is released under the MIT license. See LICENSE for details.