Search code examples
javaspringspring-mvcdesign-patternspreconditions

Share same method precondition logic between controllers and services?


I have a Service and a Controller .

Each method in the service its preconditions , for example :

  public void doSomething(Parameter para1 , Parameter para2 ...) {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    // continue do something 
  }

And in the Controller layer , there are two methods , one is showForm() which displays form for user to input ; another is doApplyForm() which accepts form and calls the underlaying Service.doSomething().

The following is the pseudo code (I eliminated some BindingResult , attr.addFlashAttribute codes ) :

  @Injected Service service;

  public String showForm() {
    if ( something wrong ) {
      throw new RuntimeException1();
    }
    if ( another thing wrong ) {
      throw new RuntimeException2();
    }
    return "showForm";
  }

  public String doApplyForm(@Validated Form form) {
    try {
      service.doSomething(para1 , para2 ...);
      return "redirect:/";
    } catch (Exception e) {
      // error handling 
      return "redirect:/error";
    }
  }

It works well , but I am not satisfied. There're bad smells within.

The problem is in the showForm() , which shares identical preconditions with Controller.doSomething() .

If Service.doSomething() add another preconditions in the future , Controller.showForm() has to do correspondent changes.

I wonder if there're any design pattern or frameworks to eliminate such bad smell ?

Java8's functional solutions are welcome.

Thanks.


Solution

  • You can define a util class called Preconditions and move all your validation logic there. It's a common pattern and there are a number of frameworks that make use of it. For example, Guava: Preconditions docs.

    At least like this your if (condition) throw new exception will be capsulated and easier to manage.