过度概括函数的名称?这是一种反模式吗?

发布于 2024-08-07 03:24:54 字数 257 浏览 3 评论 0原文

将参数传递给函数以选择该函数执行的操作的名称是什么?

例如:

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

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

对比:

void DoSomething();
....
void DoSomethingElse();

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();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

潜移默化 2024-08-14 03:24:54

一般来说,人们可以将其视为一种反模式,因为单独的方法更简单、更明确。然而,某些情况可能会改变这种观点。两个例子:

前端控制器

所有前端控制器模式都像这样工作(Struts 或更高版本):调用带有参数的集中方法;它随后被分派到正确的处理程序(由参数之一标识)。这里的要点是在许多特定代码之前(和之后,可能有例外)应用通用代码。

问题不在于执行此类代码,而在于将其包含在您自己的代码中。如果它在框架代码中(已经编写、经过良好测试等),那就没问题。
示例包括所有拦截技术,例如 Spring。

Command

Command 模式可能非常接近:

  1. 标识符可以标识要执行的命令;
  2. 然后找到正确的代码:在命令模式中,它是一个对象,因此您可以使用映射来查找与标识符对应的对象
  3. 执行代码:在命令模式中,所有这些对象都有一个公共方法,因此调用很一般,不需要开关。

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.
习惯成性 2024-08-14 03:24:54

像这样的结构通常与迭代所有值的循环一起出现。在这种情况下,它是一种伪装的循环切换模式

但这本身并不是一种反模式。如果您事先不知道参数,这样的设计可能是有效的。

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.

你在我安 2024-08-14 03:24:54

我将您在“动作”或“动词”中传递的参数称为“动作”。我还没有看到这个命名为模式。您没有显示的是不可避免的 switch 语句,我认为这就是您将其称为反模式的原因。

您可以认为这是命令模式的糟糕实现。维基百科有一篇关于函数对象的文章,它也是一个糟糕的实现。

在面向对象语言流行之前,我们通过类似的方式将函数分组到对象中,通常将其称为“调度”。 (这个名字已经被包含在模式世界中,有不同的东西。)

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.)

凉薄对峙 2024-08-14 03:24:54

控制耦合

我在 Jim Weirich 的演讲中听说过这一点。一般来说,该方法将有一个“标志”参数来控制使用什么算法。

请参阅我的笔记(以及一些参考资料),网址为软件设计的大统一理论

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.

绮烟 2024-08-14 03:24:54

它不一定是反模式!

即使 f() 函数是一个大开关,它也可以是一个方便的地方,可以处理特定“语言”的各个“标记/动词/指令/原子”(或者更确切地说“发送进行处理”)。此外,f() 函数还可以引入逻辑来决定如何根据运行时上下文分派特定动词。这种以简单、集中的方式将文本/数据动词后期绑定到特定方法的能力很重要,即使在其他情况下,使用面向对象语言的多态和内省功能来实现该目的可能更合适。

编辑:请参阅 KLE 的回应,因为它呼应了这是一种模式的想法。 KLE 还提供了相同/相似的命令和前端控制器模式的参考。

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.

清醇 2024-08-14 03:24:54

这将成为重构的目标,通过为每种情况创建单独的方法名称并将任何公共代码放入通常调用的方法中。

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.

々眼睛长脚气 2024-08-14 03:24:54

我将其称为调度程序,因为它可能会根据参数调用更具体的代码。

过于通用的功能可能会很糟糕:难以使用、难以维护、难以调试。它们过于笼统的性质使得很难断言前置条件、后置条件和不变量。尽管如此,调度程序确实有其偶尔的用途。这是提供可扩展性的一种方法——有时这是比传统模式更实用的方法。

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.

魔法唧唧 2024-08-14 03:24:54

这个例子可以被认为是一个过早泛化

额外参数。
只有一种情况需要添加参数
构成函数或类体的泛化:如果这
参数是“活动的”(作为对象、类型或函数指针)
以及函数或类如何工作的一些特殊细节移至
该参数代表的代码。示例是排序
排序函数和分配器的顺序谓词参数
容器类模板或构造函数的参数。额外的
参数可以构成调用的代码的概括
仅当此代码不关心该函数或使用该类时
该参数的实际值。

代码

  enum command{ start, stop };
  void f_command(command do){
    if( do==start )
        f_start();
    else
        f_stop();
  }
  void f(){
    f_command(start);
    f_command(stop);
  }

对比

  void f(){
    f_start();
    f_stop();
  }

This example could be considered a Premature Generalization

Extra Parameters.
There is only one case where addition of a parameter
constitutes generalization of the function or class body: if this
parameter is "active" (as an object or a type or a function pointer)
and some special details of how the function or class works move to
the code represented by this parameter. The examples are a sorting
order predicate parameter of a sorting function and an allocator
parameter for a container class template or constructor. An additional
parameter may constitute a generalization of the code that calls the
function or uses the class only if this code doesn't bother about the
actual value of this parameter.

The code

  enum command{ start, stop };
  void f_command(command do){
    if( do==start )
        f_start();
    else
        f_stop();
  }
  void f(){
    f_command(start);
    f_command(stop);
  }

Vs

  void f(){
    f_start();
    f_stop();
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文