views:

238

answers:

8

What is the name for passing an argument to a function to select what the function does?

For example:

enum {
   DoSomething,
   ...
};
void f(FunctionType a);

f(DoSomething);
....
f(DoSomethingElse);

Vs:

void DoSomething();
....
void DoSomethingElse();
+3  A: 

Constructs like these often appear together with loops iterating over all values. In that case it's a disguised loop-switch pattern.

But that's not an anti-pattern per se. If you do not know the parameters in advance, a design like this can be valid.

DR
A: 

Depending on the language, both options are anti-patterns with respect to the strategy pattern.

Austin Salonen
+2  A: 

I've called the parameter you pass in the "action" or the "verb". I haven't seen this named as pattern. What you don't show is the inevitable switch statement, which is-- I assume-- why you are calling it an antipattern.

You could consider it a bad implementation of the command pattern. And wikipedia has a article on function objects, which it is also a bad implementation of.

Before object oriented languages were prevalent, we did things like this to group functions in to objects, and often called it "dispatching". (This name has been subsumed in the pattern world with a different thing.)

ndp
A: 

This would be a target for refactoring by creating separate method names for each case and placing any common code into a commonly-called method.

Buggieboy
+4  A: 

In general, one could see it as an anti-pattern, as the separate methods are simpler and more explicit. However, some contexts may change this opinion. Two examples:

Front Controller

All Front Controller patterns work like this (Struts or later) : the call is made to a centralized method, with parameters ; it is later dispatched to the correct handler (identified by one of the parameters). The point here is to apply a common code before (and after, possibly for exceptions) many specific codes.

The problem is not that this type of code executes, but to have this in your own code. If it is in framework code (already written, well tested etc), it's fine. Examples are all the interception technologies, like Spring ..

Command

The Command pattern may be pretty close :

  1. an identifier could identify a command to execute ;
  2. then you locate the correct code : in the command pattern, it's an object, so you can use a map to find the object that corresponds to the identifier
  3. execute the code : in the Command pattern, all these objects have a common method, so calling it is general, there is no need for a switch.
KLE
+1  A: 

It not necessarily an anti-pattern!

Even when the f() function is one big switch, it can be a convenient place where individual 'tokens/verbs/instructions/atoms' of a particular 'language' are processed (or rather 'sent for processing'). Furthermore the f() function can also introduce logic to decide how to dispatch a particular verb based on the run-time context. This ability to late-bind text/data verbs to particular methods in a simple, centralized fashion is important, even though in other cases, using the polymorphic and introspective features of OO languages to serve that purpose may be more appropriate.

Edit: see KLE's response as it echos the idea that this is a pattern. KLE also provides reference to Command and the Front Controller patterns which are same/similar.

mjv
A: 

I'd call it a Dispatcher, since it's probably going to call more specific code based on the parameter(s).

Overly general functions can be bad: hard to use, hard to maintain, hard to debug. Their overly-general nature makes it hard to assert pre- and post-conditions and invariants. Nevertheless, Dispatchers do have their occasional uses. It is one way to provide for extensibility--sometimes it's a more practical way that traditional patterns.

Adrian McCarthy
A: 

Control Coupling.

I heard about it in a presentation by Jim Weirich. In general the method will have a "flag" parameter that controls what algorithm to use.

See my notes (with some references) at Grand Unified Theory of Software Design.

TrueWill