How to Avoid a Lot of If Else Conditions

How to avoid a lot of if else conditions

Try to look at the strategy pattern.

  • Make an interface class for handling the responses (IMyResponse)

    • Use this IMyResponse to create AdvisoryBoardResponse, EditorialBoardResponse classes
  • Create an dictionary with the soapresponse value as key and your strategy as value
  • Then you can use the methods of the IMyResponse class by getting it from the dictionary

Little Example:

// Interface
public interface IResponseHandler {
public void handleResponse(XmlPullParser xxp);

}

// Concrete class for EditorialOffice response
private class EditorialOfficeHandler implements IResponseHandler {
public void handleResponse(XmlPullParser xxp) {
// Do something to handle Editorial Office response
}
}

// Concrete class for EditorialBoard response
private class EditorialBoardHandler implements IResponseHandler {
public void handleResponse(XmlPullParser xxp) {
// Do something to handle Editorial Board response
}
}

On a place you need to create the handlers:

Map<String, IResponseHandler> strategyHandlers = new HashMap<String,IResponseHandler>();
strategyHandlers.put("EditorialOffice", new EditorialOfficeHandler());
strategyHandlers.put("EditorialBoard", new EditorialBoardHandler());

Where you received the response:

IResponseHandler responseHandler = strategyHandlers.get(soapResponse);
responseHandler.handleResponse(xxp);

How to avoid a lot of if else conditions

Combination of enum and switch statement comes handy for your example:

private static String getXSIType(String fieldType) {

FieldType foundFieldType = FieldType.findByValue(fieldType);
if(foundFieldType == null) {
return CustomFieldRef.STRING.getValue();
}
switch(foundFieldType) {
case FREE_FORM_TEXT:
case EMAIL_ADRESS:
case HELP:
case HYPERLINK:
case INLINE_TEXT:
case LONG_TEXT:
case PASSWORD:
case PHONE_NUMBER:
case RICH_TEXT:
case TEXT_AREA:
return CustomFieldRef.STRING.getValue();
case INTEGER_NUMBER:
return CustomFieldRef.LONG.getValue();
case MULTIPLE_SELECT:
return CustomFieldRef.MULTI_SELECT.getValue();
case DOCUMENT:
case LIST_RECORD:
case IMAGE:
return CustomFieldRef.SELECT.getValue();
case CURRENCY:
case DECIMAL_NUMBER:
case PERCENT:
return CustomFieldRef.DOUBLE.getValue();
case CHECK_BOX:
return CustomFieldRef.BOOLEAN.getValue();
case DATE:
case DATETIME:
case TIME_OF_DAY:
return CustomFieldRef.DATE.getValue();
default:
return CustomFieldRef.STRING.getValue();
}
}

enum FieldType {

FREE_FORM_TEXT("_freeFormText"),
EMAIL_ADRESS("_eMailAddress"),
HELP("_help"),
HYPERLINK("_hyperlink"),
INLINE_TEXT("_inlineText"),
LONG_TEXT("_longText"),
PASSWORD("_password"),
PHONE_NUMBER("_phoneNumber"),
RICH_TEXT("_richText"),
TEXT_AREA("_textArea"),
INTEGER_NUMBER("_integerNumber"),
MULTIPLE_SELECT("_multipleSelect"),
DOCUMENT("_document"),
LIST_RECORD("_listRecord"),
IMAGE("_image"),
CURRENCY("_currency"),
DECIMAL_NUMBER("_decimalNumber"),
PERCENT("_percent"),
CHECK_BOX("_checkBox"),
DATE("_date"),
DATETIME("_datetime"),
TIME_OF_DAY("_timeOfDay");

private final String value;

FieldType(String fieldType) {
this.value = fieldType;
}

public static FieldType findByValue(final String value) {
return Arrays.stream(FieldType.values())
.filter(o -> StringUtils.equals(o.value, value))
.findFirst()
.orElse(null);
}
}

enum CustomFieldRef {

STRING("String"),
LONG("Long"),
DOUBLE("Double"),
BOOLEAN("Boolean"),
DATE("Date"),
SELECT("Select"),
MULTI_SELECT("MultiSelect");

private final String value;

CustomFieldRef(String customFieldRef) {
this.value = customFieldRef;
}

public String getValue() {
String prefix = "platformCore";
String suffix = "CustomFieldRef";
return String.format("%s:%s%s", prefix, value, suffix);
}
}

There is no need for a break in this case because the return stops the execution of the getXSIType() function.

In a switch statement you can not use the || operator but instead, you can define fall through statements:

...
case PHONE_NUMBER:
case RICH_TEXT:
case TEXT_AREA:
return CustomFieldRef.STRING.getValue();

This is equivalent to:

if(FieldType.findByValue(fieldType).equals(FieldType.PHONE_NUMBER)
|| FieldType.findByValue(fieldType).equals(FieldType.RICH_TEXT)
|| FieldType.findByValue(fieldType).equals(FieldType.TEXT_AREA)) {
return CustomFieldRef.STRING.getValue();
}

A switch statement can have an optional default case, which must appear at the end of the switch statement. It can be used for performing an action when none of the cases above is true.

avoid a lot of if-else checks

If the conditions are really exclusive then I'd start with three separate functions, one for each process. Break any common code out into their own functions that you can call from the three process functions. The only conditional left should be where you decide which of the three process functions to call.

How to avoid if..else(or any conditionals) while deciding which method to be called?

The nature of obj is ambiguous, but I would recommend having a well-defined interface and pass it throughout your code where the class implementation of your interface would be equivalent to your 'action'. Here's an example of what that might look like in Typescript:

interface someDBInterface {
performAction() : void;
}

function process(obj : someDBInterface) {
let result = obj.performAction();
}

class action1 implements someDBInterface {
status: any
performAction() {
//db.updateTable1();
}
}

class action2 implements someDBInterface {
status : any
performAction() {
//db.updateTable1(this.status);
}
}

class action3 implements someDBInterface {
performAction() {
//May be log action 3 recieved
}
}

If this doesn't meet your requirements, feel free to reach out :)

Best practice for large amounts of if/else statements

First off, good job noticing that large if/else statements are not a positive thing. There are a lot of ways to make them less painful and easier to read, some of which you've touched on. For example, you could move this to another class (as you said), or at the very least another method to isolate them from the rest of your code.

One design pattern that I've found helpful in this situation is the chain-of-responsibility pattern. In the CoR pattern, you have a number of command objects that are responsible for knowing if they can handle a particular value. So in your case, you'd have a command object for each if/else in your logic, and each command object would know if they can handle newCondition.number. If the command object can handle the value, it performs its' logic (in your case, it'd perform the stuff inside the if/else); if it cannot, it passes the message along to the next object in the chain.

This has the benefit of isolating the logic and making it easier to add functionality with minimal impact. You can also name the command subclasses something interesting and informative to remove some of the mystique of the code.

At the very least, I'd refactor the if statement into its own method. And if you have lots of if/else statements, I'd consider the chain-of-responsibility pattern.

There is a great book called Refactoring to Patterns that I highly recommend.

I want to avoid lots of if-else statement

Your switch/case statements look like they could, and should, be replaced with table lookup -- for example, a 2D array where the first axis is indexed by purchaseAmount > 100 (0 or 1) and the second axis is indexed by deliveryDay (0, 1, or 2).

Is using too many 'if' statements bad programming?

Programming is all about automating processes. You will not hear me say that the way you are doing this is wrong. If it works then it is oke. But of course it would be more beautiful if you could find a way to make it check everything automatically. Like looping through all x cords and just check if all of those are checked. This may not be easier, but it will be more extendable. If you'd ever wish to play a game on a ten by ten grid. then you would only have to say that that is the size of the field. Right now you would need to add all those other lines of code.



Related Topics



Leave a reply



Submit