Design pattern for cumulative validation violations
design-patterns, exception, java, validation
Solution
You can do the following:
define an abstract Check class, as follows:
public abstract class Check {
private final List<Check> subChecks = new ArrayList<Check>();
public Check add(Check subCheck) { subChecks.add(subCheck); return this }
public void run(Data dataToInspect, List<Error> errors) {
Error e = check(dataToInspect);
if (e != null) {
errors.add(e);
return;
}
for (Check subCheck : subChecks) {
subCheck.run(dataToInspect, errors);
}
}
// Returns null if dataToInspect is OK.
public abstract Error check(Data dataToInspect);
}
class `Data` is the class holding the data (that needs to be checked). Can be a String, a JSON object, what have you.
class `Error` represents a problem detected in the data should be roughly something like:
public class Error {
private String problem;
public Error(String problem) { this.problem = problem }
public String getProblem() { return problem }
// maybe additional fields and method to better describe the detected problem...
}
You then have code that runs the check against piece of data:
public class Checker {
private final List<Error> errors = new ArrayList<Error>();
private final List<Check> checks = new ArrayList<Check>();
public Checker() {
checks.add(new DateIsParsableCheck().add(new DateIsInTheFurutreCheck());
checks.add(new UrlIsWellFormed().add(new UrlIsAccessible());
checks.add();
..
}
public void check(Data d) {
for (Check c : checks) {
Error e = c.run(d, errors);
if (e != null)
errors.add(e);
}
}
}
Slightly changed my original answer. In the current answer there is the notion of subchecks: if a check called `x` has a subcheck called `y` then the `y` check will run only if the `x` check succeeded. For instance, if the Date is not parseable there is no point to check it it is in the future.
In your case I think that all/most logical check should be sub-checks of a formal check.
Problem
Let's imagine, that we have a process, which accepts data of the following type: ``` {"date":"2014-05-05", "url":"http://some.website.com","counter":3} ``` - This data should be validated formally: value of `date` should be a parseable date, `url` should also conform the normal url syntax. - Also, this data should be validated logically: `date` should be in the future, `url` should be an accessible address, returning `200 OK`. To make it clean, one must separate those two validation routines into different units (classes, utils, whatever). The desired final behaviour, however, must give user clear understanding of ALL violations, that are present in data. Something like: `{"Errors":[ "Specified date is not in the future",//Formal validation failed "Specified URL has invalid syntax"//Logical validation failed ]}` - I have seen some implementations of the required behaviour, but they use those make use of `Error` objects and are full of checks like `Error.hasErrors()` or `error==null`, which does not look elegant. - I have also seen the implementation of `javax.validation`, which gives you all violations on all field at once. Same approach could be implemented for content validation, but I am not sure, that this is the best way to do this. Question: what is the best practice for handling multiple exceptions/violations of various nature? UPD: short digest of answers: collect `Violations`, build an `Exception`, containing their context, cause and description, use an interceptor to render. See reference links from answers: http://beanvalidation.org/1.0/spec/ JSR 303 specification http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html Spring Bean Validation http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html Java EE validation Which Design Pattern To Use For Validation Why not use exceptions as regular flow of control?