10

我有一个非常常见的“给定 a Foo,返回 a Bar”的模式,例如,给定 a user_id,返回 a User

这类函数是否有传统的命名模式?在Joel on Software之后,我个人使用了很多bar_from_foo(),但我很少看到其他人这样做,它很快就变得冗长,例如

widgets = user_widgets_from_user(user_from_param_map(params))

有没有一种传统的方式来命名,或者User.from_map()以任何流行的语言命名或命名空间(例如)?我对 Python 特别感兴趣,但你能想到的任何语言都会很有用。

4

5 回答 5

15

我会利用 Clojure 的命名灵活性并将其称为:

(defn foo->bar [] ...)

对我来说,这使意图很清楚,而且很短。

于 2013-04-12T03:45:16.923 回答
6

在 Python 和其他各种 OO 语言中,这应该是 Bar 上的构造函数,它以单个 Foo 作为其唯一参数。由于 Python 不进行方法重载(并且尝试模拟它通常很脆弱),如果Bar.__init__已经采用不同的签名,那么约定正是您的最后一个。重要的是,这通常被定义为方法而不是静态方法(为了子类的利益):

 class Bar:
      @classmethod
      def from_foo(cls, f):
          '''Create a new Bar from the given Foo'''
          ret = cls()
          # ...
于 2013-04-12T03:49:15.583 回答
5

如果你想把一个东西转换成另一个东西,例如一个字符串到一个整数,方法是在接收器上定义的,因此它的类是明确的,所以你不应该把接收器类作为方法名称的一部分:String#to_i,不是String#string_to_i。这是面向对象编程的核心思想之一(多态性)。

如果接收者过于笼统而无法分配这样的方法,例如 ifuser_id只是一个字符串,并且定义一个String将其转换为 a的方法User看起来不正确,那么您应该在您期望返回的类上定义一个构造函数方法值为:User.newUser.from_id

于 2013-04-12T03:43:39.957 回答
4

我认为这在很大程度上取决于上下文和选择一个有意义的隐喻。例如 ActiveRecord 使用类方法“find”来查找数据库中的记录,这是一个比“输入 user_id,输出用户”更有意义的想法。例如:

User.find(user_id)
User.find_by_email(user_email)

对于转换,我通常喜欢编写转换方法以使其易于在高阶函数中使用。例如在 ruby​​ 中,转换通常使用to_*实例方法完成,例如将 a 转换Foo为 a对所有 fooBar都有一个to_bar方法是有意义的,因此您可以编写:

foo = Foo.new(...)   # make a new Foo
bar = foo.to_bar     # convert it to a Bar

然后要转换一堆 foo,您可以简单地:

bars = foos.map(&:to_bar)

Ruby 也倾向于Foo.parse(str)将字符串转换为对象。


对于 javascript,我喜欢使用类方法(我从标准 ml 中获得),例如:

Foo.toBar = function(foo) {
   return new Bar(...);
};

然后你也可以映射它(在这个例子中使用下划线):

var bars = _.map(foos, Foo.toBar);

标准 ML 约定是结构(类)方法。示例 fn 类型:

Foo.toBar : foo -> bar
Foo.fromBar : bar -> foo

你会像这样使用它:

val bar = Foo.toBar foo;
val bars = map Foo.toBar foos;
于 2013-04-12T08:04:15.233 回答
1

为什么将参数的类型放在函数的名称中?我认为这会更清楚一些

a_bar = bar_from(a_foo)

那么您可以在许多语言中依赖动态调度或重载......例如,在 Python 中,实现可以尝试调用(x.toBar()如果存在),或者它可以检查全局注册表,如Bar_builders[type(x)](x); 在 Lisp 中,你可以依赖方法;在 C++ 中关于重载...

于 2013-04-12T20:24:03.773 回答