Cómo mejorar la organización y mantenibilidad de tu código Android con la arquitectura MVI

Avatar
4 min lectura

La arquitectura MVI, o Modelo-Vista-Intérprete, es un patrón de diseño utilizado en desarrollo de aplicaciones Android que busca mejorar la organización y mantenibilidad del código.

En esta arquitectura, la vista se encarga de mostrar los datos al usuario y recibir sus interacciones, mientras que el modelo es el encargado de contener los datos y la lógica de negocio.

El intérprete, por su parte, es el encargado de interpretar las acciones del usuario y comunicarlas al modelo para que éste actualice la información y notifique a la vista.

Esta estructura nos permite separar nuestro código en componentes más pequeños y reutilizables, lo que facilita la lectura y el mantenimiento del código.

Además, al utilizar un flujo unidireccional de datos, evitamos el acoplamiento y la complejidad que puede surgir en aplicaciones con estructuras de datos anidadas y complejas.

Ejemplo de MVI en Android

Un ejemplo de código en Kotlin utilizando esta arquitectura sería el siguiente:

// Vista
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.state.observe(this, Observer { state ->
            // Actualizar la vista con los datos del estado
        })

        button.setOnClickListener {
            // Enviar acción al viewModel
            viewModel.sendAction(Action.ButtonClicked)
        }
    }
}

// ViewModel
class MainViewModel : ViewModel() {
    private val _state = MutableLiveData<State>()
    val state: LiveData<State> = _state

    fun sendAction(action: Action) {
        // Interpretar acción y actualizar el estado
        when (action) {
            is Action.ButtonClicked -> {
                // Actualizar datos del estado y notificar a la vista
                _state.value = state.copy(counter = state.counter + 1)
            }
        }
    }
}

// Modelo
data class State(val counter: Int)

sealed class Action {
    object ButtonClicked : Action()
}

La clase MainActivity se encarga de mostrar la información del contador y enviar una acción al viewModel cuando se hace clic en el botón. La clase MainViewModel interpreta la acción y actualiza el estado del contador, notificando a la vista para que ésta muestre la información actualizada.

La clase MainActivity contiene una instancia del viewModel MainViewModel y se suscribe al estado de éste mediante un observador. Cuando se hace clic en el botón, se envía una acción al viewModel mediante el método sendAction().

El viewModel MainViewModel contiene una instancia de un objeto mutable MutableLiveData que representa el estado del contador. Cuando se envía una acción al viewModel, éste interpreta la acción y actualiza el estado del contador mediante el método copy(). Finalmente, se notifica a la vista para que ésta muestre la información actualizada.

El modelo se define mediante la clase State que contiene la información del contador y la clase Action que define las acciones que pueden ser enviadas desde la vista al viewModel. En este caso, sólo se define una acción llamada ButtonClicked que representa el clic en el botón.

Charla de Gema Socorro sobre MVI

En el evento de Architect Coders que organizamos en septiembre de 2022, Gema dio una charla impresionante sobre esta arquitectura.

Si te interesa el tema, te recomiendo que la revises:

¿Sustituirá MVI a MVVM en Android?

Aunque ambas arquitecturas buscan mejorar la organización y mantenibilidad del código en aplicaciones Android, cada una tiene sus propias características y ventajas.

MVI se caracteriza por utilizar un flujo unidireccional de datos que evita el acoplamiento y la complejidad en estructuras de datos complejas. Además, al separar el código en componentes más pequeños y reutilizables, facilita la lectura y el mantenimiento del código.

Por otro lado, MVVM se caracteriza por utilizar el patrón Observador para notificar a la vista de cualquier cambio en el modelo. Esto permite a la vista actualizarse de manera automática sin necesidad de tener que escribir código para actualizarla manualmente.

Ambas arquitecturas tienen sus propias ventajas y desventajas y la elección de una u otra dependerá del contexto y necesidades del desarrollo de la aplicación.

MVI y MVVM no son mutuamente excluyentes y se pueden utilizar en conjunto en una misma aplicación si así lo requiere el diseño.

Conclusión

En resumen, la arquitectura MVI es un patrón de diseño muy útil en desarrollo de aplicaciones Android, ya que nos permite organizar y mantener nuestro código de manera más eficiente.

Su estructura basada en componentes separados y su flujo unidireccional de datos nos permiten evitar el acoplamiento y la complejidad que pueden surgir en aplicaciones con estructuras de datos complejas.

Utilizando este patrón, podemos desarrollar aplicaciones más mantenibles y escalables en el tiempo.