"if" statement against OO Design

I have enum say ErrorCodes that

public enum ErrorCodes { INVALID_LOGIN(100), INVALID_PASSWORD(101), SESSION_EXPIRED(102) ...; private int errorCode; private ErrorCodes(int error){ this.errorCode = error; } //setter and getter and other codes } 

I am now checking exception error codes with these error codes. I do not want to write if this is so, if so. How can I solve this problem (writing 10+ if blocks)

Is there any project for this situation?

thanks

+7
java design-patterns enumeration if-statement
source share
6 answers

As Spoike pointed out, using polymorphism to choose the right error handling method is an option. This approach basically discards 10 + if blocks for a virtual JVM search, defining a class hierarchy.

But before moving on to a full-blown class hierarchy, consider the enum methods as well. This option works well if what you plan to do in each case is pretty similar.

For example, if you want to return a different error message for each ErrorCode , you can simply do this:

 // Note singular name for enum public enum ErrorCode { INVALID_LOGIN(100, "Your login is invalid"), INVALID_PASSWORD(101, "Your password is invalid"), SESSION_EXPIRED(102, "Your session has expired"); private final int code; private final String private ErrorCode(int code, String message){ this.code = code; this.message = message; } public String getMessage() { return message; } } 

Then your error handling code will be as follows:

 ErrorCode errorCode = getErrorCode(); prompt(errorCode.getMessage()); 

One of the drawbacks of this approach is that if you want to add additional cases, you will need to change the enumeration itself, while with the class hierarchy you can add new cases without changing the existing code.

+3
source share

Either you do this using an if statement or switch, or you simply implement this logic in ErrorCode code.

In OO mode, it all depends on how you want the application or system to respond to the error code. Suppose you just want it to display some kind of dialog:

 public doSomethingWithError() { ErrorCodes e = getError(); // the source of error, or originator, returns the enum switch(e) { case ErrorCodes.INVALID_LOGIN: prompt('Invalid Login'); case ErrorCodes.INVALID_PASSWORD: prompt('Invalid password'); // and so on } } 

Instead, we could create an ErrorHandler class that does this instead:

 // We'll implement this using OO instead public doSomethingWithError() { ErrorHandler e = getError(); // the originator now returns an ErrorHandler object instead e.handleMessage(); } // We will need the following abstract class: public abstract class ErrorHandler { // Lets say we have a prompter class that prompts the message private Prompter prompter = new Prompter(); public final void handleMessage() { String message = this.getMessage(); prompter.prompt(message); } // This needs to be implemented in subclasses because // handleMessage() method is using it. public abstract String getMessage(); } // And you'll have the following implementations, eg // for invalid logins: public final class InvalidLoginHandler() { public final String getMessage() { return "Invalid login"; } } // Eg for invalid password: public final class InvalidPasswordHandler() { public final String getMessage() { return "Invalid password"; } } 

The first solution is easy to implement, but it becomes difficult to maintain as the code grows. The latter solution is more complex (aka. Template template template according to Open Closing Principle ), but allows you to add additional methods to the ErrorHandler when you need it (for example, recovering resources or something else). You can also implement this using Strategy .

You will not completely leave with conditional statements, but in the latter case, the condition will be transferred to the part of the code in which the error occurred. Thus, you will not have dual servicing of conditional statements by either the creator or the error handling code.

EDIT:

See this answer by Michael Borgwardt and this answer by oksayt on how to implement methods in Java Enums if you want to do this.

+7
source share

Java variables are very powerful and allow you to implement implementations of each instance:

 public enum ErrorCode { INVALID_LOGIN { public void handleError() { // do something } }, INVALID_PASSWORD { public void handleError() { // do something else } }, SESSION_EXPIRED { public void handleError() { // do something else again } }; public abstract void handleError(); } 

Then you can just call errorCode.handleError(); . However, it is doubtful whether the renaming of ErrorCode is the right place for this logic.

+4
source share

I believe that the best you can do is implement a strategy template. This way you do not have to change existing classes when adding new enumerations, but you can still expand them. (Open-principle).

Search for a strategy template and an open closed principle.

+2
source share

You can create an error code map (Integer) for enumeration types

Edit

In this solution, once the map is prepared, you can find the error code on the map and therefore will not require .... sse look ups.

eg.

 Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>(); for (ErrorCodes error : ErrorCodes.values()) { errorMap.put(error.getCode(), error); } 

Now that you want to check the error code coming from your application, all you have to do is

 ErrorCodes error = errorMap.get(erro_code_from_application); 

Thus, we eliminate the need for all if..else.

You just need to configure the card so that adding error codes does not require changes to another code. Preparing a map is a one-time job and can be associated with a database, properties file, etc. During initialization of your application.

0
source share

In my opinion, there is nothing wrong with ErrorCodes as enumerations and the switch statement for handling send errors. Enumerations and switches work well together.

However, maybe you will find the following insteresting (a kind of excessive design), see the Example or โ€œDual Dispatchโ€ on Wikipedia . Estimated Requirements:

  • Error handling must be encapsulated in a native class.
  • Error handling should be replaceable.
  • Type of security: whenever an error is added, you are forced to add error handling with each implementation of the error handler. It is impossible to "forget" an error in one (possibly many) switching states.

The code:

 //Inteface for type-safe error handler interface ErrorHandler { void handleInvalidLoginError(InvalidLoginError error); void handleInvalidPasswordError(InvalidLoginError error); //One method must be added for each kind error. No chance to "forget" one. } //The error hierachy public class AbstractError(Exception) { private int code; abstract public void handle(ErrorHandler); } public class InvalidLoginError(AbstractError) { private String additionalStuff; public void handle(ErrorHandler handler) { handler.handleInvalidLoginError(this); } public String getAdditionalStuff(); } public class InvalidPasswordError(AbstractError) { private int code; public void handle(ErrorHandler handler) { handler.handleInvalidPasswordError(this); } } //Test class public class Test { public void test() { //Create an error handler instance. ErrorHandler handler = new LoggingErrorHandler(); try { doSomething();//throws AbstractError } catch (AbstractError e) { e.handle(handler); } } } 
0
source share

All Articles