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>
}