vendredi 27 juillet 2018

Design patter to refactor nested if else inside switch case

I have to refactor a bulky existing code. Gone through a lot of similar questions on SO and other sites, still confused. If anyone can put some light or any idea will be of great help.

There are 5 drop downs and I need to update the view based upon the slected values in drop downs. First drop down has following options:

"TOP DOWN BUDGET"
"TEMPLATE BUDGET"
"ORIGINAL BUDGET"
"REVISED BUDGET"

Second drop down has following options:

"Day"
"Week"
"Month"
"Quarter"
"Year"

Third drop down has following options:

"Details"
"Summary"

Fourth drop down has following options:

"Hours"
"Dollars"

Fifth drop down has following options:

 "StartDate"
 "EndDate"

Now code has following scenario:

public List<WorkPlanReport> XYZ(...){//opening of some method XYZ....

List<WorkPlanReport> workPlanReportList=null;
switch(first_Drop_Down_Value){

    case "TOP DOWN BUDGET":
        List<TaskDetails> timeLine=getTimeLine("firstDropDownA", second_drop_down_val, third_drop_down_val, fourth_drop_down_val);
        workPlanReportList=setWorkPlanByTimeLine(timeLine, "firstDropDownA", second_drop_down_val, third_drop_down_val, fourth_drop_down_val);
        break;
    case "TEMPLATE BUDGET":
        List<TaskDetails> timeLine=getTimeLine("firstDropDownB", second_drop_down_val, third_drop_down_val, fourth_drop_down_val, fifth_dd_val);
        workPlanReportList=setWorkPlanByTimeLine(timeLine, "firstDropDownA", second_drop_down_val, third_drop_down_val, fourth_drop_down_val);
        break;
    case "ORIGINAL BUDGET":
        List<TaskDetails> timeLine=getTimeLine("firstDropDownC", second_drop_down_val, third_drop_down_val, fourth_drop_down_val, fifth_dd_val);
        workPlanReportList=setWorkPlanByTimeLine(timeLine, "firstDropDownA", second_drop_down_val, third_drop_down_val, fourth_drop_down_val);
        break;
    case "REVISED BUDGET":
        List<TaskDetails> timeLine=getTimeLine("firstDropDownD", second_drop_down_val, third_drop_down_val, fourth_drop_down_val, fifth_dd_val);
        workPlanReportList=setWorkPlanByTimeLine(timeLine, "firstDropDownA", second_drop_down_val, third_drop_down_val, fourth_drop_down_val);
        break;

}

return workPlanReportList;
}// Closing of some method XYZ....

private List<TaskDetails> getTimeLine(String first_Drop_Down_Value, String second_dd_val, third_dd_val, fourth_dd_val, String fifth_dd_val){

    switch(second_Drop_Down_Value){

    case "Day":
        if(third_dd_val.equals("Details")){
            if(fourth_dd_val.equals("Hours")){
                if(fifth_dd_val.equals("startDate"){
                //prepare query & call DB for fetching days timeline for hours details of TOP DOWN BUDGET filtered by start date...
                }
                else// means endDate{
                //prepare query & call DB for fetching days timeline for hours details of TOP DOWN BUDGET filtered by end date...
                }
            }
            else{//means Dollars
                if(fifth_dd_val.equals("startDate"){
                //prepare query & call DB for fetching days timeline for dollars details of TOP DOWN BUDGET filtered by start date...
                }
                else// means endDate{
                //prepare query & call DB for fetching days timeline for dollars details of TOP DOWN BUDGET filtered by end date...
                }
            }   
        }
        else// means summary...
        {
            if(fourth_dd_val.equals("Hours")){
                if(fifth_dd_val.equals("startDate"){
                //prepare query & call DB for fetching days timeline for 'hours' "summary" of TOP DOWN BUDGET filtered by start date...
                }
                else// means endDate{
                //prepare query & call DB for fetching days timeline for hours summary of TOP DOWN BUDGET filtered by end date...
                }
            }
            else{//means Dollars
                if(fifth_dd_val.equals("startDate"){
                //prepare query & call DB for fetching days timeline for dollars details of TOP DOWN BUDGET filtered by start date...
                }
                else// means endDate{
                //prepare query & call DB for fetching days timeline for dollars details of TOP DOWN BUDGET filtered by end date...
                }
            }
        }
        break;
    case "Week":
            //....similar code as in case "Day" just here we need to fetch data week-wise
            break;
    case "Month":
            //....similar code as in case "Day" just here we need to fetch data month-wise
            break;
    case "Quarter":
            //....similar code as in case "Day" just here we need to fetch data quarter-wise
            break;
    case "Year":
            //....similar code as in case "Day" just here we need to fetch data year-wise
            break;
    }
}


private List<WorkPlanReport> setWorkPlanByTimeLine(List<TaskDetails> timeLine, String "firstDropDownA", String second_drop_down_val, String third_drop_down_val, String fourth_drop_down_val){

WorkPlanReport wpr=new WorkPlanReport();
// Here I have real mess..., Iterating the timeLine list and have switch case and inside switch case multilevel nesting of if else to decide which setter we need to use to set the value.

for example:

If it is "TOP DOWN BUDGET" in first drop-down, "Day" in second drop-down, "Details" in third drop down, "Hours" in fourth drop-down & "StartDate" in fifth drop-down, I have to call follwing code:

wpr.setTDBDetailsHoursByStartDate(taskDetails.getTDBDetailsByHourStartDayView());

If it is "TOP DOWN BUDGET" in first drop-down, "Day" in second drop-down, "Details" in third drop down, "Hours" in fourth drop-down & "EndDate" in fifth drop-down, I have to call follwing code:
wpr.setTDBDetailsHoursByEndDate(taskDetails.getTDBDetailsByHourEndDayView());

}

This code is more than 1000 lines, and I am deseparate to refactor it using some suitable design pattern.

WorkPlanReport & TaskDetails DTOs have few similar types of properties in common and many other different properties also.

I am not allowed to alter those DTOs because those are used in some related common code base.

Aucun commentaire:

Enregistrer un commentaire