Home > Back-end >  KOTLIN How to decrease if conditions by using sealed classes
KOTLIN How to decrease if conditions by using sealed classes

Time:08-31

I have a use-case class which is validating form fields and pass error if it's neccessary. The structure i used make me feel like it's wrong. Do you have any suggestions? How can i decreased the number of if conditions?

UseCase Class

suspend operator fun invoke(userInfo: UserInfo): Resource<Unit> {

    val a = userInfo.name.length < 3
    val b = userInfo.name.length > 10
    val c = userInfo.surname.length < 2
    val d = userInfo.surname.length > 10
     if (a){
       return Resource.Error(type = FormValidationError.NameFieldError(""))
    }
    if (b){
        return Resource.Error(type = FormValidationError.NameFieldError(""))
    }
    if (c){
        return Resource.Error(type = FormValidationError.LastNameError(""))
    }
    if (d){
        return Resource.Error(type = FormValidationError.LastNameError(""))
    }

    return currentUserRepository.insertCurrentUserInfo(userInfo)

}

Resource Class

sealed class Resource<T>(val data: T? = null, val message: String? = null) {
class Loading<T>(data: T? = null): Resource<T>(data)
class Success<T>(data: T?): Resource<T>(data)
class Error<T>(message: String? = null, data: T? = null, val type: FormValidationError? = null): Resource<T>(data, message)

}

FormValidationError Class

sealed class FormValidationError(val message: String? = null) {
   class NameFieldError(message: String?): FormValidationError(message)
   class LastNameError(message: String?): FormValidationError(message) 
}

CodePudding user response:

Sealed classes really have nothing to do with simplifying this code. Since all the if conditions are mutually exclusive, you can switch to using a when expression. Also, you can use ranges with in to reduce the number of cases.

suspend operator fun invoke(userInfo: UserInfo): Resource<Unit> {
    return when {
        userInfo.name.length !in 3..10 -> Resource.Error(type = FormValidationError.NameFieldError(""))
        userInfo.surname.length !in 2..10 ->Resource.Error(type = FormValidationError.LastNameError(""))
        else -> currentUserRepository.insertCurrentUserInfo(userInfo)
    }
}

Is there a reason your Error and Loading states need to be able to return data? If not, you can make your data non-nullable and change your Loading state to an object since it carries no state. The way you have them defined kind of defeats the purpose of having a sealed class. It might as well just be one class because it always has all the possible properties and it makes them nullable. Here's how I'd do it, using a sealed interface in this case since it needs to hold no common state at all:

sealed interface Resource<T> {
    object Loading: Resource<Nothing>
    class Success<T>(val data: T): Resource<T>
    class Error(val message: String? = null, val type: FormValidationError? = null): Resource<Nothing>
}
  • Related