Handling parameter validation

It’s usual practice to validate all kind of data in software engineering. The logic behind validation is quite easy to implement but the main question probably lies with how do you do that efficiently, ensure that there are no invalid data in your calls and DRY.

Let me suggest a way how to handle that efficiently.

First of all you want to validate data as soon as possible (fail fastand hard). Most common place to do that is entries in your system such as Controllers, Facades and etc. It could look something trivial like this:

class Controller {
    public void doAction(Request request) {
        String myBookingId = request.getParam("bookingId");
        new BookingValidator().validateId(myBookingId);
        nextCallInApi(myBookingId);
    }
}

Code looks quite nice and reasonable now, but what happens if I am going to call nextCallInApi from another place? We can add validation check again before that call or we can move our code snippet in the nextCallInApi. Actually this, won’t solve our DRY problem again, consider this example:

    /*
    * Method that contains validation call
    */
    nextCallInApi(myBookingId);

    secondCall(myBookingId);

Now we have to do second validation in secondCall. The problem is evident now: we either have multiple validation calls in most of the methods or we can’t guarantee that data we are getting is valid. So how do you handle this contradicting situation.

Introduce Value Objects or DTOs. Start using them in your call chain as soon as possible and don’t allow them to get in invalid state. Take a look here:

class BookingId {
    private BookingId(String bookingId) {
        this.id = bookingId;
    }

    public static BookingId fromString(String bookingId) {
        if (doesntMatchRegex(booking))
            throw new IllegalArgumentException("Please check format");
        return new BookingId(bookingId);
    }
}

BookingId is immutable value object that once created cannot be changed and before creating it we ensure that it is going to hold valid data. This is perfect to opportunity to make use of factory method pattern:

    public static BookingId fromString(String bookingId) {
        if (doesntMatchRegex(booking))
            throw new IllegalArgumentException("Please check format");
        return new BookingId(bookingId);
    }

Now we can pass BookingId wherever we want and we can be sure that data is going to be valid. Also, we aren’t duplicating any of the validation logic because it’s being executed only in that factory method. If validation logic is complex, of course we can extract it into separate validation class.

The other good thing that we achieved now is that API is more descriptive now - we explicitly say that this is booking id and not some other random string.

One may think that we are going to have lot’s of redundant classes by doing this because sheer number of parameters sometimes can be discouraging. Well, in most cases those parameters are going to be grouped under single Value Object or DTO. If you need a few DTOs to make one call to your API it is good sign that you are not following Single Responsibility principle.

Consider this situation which can be encountered quite often these days with frameworks like Spring MVC:

Loading ....
class Controller {
    public void myControllerAction(MyValueObject valueObject) {
    }
}

Value object is created by external means (framework) and let’s say it is already in invalid state. Personally I would suggest limiting utilization of this approach because it’s hard to control how this object is created and it can result in invalid state. We would end calling some kind of validation logic always before using the object and that would break DRY rule. Well, we could do something like this:

Loading ....
class MyValueObject {
    private String nonValidField;
    private boolean validated;

    public String getNonValidField() {
        doValidation();
        return nonValidField;
    }

    public void doValidation() {
        if (validated) return;
        //... do validation here and throw ...
    }
}

But I wouldn’t recommend this approach because it introduces unneeded complexity that we could avoided by utilizing simple and straightforward Factories.

Situation would be somewhat different if we would like to get back validation result object and return those errors to client. In this case I would return complex exception (read with custom fields) that contains aggregated validation result and later that exception is handled and translated in proper response depending on transport used and format expected.

To conclude, I suggest this approach - use ValueObject or DTO as early as possible in your chain and fail as fast as possible. Simple. Let me know how that works (or doesn’t work) for you or other suggestions :).