android10 / Android-CleanArchitecture

This is a sample app that is part of a series of blog posts I have written about how to architect an android application using Uncle Bob's clean architecture approach.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Validating UseCase

chrizzz35 opened this issue · comments

Hi, I want to ask if I create new UseCase AddUser which is like this

public class AddUser extends UseCase<User, AddUser.Params> {

    private UserRepository userRepository;

    public AddUser(UserRepository userRepository, ThreadExecutor threadExecutor, PostExecutionThread postExecutionThread) {
        super(threadExecutor, postExecutionThread);
        this.userRepository = userRepository;
    }

    @Override
    Observable<User> buildUseCaseObservable(Params params) {
        if(params.userName.isEmpty()) {
            // notify presenter that username is empty
        }
        else if(params.password.isEmpty()){
            // notify presenter that password is empty
        }
        else if(params.email.isEmpty()) {
            // notify presenter that email is empty
        }
        else if(params.phone.isEmpty()){
            // notify presenter that phone is empty
        }

        return userRepository.addUser(params.userName, params.password, params.email, params.phone);
    }

    public static final class Params {

        private final String userName;
        private final String password;
        private final String email;
        private final String phone;

        public Params(String userName, String password, String email, String phone) {
            this.userName = userName;
            this.password = password;
            this.email = email;
            this.phone = phone;
        }
    }
}

How to notify presenter if my username, password, email, & phone is empty? Should I throw custom exception each for those validation? I have no idea, since the default return value is Observable<User> But if I solve this by adding custom exception, would I have too many custom exception in my project?

Another approach is to return an object that contains the user (if we had successful addition) or the possible error.

For example
public class SubmissionResult {

    private String mError; 

    private User mUser;

} 

Personally I prefer the approach with the custom exception, but i would not have an exception for every case. I would just different message.

For example
public class AddUserException extends Exception {...}

@Override
Observable<User> buildUseCaseObservable(Params params) {
    List<String> required = new ArrayList<>();
    if(params.userName.isEmpty()) {
        required.add("userName");
    }
    else if(params.password.isEmpty()){
       required.add("password");
    }
    else if(params.email.isEmpty()) {
        required.add("email");
    }
    else if(params.phone.isEmpty()){
        required.add("phone");
    }

   if (required.size() > 0) {
              StringBuilder builder = new StringBuilder();
    builder.append("Required: ");
    for (int i = 0, size = required.size(); i < size; i++) {
        builder.append(required.get(i));
        builder.append(" ,");
    }
    builder.setLength(builder.length()-1); //removes last comma
       throw new AddUserException(builder.toString());
   }

    return userRepository.addUser(params.userName, params.password, params.email, params.phone);
}

I would do the username & password empty validations in the view itself (will not pass the empty username or password to the presenter), only will handle the error response come from UserRepository

@St4B I think SubmissionResult seems good to me, it acts as UseCase's Output right?
With custom exception & message collection (separated by coma), then I assume that I need to parse the message in the presenter. And if I have multiple behaviour for each case, I still need multiple custom exception, to validate the behaviour in the presenter.

@drayan85 If I do the empty validation in the view, does it make become harder to test & violate the clean principle? (Or it's not?)

@chrizzz35 you can do empty string check for username EditText View when the user clicks on login/register button and then you can write the espresso test for register/login button click to test username EditText whether it is empty or not.

@chrizzz35 Why do you need to parse the message in the presenter? I would just show the message of the throwable that was passed in the onError method.

@St4B I'm using TextInputEditText to show specific error by calling setError() to each of TextInputEditText. That's why I need to parse the message.

Example:

view.showUsernameInvalid(msg)
view.showPasswordInvalid(msg)
view.showEmailInvalid(msg)
view.showPhoneInvalid(msg)