views:

105

answers:

7

Ok, so I am designing a class here and I have two options. I can either write multiple methods or a single method which takes say an Enum.

I'm trying to figure out the best way to do this.

Lets take an example:

public class myClass
{ ...
    public void DoStuff1()
    { ... Do Stuff ... }

    public void DoStuff2()
    { ... Do Stuff ... }

    public void DoStuff3()
    { ... Do Stuff ... }
}

Ok, all makes sence, now an alternative way would be:

public class myClass
{ ...

    public Enum Option
    {
        Option1,
        Option2,
        Option3
    }

    public void DoStuff(Option option)
    { ... Do Stuff ... }
}

In terms of DRY, they are not that bad becaues the code pretty much calls internal methods anyhow, so it's only what is visible to the user for them to choose.

So which do you prefer an why and are there any guidelines around this already?

A: 

It depends on how similar your options are. In the sense that, if your algorithm/method will change drastically depending on the option, then better to use multiple methods. If it's relatively similar, then go with the enum.

Sev
A: 

I would only use the second option (so Parameters) when most of the code in the methods is somehow related and the enum Option only specifies a small change in method's behaviour. When the option would change the effect of the function drastically, it is better to use a separate method. It makes the code much more readable, and you would probably be using some sort of case statement in the function anyway, effectively making things more complicated than they need to be.

I think a good example when to use option parameters is a "GetData" function, where the option parameter only specifies where the data comes from (ie from current database or from archives), but the rest of the mechanics is the same for both cases.

Rekreativc
+3  A: 

Was it just me or I'm actually smelling a Command design pattern here?

Seh Hui 'Felix' Leong
+1 I picked up that scent too.
Gishu
+1  A: 

Multiple methods it is for me.

  • From the developer side, I don't have to maintain an enum of method/command-codes and a switch case inside DoStuff()
  • From the client side, I think it doesn't matter much.

Update: If this class isn't doing the actual work and is more of a forwarder / delegates work to the right object, then I'd look at implementing the Command Design Pattern as someone rightly pointed out here.

Gishu
A: 

You need to take into account the purpose of each execution path. Is the behavior for Options 1, 2, and 3 very similar, changing only in minor ways? Or are all three options different, changing in more significant ways? Even if each option is similar, what is a clearer way of representing the operations for those options? An enum with values Option1, Option2, and Option3 is pretty vauge.

You should also be asking yourself...will I stop at three options? What is the possibility of needing more than three in the future? Will you need many more? Perhaps a more object oriented approach is needed.

There are many tools to help you decide what you need to solve your problem. Design patterns, anti-patterns, and probably books on refactoring could help provide some problem-solving fuel.

jrista
A: 

In the second case, if DoStuff looks like this

public void DoStuff(Option option)
{ 
  switch (option)
  {
     case Option1: /* Stuff 1 */ break;
     case Option2: /* Stuff 2 */ break;
     case Option3: /* Stuff 3 */ break;
  }
}

then it's probably not a good idea. But the most important aspect is: Which one makes the better API for other classes using this class? Hard to tell as this is an abstract example. If the second option makes more sense, you could still implement the first method (making DoStuff1..DoStuff3 private or protected) and implement DoStuff as in

public void DoStuff(Option option)
{ 
  switch (option)
  {
     case Option1: DoStuff1(); break;
     case Option2: DoStuff2(); break;
     case Option3: DoStuff3(); break;
  }
}
ammoQ
A: 

If the DoStuffX() methods have common functionality I would use enums. If there is nothing in common, then I would use separate methods to avoid the if-else/switch stmts.

Rashmi Pandit