java - Reducing if else branches and cleaning code using chain of functions, does it make sense -


i working on legacy code has lots of if/else. can use conditional decomposition and/or guard statements etc. clean it. approach can used create functions out of branches , execute these functions chain , exit first response. wondering if using function chain overkill? views?

my chain looks below. simplified example.

public class requeststatehandler {     private final list<function<requeststateinfo, optional<response>>> handlers = new arraylist<>();      public requeststatehandler() {         handlers.add(requeststateinfo -> xstatevalidator(requeststateinfo));         handlers.add(requeststateinfo -> ystatevalidator(requeststateinfo));         handlers.add(requeststateinfo -> zstatevalidator(requeststateinfo));     }      public response getresponse(requeststateinfo requeststateinfo) {         try {             (final function<requeststateinfo, optional<response>> handler : handlers) {                 final optional<response> response = handler.apply(requeststateinfo);                  if (response.ispresent()) {                     return response.get();                 }             }         } catch (exception e) {             logger.error("some log", e);         }          return getdefaultresponse(requeststateinfo);     }      private optional<response> xstatevalidator(requeststateinfo requeststateinfo) {         final a = requeststateinfo.geta();         if (a.isabc()) {             return optional.of(requeststateinfo.getx());         }          return optional.empty();     }      private optional<response> ystatevalidator(requeststateinfo requeststateinfo) {         if (requeststateinfo.isxyz()) {             final response response = requeststateinfo.getx();             final a = response.geta();             if (a.issomeothertest()) {                 return optional.of(response);             }         }          return optional.empty();     }      private optional<response> zstatevalidator(requeststateinfo requeststateinfo) {         final response response = requeststateinfo.getx();         final a = response.geta();         if (a.issomeanothertest()) {             return optional.of(response);         }          return optional.of(getdefaultresponse(requeststateinfo));     }      private response getdefaultresponse(requeststateinfo requeststateinfo) {         return new response(a.create(requeststateinfo.gety()), null, null, null);     } } 

i thought of creating reusable executor can have business logic here. me looks cleaner add dependency execute functions in order. chain of responsibility, say. thoughts?

a generic executor like:

import org.apache.commons.lang3.validate; import org.slf4j.logger; import org.slf4j.loggerfactory;  import java.util.arraylist; import java.util.list; import java.util.optional; import java.util.function.consumer; import java.util.function.function; import java.util.function.supplier;  public class chainedexecutor<t, r> {     private final static logger logger = loggerfactory.getlogger(chainedexecutor.class);     public final list<function<t,optional<r>>> handlers;     private r defaultresponse;      private chainedexecutor() {         this.handlers = new arraylist<>();     }      public r execute(t request) {         return execute(request, optional.empty(), optional.empty());     }      public r execute(t request, function<t, r> defaultsupplier) {         return execute(request, optional.of(defaultsupplier), optional.empty());     }      public r execute(t request, consumer<exception> exceptionhandler) {         return execute(request, optional.empty() ,optional.of(exceptionhandler));     }      public r execute(t request, function<t, r> defaulthandler, consumer<exception> exceptionhandler) {         return execute(request, optional.of(defaulthandler), optional.of(exceptionhandler));     }      public r execute(t request, supplier<r> defaultsupplier) {         final function<t, r> defaulthandler = (input) -> defaultsupplier.get();         return execute(request, optional.of(defaulthandler), optional.empty());     }      private r execute(t request, optional<function<t, r>> defaulthandler, optional<consumer<exception>> exceptionhandler) {         optional<r> response;         try {             (final function<t,optional<r>> handler: handlers) {                 response = handler.apply(request);                  if (response.ispresent()) {                     return response.get();                 }             }         }         catch (exception exception) {             handleorlog(exceptionhandler, exception);         }          return getdefaultresponse(defaulthandler, request);     }      private void handleorlog(optional<consumer<exception>> exceptionhandler, exception exception) {         if (exceptionhandler.ispresent()) {             exceptionhandler.get().accept(exception);             return;         }         logger.error("unhandled exception occurred while executing handler chain. developer error.");     }      private r getdefaultresponse(optional<function<t, r>> defaulthandler, t request) {         if (defaulthandler.ispresent()) {             return defaulthandler.get().apply(request);         }         return getdefaultresponse();     }      public r getdefaultresponse() {         return defaultresponse;     }      public static class builder<t, r> {         private final chainedexecutor<t, r> chainedexecutor = new chainedexecutor<>();          public builder(list<function<t,optional<r>>> handlers) {             validate.notnull(handlers);             (final function<t, optional<r>> handler: handlers) {                 validate.notnull(handler);                 handlers.add(handler);             }         }          public builder() {}          public chainedexecutor.builder<t, r> withhandler(function<t, optional<r>> handler) {             validate.notnull(handler);             chainedexecutor.handlers.add(handler);             return this;         }          public chainedexecutor.builder<t, r> withdefaultresponse(r defaultresponse) {             validate.notnull(defaultresponse);             chainedexecutor.defaultresponse = defaultresponse;             return this;         }          public chainedexecutor<t, r> build() {             validate.istrue(!chainedexecutor.handlers.isempty());             return chainedexecutor;         }     } } 

edit

i ended not doing this. thought crossed mind. felt make more cryptic colleagues. though, removing if/else. went oops way (polymorphism).

from point of view first version looks simpler , easier read, go if there no win in performance in second version. extraction of generic method good, seems not straight forward because each statevalidator looks different.


Comments

Popular posts from this blog

javascript - Create a stacked percentage column -

Optimising Firebase database by automatically overwriting data -

javascript - Angular UI-Grid customTemplate directive causing rows to load slowly/? -