2

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.

smallufo
  • 11,516
  • 20
  • 73
  • 111

2 Answers2

1

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.

Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
1

Introduce a parameter object for the service request and put the validation logic into the request object. E.g.

public class DoSomethingRequest {

   private Parameter param1;
   private Parameter param2;


   public void validate(){
       if ( something wrong ) {
           throw new RuntimeException1();
       }
       if ( another thing wrong ) {
           throw new RuntimeException2();
       }
   }

}

Your service will be more easy

public void doSomething(DoSomethingRequest request) {
    request.validate();
}

so the controller

public String showForm() {
    DoSomethingRequest request = ... // obtained somehow
    request.validate();
    // ...
    return "showForm";
}

This encapsulates the service method's preconditions in an object.

René Link
  • 48,224
  • 13
  • 108
  • 140