views:

315

answers:

9

Hi guys,

I have been programming for alot of time. Generally i program in some languages like PHP, ASP.net, Java, JavaScript and others. In all languages i have to use alot of if else statments . Like if value= 10 then ... if i review my code then i find alot of if conditions. So i would like to minimise them but how not sure.

one point was using classes somewhat minimised but still they are more...

like task, cat, sec and type:

if task = 'add' then
   if cat = "animal" then
      if sec = "man" then
          if type = "male" then
                 'do the following stuffs
          else
                 'do the following stuffs
          end if
      elseif sec = "horse" then
          if type = "run"
                 'do the following stuffs
          else
                 'do the following stuffs
          end if
      elseif....
      end if
   elseif cat = "plant" then
     if sec = "land" then
          if type="tree" then
                 'do the following stuffs
          elseif type = "grass" then..
                 'do the following stuffs
          elseif...
          end if
    elseif sec = "water" then
    ...
...

...

more n more continue n continue

so wonder how can i minimise them and write some efficient codes?

Sorry to inform lately that there may be alot of values for task, cat, sec, and type. My if statements are going nested n nested.

More explanatory my code also looks like same as :

http://thedailywtf.com/Articles/Coding-Like-the-Tour-de-France.aspx

+12  A: 

Many if..else statements is often a symptom the Polymorphism is not being used.

Mitch Wheat
reading the stuff may be it is the one m looking for... will post comment later... if some visual explanation link plz post it
KoolKabin
I don't think polymorphism solves all issues of too many if-else's. What if it's input from console that needs to be interpreted?
Default
Would the downvoter please leave a comment. Thanks.
Mitch Wheat
I'm not suggesting it removes all if..else's but too many if..else's is often a symptom the polymorphism is not being used.
Mitch Wheat
I don't see how your answer solves the OP's problem, could you elaborate? In particular since `task`, `cat` etc. are ordinary strings, not a hierarchy of objects.
Heinrich Apfelmus
@Heinrich: Interpolating the variables' *meanings* from their names/values, it's pretty obvious that they shouldn't be strings. This answer tackles the OP's real problem, which is 1000x more useful to him than new techniques to compare strings.
BlueRaja - Danny Pflughoeft
Fair enough. I'm more hesitant to interpolate the OP's real problem, though, in particular because subtype polymorphism is not the only solution.
Heinrich Apfelmus
+4  A: 

It's called 'Arrow Antipattern' Some of the methods of dealing with it are described here: http://c2.com/cgi/wiki?ArrowAntiPattern

One of the ways you migt consider, is to refactor code in nested levels to separate functions like

if cat = "animal" then
  functionForAnimal();
elseif cat = "plant" then
 functionForPlant();
elseif...


function functionForAnimal() 
  if sec = "man" then
    functionForMan();
  elseif sec = "horse" then
    functionForHorse();
  elseif...

etc...

This splits code into smaller fragments which are easier to maintain, and possibly reusable.

Mchl
sorry for making question clear lately... but the cases may be alot like in edited question
KoolKabin
yeah more explanatory my code also looks like the same:http://thedailywtf.com/Articles/Coding-Like-the-Tour-de-France.aspx
KoolKabin
+1, this was my thought as well, split it, make it more easily viewable and reuse the parts that can be reused.
Default
A: 

If choices for each of those variables are finite, then you can even use tricks like bit fields with OR operation.

Example:

// give each field a byte so that each can have 256 possible values
#define TASK_ADD 0x01
#define TASK_SUB 0x02
...
#define CAT_ANIMAL 0x01
...
#define SEC_BOY 0x03
#define SEC_MAN 0x04
...
#define TYPE_FEMALE 0x01
#define TYPE_MALE 0x02
...

if ((task << 24 | cat << 16 | sec << 8 | type) == 0x01010402) {
  // do stuff
}
Joy Dutta
sorry for making question clear lately... but the cases may be alot like in edited question
KoolKabin
+1  A: 

Polymorphism might be useful when you have different implementations but the task is conceptually the same. Sometimes it's hard to find a natural class structure, and approaches like the state pattern or the strategy pattern might be more appropriate.

Felix Ungman
yeah polymorphism is definitely a useful one but before using polymorphism we should create object and before creating object we should know what's the options set by user. eg. if keep all those options in a form and then user clicks a button to start the work then which one class should be created and called as per polymorphisim
KoolKabin
A: 

Somewhere you will need to check the conditions with if-elses, to make sure you do the right thing. You could create new subs if you don't want to cram one sub

Sub AddAnimalManMale()
    If task = 'add' And cat = 'animal' And sec = 'man' And type = 'male' Then
        'perform the add animal man male action'
    End If
End Sub
Sub AddAnimalHorseRun()
    If task = 'add' And cat = 'animal' And sec = 'horse' And type = 'run' Then
        'perform the add animal horse run action'
    End If
End Sub

then in your main sub

...
Call AddAnimalManMale()
Call AddAnimalHorseRun()
...
Default
Your stuff is also good and similar to above ones. If we make a function call by concatinating all the options then do we need to check the variables once more inside the function
KoolKabin
+2  A: 

You described a matrix with 4 incoming parameters - task, cat, sec, type and one outgoing - stuff. So you have to code it someway.

For example, XML map and an XPath query, i.e. String.Format("task[@value={0}]/cat[@value={1}]/sec[@value={2}]/type[@value={3}]", "add", "animal", "man", "male") but this approach points to a data, not a method delegate.

Another way:

void DoStuffA() { }
void DoStuffB() { }

var arr = new[]
{
    new { Task = "Add", Cat = "Animal", Sec = "Man", Type = "Male", Method = (Action)DoStuffA },
    new { Task = "Add", Cat = "Plant", Sec = "Land", Type = "Tree", Method = (Action)DoStuffB },
    // etc..
};

var action = arr.FirstOrDefault(i =>
     i.Task == "Add" &&
     i.Cat == "Animal" &&
     i.Type == "Male").Method;
action();

Also you can use not anonymous members but declare a class, describe your variants in XML and deserialize them from XML to a number of your class instances.

abatishchev
nice approach using array... its also interesting... will be looking forward on it too
KoolKabin
+1  A: 

I think there are some fundamental flaws in your design. I don't know what problem you are trying to solve with this code, but such code should be very rare in an object oriented language. Your code also seems a bit illogical to me, because, for example, the variable type means gender the first time it's used (male) and then it means an action (run). Have you noticed this?

Anyway, if you're indeed using Java (or anything with classes), what you need is abstraction. Next, move all logic you can to your objects -- don't handle it in one monstrous routine. Think this way: my objects know how to do their part.

Actually it's a bit difficult to give good advice in this situation, I suspect your problems have source on some high level in your application and this case code is only a symptom. Try to redesign your program to use object-oriented approach and perhaps a better solution will come to your mind as you go.

If you're not sure what polymorphism, abstraction and other OO terms mean, you will need to read up on this.

YRH
+4  A: 

Assuming you're always doing equality comparisons, and comparing all four fields, a simple data-driven approach is quite practical. All you need to do is construct a map from (task, cat, sec, type) to a function to call:

handlers = {
    ('add', 'animal', 'man', 'male'): add_man_func,
    ('add', 'animal', 'horse', 'run'): run_horse_func,
    # ...
}

handler = handlers[(task, cat, sec, type)]
handler(some_args)
Nick Johnson
I would probably break this up into different levels (single key->function pair). The main reason being, there is likely to be shared code for all _add_ s and all _animal_ s etc.
Dolphin
A: 

Breaking the code up is all what the game is about.

Historically you would do (and there had been good, or at least stable code, and still there is in all of these)

  • as you are doing it now, monolithic in huge functions, with lots of comments

  • split it into small well defined and well named functions

  • naming functions was tricky for complex stuff and also if you keep on passing references to big structures then objects were a natural thing to invent (however, once you go object way then it makes sense to do everything and through reusing the code object oriented patterns emerge... )

Recognizing the patterns is in a way similar to giving good names to functions (plus you get naturally useful methods thrown in, which can be huge win).

Unreason