【问题标题】:When a method has too many parameters? [closed]当一个方法有太多参数时? [关闭]
【发布时间】:2010-02-11 14:01:14
【问题描述】:

今天在调试一些 Web 服务客户端代码时(在 Java 中,使用 jax-ws),我遇到了一个具有 97 个参数的 Web 服务方法!

我不得不创建一个调用这个方法的测试用例,我注意到了几件事:

  • 代码辅助/悬停不能很好地扩展。我使用的是 Eclipse,该方法的工具提示与屏幕一样宽,跨越几行。
  • 我不得不从以前的 xml 捕获中复制参数值,而且几乎不可能记住“我在哪里” - 当我将光标定位在逗号之后并且在输入一些值之前,我经常弄错数据类型- 我输入的是整数而不是字符串,反之亦然。
  • 即使我写了所有的参数,我仍然有一些错误,签名不匹配。不幸的是,Eclipse 将整行标记为有错误,因此查找错误所在的位置需要更多时间:(

所以这让我想到,你认为一个方法的最大合理参数数量是多少?如果您可以更改此 Web 服务签名,您认为可以如何改进?

【问题讨论】:

  • 改为传递参数名称/值的字典?
  • @pisswillis,我想到了,也许它对常规方法很有用,但是对于 web-service,它破坏了合同的全部意义。您还会遇到如何将 dict 序列化为 xml 的问题,并且您的数据模型变得更加轻松(dict 可能有缺失值等)。
  • 97 个参数!?听起来像是每天的 WTF。
  • 97?!不改,申请吉尼斯纪录!
  • @ragu.pattabi:不是记录:stackoverflow.com/questions/174968/….

标签: language-agnostic ide parameters


【解决方案1】:

没有明确的限制,但我对超过 3-4 个参数感到不舒服。 Clean Code 的 AFAIR 叔叔 Bob Martin 建议最多 3 个。

有几个重构可以减少方法参数的数量(请参阅Working Effectively with Legacy Code,Michael Feathers 的详细信息)。我想到了这些:

  • 将许多相关参数封装到一个对象中(例如,代替 String surName, String firstName, String streetAddress, String phoneNumber 传递包含这些字段的 Person 对象)
  • 在调用此方法之前在构造函数或其他方法调用中传递参数

【讨论】:

  • +1 提到了 WELC,这是处理现实世界的绝佳资源。
  • +1 表示“没有明确的限制”,因为我认为 Bob 大叔对 max 的严格限制。 3个参数太教条了。这可能会导致奇怪的解决方法,例如隐藏依赖项和破坏线程安全的附加变量(例如,在“清洁代码”第 73 页重构 PrimeGenerator.java)。
  • WELC 的另一个 +1,它是一个真正的宝石。
【解决方案2】:

当你不得不问的时候,它可能太多了。

【讨论】:

  • 与这个完全相同的问题中接受的答案基本相同:stackoverflow.com/questions/174968/…
  • 呃,抱歉。我在发布之前查找了重复项,但也没有找到您所指的那个
【解决方案3】:

正如 Steve McConnell 在 Code Complete 中提到的,黄金法则是 4 +/-3 个参数。对于普通人来说,很难记住超过 4 个参数,5-7 应该只在特殊情况下使用,并且永远不要使用 8 或更多。

【讨论】:

  • 提神必+1
【解决方案4】:

大佛!!九十七????

良好的做法通常建议最大。六到八。当然,ymmv,也有可能是有正当理由的,时不时换个九分。但是97??!!

一些想法......这些仅仅是数据,还是基于它们的价值观做出的决定?

如果很多/大部分影响流控制,那么您的“设计”几乎无法维护(甚至是可理解或可测试的)(对于较小的“设计”值)。

如果它们只是数据,是否可以将它们分组为结构和指针,而不是传递的那些结构?

您有任何设计文档吗?这可以解释发生了什么。

哦,还有,“Danger, Will Robinson”——任何公开传递 97 个参数的人也可以传递任意数字——不是很明显——作为全局变量。

P.s 不知道 Eclipse 在 Java 上是如何工作的,但是对于 C/C++,如果你把参数放在不同的行上

char DoEverything(
        int meaninglessParameterName1,
        char *meaninglessParameterName2,
        ....
        long double *meaninglessParameterName97)
        { return !NULL;}

Eclipse 将实际识别带有错误参数的行

【讨论】:

    【解决方案5】:

    好吧,如果你把它变成一个 JSON 对象,你可以将所有 97 个(或更多)包装在那个对象中,并且只发送一个对象。

    【讨论】:

      【解决方案6】:

      如果它的参数超过 5-10 个,则创建一个接受参数的对象,它可以是类型化的数据集、结构或其他。

      而不是:

      Mywebservice.CreateUser(Firstname, LastName, Age,Sex, Haircolor,AmountOfFingers,AmountOfTeeht,Childrens,,,,,,,,,,,,,and so on)
      

      做:

      Dim MyUser as new UserObject
      MyUser.Firstname="Stefan"
      ...and so on...
      MyWebservice.CreateUser(UserObject)
      

      【讨论】:

      • 实际上,创建一个包含 97 个字段的对象听起来也很可怕。
      • @gooli,是的。因此,您将其分解为与主对象相关的更多子对象。街道、国家、邮政编码字段作为地址对象,电话和邮件地址作为联系人字段等等。它在 db-normalization 和使用类方面的常识。 ;)
      【解决方案7】:

      根据我自己的经验,我发现如果参数超过 5 或 6 个,方法签名开始变得混乱且难以记忆。一旦你超过 10 个参数,那就太荒谬了。

      这些参数确实需要组合成一个包含所有数据的对象(或一小组对象)。在我使用的服务中,每个服务操作总是接受一个 Request 对象并返回一个 Response 对象。

      【讨论】:

        【解决方案8】:

        就 Web 服务而言,我更喜欢将参数作为单个对象来处理。虽然您的数据合同可能会改变,但您的服务合同不会。这使您的服务更具前瞻性。

        对于其他一切,我支持 3 个参数,偶尔会达到 5 个。

        【讨论】:

          【解决方案9】:

          好吧,我建议重载该方法,以便您可以更简单地实现该方法。如果许多参数很少更改并且可以分配默认值,这可能特别有用。但是,如果没有记错的话,我认为您不能重载 Web 服务调用(您必须使用不同的方法名称)。

          另一种可能的解决方案是将参数封装到某种元数据类中,其目的是保存参数。这将简化方法签名。但是,在某些方面,您只是将问题转移到参数类。但是,如果可以将参数分类为主题,则可以通过利用多个元数据类来使用该技术,每个元数据类都将作为参数包含在 Web 服务中。这应该可以简化事情并帮助您了解这个怪物。

          最后,很难说没有任何细节,但显然这段代码是重构的重要候选者。除了遵循简单易读的一般原则之外,我对方法的参数数量没有硬性规定。

          【讨论】:

            猜你喜欢
            • 2012-11-22
            • 1970-01-01
            • 2022-12-22
            • 2013-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-03
            • 1970-01-01
            相关资源
            最近更新 更多