“将foo转换为bar”的函数名称约定

时间:2013-04-12 03:29:13

标签: javascript python ruby clojure lisp

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

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

widgets = user_widgets_from_user(user_from_param_map(params))

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

5 个答案:

答案 0 :(得分:15)

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

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

对我来说,这意味着很明确,而且很短。

答案 1 :(得分:5)

如果要将某些东西转换为另一个,例如字符串为整数,则该方法将在接收器上定义,因此其类是明确的,因此您不应将接收器类作为方法的一部分名称:String#to_i,而不是String#string_to_i。这是面向对象编程(多态)的核心思想之一。

如果接收者过于笼统而无法分配此类方法,例如,如果user_id仅仅是字符串,并且在String上定义方法以将其转换为User则不会看起来正确,那么你应该在类上定义一个你希望返回值为:User.newUser.from_id的构造函数方法。

答案 2 :(得分:5)

在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()
          # ...

答案 3 :(得分:3)

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

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

对于转换,我通常喜欢编写转换方法,以便在高阶函数中使用。例如,在ruby中,转换通常使用to_*实例方法完成,例如将Foo转换为Bar,为所有人设置to_bar方法是有意义的foos,所以你可以写:

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

然后转换一堆foos,你可以简单地说:

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;

答案 4 :(得分:1)

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

a_bar = bar_from(a_foo)

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