【问题标题】:What to do when function has too many arguments?当函数的参数太多时该怎么办?
【发布时间】:2014-03-17 16:16:08
【问题描述】:

我在 Clojure 中开发了一个系统。我尽量把它写得尽可能实用。其中之一是引用透明性(对于相同的参数,函数应该始终返回相同的结果)。

问题是某些函数(尤其是我的视图和部分控制器)获得了太多 args(比如 5-6 并且将来可能更多)。

你会如何解决这个问题?

我看到了几个可能的解决方案,每个都有优点和缺点。

1) create ParameterMap - 将参数放入 Map 并使用模式 (https://github.com/prismatic/schema) 验证它 - 这是首选解决方案,但此解决方案的问题是我得到运行时错误而不是编译时错误错误(现在应用程序拒绝编译,因为当我忘记重构应用程序的某些部分时,arity 不好)

2) 使用闭包 - 闭包可以捕获命名变量并等待其余的。它检查编译时间。这个解决方案很简单,但让我创建闭包只是为了将大量参数拆分为更多功能,我认为这些功能就像功能性方式来进行贫血设计。这个解决方案类似于使用 monad,似乎没有人认为在步骤中添加参数是不干净的,我不明白为什么。

3) 将参数转换为命名参数 - 我仍然会有大量参数,但它们不再不清楚,因为我一眼就能看出它们的含义。我在应用程序的其他部分使用了这种方法并且它有效。不幸的是,这很容易在运行时出现 NullPointerException,并且不会在编译时检查。

【问题讨论】:

    标签: parameters clojure refactoring


    【解决方案1】:

    嗯,答案在很大程度上取决于您的代码库,但很可能是所有这些因素的组合。

    这不是选择一个或另一个的问题,而是选择最适合各种特定功能的问题。例如,您应该在闭包有意义的情况下使用闭包,在有意义的情况下使用命名参数,并在有意义的情况下使用映射。

    如果您有一堆参数,并且要将这些通用参数传递给许多函数,那么使用映射来包含它们并更清楚地说明参数的实际含义可能是有意义的。

    【讨论】:

    • 命名参数是有争议的(例如,与合并参数映射的能力相比,部分应用和重复键的错误)。
    • 命名参数对于 DSL 和可读性更有用。不过,很容易判断您是否应该使用它们。归结为“我的大多数调用现在都涉及应用吗?”很多时候。
    【解决方案2】:

    扩展评论:

    Paul Graham wrote 以下关于称为 Rtml 的 DSL(其中程序称为模板):

    Rtml 很大程度上依赖于关键字参数,直到那时我都有 一直被认为是 Common Lisp 中比较可疑的特性之一。 ...

    如果我想为其中一个人的行为添加另一个维度 运营商,我可以添加一个新的关键字参数,每个人的 现有模板将继续有效。一些 Rtml 运算符没有采用关键字参数,因为我认为我不会 永远需要改变它们,几乎每一个我最终都踢了 自己约以后。如果我可以回去从头开始, 我要改变的一件事是我会制作每个 Rtml 运算符取关键字参数。

    【讨论】:

      猜你喜欢
      • 2015-10-12
      • 1970-01-01
      • 2014-03-23
      • 2023-03-20
      • 1970-01-01
      • 2012-10-23
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多