Validation before or after request model construction

151 views
Skip to first unread message

Jeroen De Dauw

unread,
Nov 18, 2015, 1:50:34 PM11/18/15
to Clean Code Discussion
Apologies if this was already discussed on this list; I cannot find any such threads.

I'm creating a REST API, and have a GetItemUseCase (or GetItemInteractor if you will), which gets invoked when hitting the /items/{id} endpoint. At present, only this id parameter is handled, though later things such as language can be added. I've created a GetItemRequest class to represent this request model. At present its single field is of type string. (Note that the item IDs in my case are not purely numeric.)  Creating that field is the last step I did before asking this question here, as now I'm faced with the question where I want to do the validation of this id. There is an ItemId object, so I could have the GetItemRequest have a field of this type, which then move the responsibility of validation from the use case / interactor to the thing constructing the request model. Any recommendations on where to put such validation?

As a bonus question, I'm wondering about if having a string id in the request model violates some other principles. The request model should not know about the presentation mechanism, though then the string form of the id does not seem presentation mechanism specific in my use case. Another point is to #AlwaysWrapPrimivites, though if that conflicts with the best approach for validation, it probably ends up being significantly less important here. Thoughts?

Christian B

unread,
Nov 19, 2015, 1:52:52 PM11/19/15
to Clean Code Discussion
I was in that situation a lot of times since i do some clean architecture and not depend on crazy hugh validation frameworks.

I see 2 different approaches here:

#1 Validation in entities

For instance:

public class Basket {
    private BasketId id;
    
    public Basket (BasketId id) { this.id = id; }
}

public class BasketId {
    private String value;
    
    public BasketId (String value) throws InvalidArgumentException {
        if (value.equals("")) {  // So here could be the validation
            throw new InvalidArgumentException();
        }
    }
}

public class GetBasketInteractor {
    public void execute(GetBasketRequest request) {
        try {
            BasketId id =  new BasketId(request.basketId);
        } catch (InvalidArgumentException e) {
            // return some error
        }
    }
}

What i think about this:

Pros:

  • Validation in 1 place, nobody can create a broken Basket entity

Cons:

  • I think it violates the Single Responsibility Principle, when more than validation will be added to the BasketId class
  • If there is validation in the Basket entity aswell, and other businessrules too, that certainly violates the SRP
  • Kind of feels weird to try catch a constructor

#2 Validation in Validation classes

public class Basket {
    private BasketId id;
    
    public Basket (BasketId id) { this.id = id; }
}

public class BasketId {
    private String value;
    
    public BasketId (String value) throws InvalidArgumentException {
        this.value = value;
    }
}

public class GetBasketInteractor {
    public void execute(GetBasketRequest request) {
        // Probably injected via dependency injection, but for simplicity..
        validator = new BasketRequestValidator(); // probably composes a lot of single validators like NotEmptyValidator or RegexValidator
        if (validator.isValid(request)) {
            // return some error
        }
    }
}

What i think about this:

Pros:

  • Single Responsibility Principle fulfilled
  • No scary try catch in execute() method
Cons:

  • It is possible to create a broken Basket entity
There is a third option, that is validating in the Usecase Interactor but i think that is not a good place, since the validation might not be reusable.

Jeroen De Dauw

unread,
Dec 8, 2015, 11:18:21 AM12/8/15
to Clean Code Discussion
I've been mulling over this during the past weeks and am still looking for input.

Thanks for your reply Christian! All 3 approaches you listed do the validation in the Interactor or something used by the Interactor. Does this mean you think validation should always happen after the construction of the request model?

One consideration I did not mention in my original post is that when not doing the validation before the construction of the request model, one is probably forced to create a more complicated response model. Rather than having the model be ThisSetOfData, it will now be SomeWrapperThing that contains ThisSetOfData when validation went fine, or SomeKindOfError when it did not. It somehow seems nice to not have to care about such stuff in the interactor.
Reply all
Reply to author
Forward
0 new messages