views:

113

answers:

8

I have a situation where I need to perform several small (but similar) tasks. I can think of two ways to achieve this.

First Approach:

function doTask1();
function doTask2();
function doTask3();
function doTask4();


Second Approach:

// TASK1, TASK2, ... TASK4 are all constants
function doTask(TASK) {
    switch(TASK) {
        case TASK1:
            // do task1
            break;
        case TASK2:
            // do task2
            break;
        case TASK3:
            // do task3
            break;
        case TASK4:
            // do task4
            break;
    }
}

A few more tasks may be added in future (though the chances are rare. but this cannot be ruled out)

Please suggest which of the two approaches (or if any other) is a best practice in such a situation.

+1  A: 

In most languages the best practice would be to have a function per task. For figuring out which function to call there are a number of options (a switch being one of them).

dahlbyk
+1  A: 

I think an important key is context. I try to think of functions as something that will be done over and over again from various contexts. So if the function is only called by one "guy" (or event, or some other function), then I'd go with the switch statement.

Anthony
A: 

nowhere near enough info. is there code sharing? if there is, probably switches over functions, but you may want a strategy, depending on how much there is and the level of complexity. if there isn't, functions are probably a good idea, but how is this api being called? depending on your application, you may want to implement a command pattern, which would mean classes instead of functions...

there are way too many variables in api design to make sweeping statement at this high a level.

Matt Briggs
+7  A: 

Maybe consider :

class TaskN extends Task {
  public void doTask() {
    // do something
  }
}

Case statements are often a sign that there is a polymorphic solution wanting to come out.

But as already pointed out, we need more context to say what is good.

Also do not get hung up on BEST practice. GOOD practice is good enough, especially if improved over time when you know more.

Peter Tillemans
A: 

There is a third approach -- a table of function pointers.

typedef retType (*func)(argTypes)  funcptr_t;

funcptr_t  _func_doTasks[4] = {doTask1, doTask2, doTask3, doTask4};

Now the task can be called directly using ...

_func_doTasks[taskSelector](args if any);

Hope this helps.

Sparky
Note that not all languages support functions as first-class values.
DeadMG
A: 

From the little information you provided, seems like a dispatch table could be the best solution.

kemp
+1  A: 

It could also be possible to use a static variable switch. For example, in C++, you might have

enum tasks {
    SomeDescriptiveTaskNameOne,
    SomeDescriptiveTaskNameTwo,
};

template<tasks t> void DoTask(); // get compiler error if unknown task
template<> void DoTask<SomeDescriptiveTaskNameOne>() {
    // do task one
}
template<> void DoTask<SomeDescriptiveTaskNameTwo>() {
    // do task two
}

Unfortunately, since you didn't specify your language, it's difficult to make a recommendation, as few languages offer this solution. The polymorphic solution offered by others may fit more languages.

DeadMG
+1  A: 

Looks like you could use the strategy pattern here.

fastcodejava