MVVM seemed simple. Then you added ten MutableStateFlow properties to your ViewModel. MVI promised purity. Then you wrote a middleware for side effects. There’s a better way. The Problem With MVVM A typical ViewModel looks like this: class ProfileViewModel : ViewModel () { val name = MutableStateFlow ( "" ) val email = MutableStateFlow ( "" ) val isLoading = MutableStateFlow ( false ) val error = MutableStateFlow < String ?>( null ) fun updateProfile ( name : String ) { viewModelScope . launch { isLoading . value = true try { profileService . update ( name ) this @ProfileViewModel . name . value = name } catch ( e : Exception ) { error . value = e . message } finally { isLoading . value = false } } } } Enter fullscreen mode Exit fullscreen mode Five mutable properties. Loading state scattered across three places. Error handling duplicated in every method. And the ViewModel doesn’t own its side effects — viewModelScope does.…