Search code examples
javajava-8fluent

Simplified Java one-liner validation and assignment and return


I want to simplify the following Java 8 block executed on method start:

public void handle(Context ctx) {
    String param = ctx.getParam(name);
    if (!Validation.validate(param)) {
        ctx.markError().end();
        return;
    }
    ... do the same with other params

    ... finally, busines logic on params
}

This is repeated for many params. I would like to be able to write this block more fluently, with less chars as possible, using Java 8 syntax. The problem here is that we have an assignment and method flow breaking (return).

I was looking for something like:

if (Validator.on(ctx).param("instanceId")) return;

however, we are missing an assignment here. I tried to used some Consumer, but param must be (effectively) final. Something like (in sudo):

if (Validator.on(ctx).param("instanceId").into(param)) return;
if (Validator.on(ctx).param("instanceId", value -> param = value) return;

(Note that ctx.end() is wrapped inside).

Of course, this is not working in Java. Any ideas?

NOTE: Im in control of the code, i.e. no 3rd party is used here.

EDIT: If computers could understand plain English, I would say:

Validate parameter name of context; if it is valid, assign it to a param; if not, exit the method. Please :)

EDIT2: It does NOT need to be Java 8! I mean, it is allowed to use Java 8 trickeries, but it is NOT mandatory.


Solution

  • Just use a helper function:

    private static boolean check(Context ctx, String value)
    {
      if (!Validation.validate(value)) {
        ctx.markError().end();
        return false;
      }
      return true;
    }
    

    Usage would look like this:

    String param = ctx.getParam(name);
    if (!check(ctx, param)) return;
    /* Assign and test other variables... */
    /* Use variables... */
    

    The helper function could be given more visibility and moved to another class, as appropriate.

    The helper function could be parameterized with a Predicate to perform custom validation, and a Runnable to perform custom failure handling. (Or Consumer, accepting the value or context; or BiConsumer, accepting value and context.)