V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awesomePower
V2EX  ›  Java

一个方法很多参数,算是好的设计还是不好的设计

  •  
  •   awesomePower · 2024-07-11 08:37:29 +08:00 · 7030 次点击
    这是一个创建于 396 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,一个方法含有十几个参数,这算是糟糕的设计还是好的设计,还是无所谓。 有这方面的标准么?

    50 条回复    2024-07-12 16:50:52 +08:00
    iOCZS
        1
    iOCZS  
       2024-07-11 08:40:33 +08:00
    看情况,偶时候难免
    maokg
        2
    maokg  
       2024-07-11 08:41:37 +08:00
    Android 源码倒有很多方法是很多参数的,但会在方法里调方法,f1(var a, var b, var c, var d){ f2(var ... x)}
    yazinnnn0
        3
    yazinnnn0  
       2024-07-11 08:43:34 +08:00   ❤️ 3
    能像 kotlin 那样有默认值就不是遭设计, java 这种想要默认值需要重载无数个的是糟设计
    goxxoo
        4
    goxxoo  
       2024-07-11 08:45:00 +08:00   ❤️ 1
    十几个算啥? 我遇到过一个接口里大几十个参数的, 连调用哪个参数实现功能,都特么没写的
    qping
        5
    qping  
       2024-07-11 08:46:28 +08:00 via Android   ❤️ 3
    实在太多,就建个 options 类,包一下。我们想要参数越少越好,但有时候很困难
    jackmod
        6
    jackmod  
       2024-07-11 09:09:40 +08:00
    有条件就包装成新的类。含义相似参数塞太多是很糟糕的,但一般这种时候都可以甩锅🐶
    比如有些 ORM 不支持动态数量的参数(或者说传一个 List ),那就只好塞到 255 个了🐶
    woodfizky
        7
    woodfizky  
       2024-07-11 09:13:53 +08:00
    举个例子,ElasticSearch 的 Python 包,8.0.0 的,AsyncElasticSearch 类的 search 实例方法,我数了一下大概 60 多个参数。。不过全部是默认参,进到方法里面再具体做了参数校验或判断,一般情况实际传进去的参数比较少。

    有时候没办法啊,场景就决定了参数多。

    你可以把用途比较统一的,属于某个模块的一系列参数写到一个类/字典里,传参的时候传单个对象,避免方法调方法还要多次传多个参。
    HackerJax
        8
    HackerJax  
       2024-07-11 09:17:52 +08:00
    python 那种不依赖参数顺序且有默认值的可以,PHP 那种强依赖顺序的就不行,
    loryyang
        9
    loryyang  
       2024-07-11 09:19:14 +08:00
    主要看是否有冗余,而解决参数多的代码结构问题,可以用参数类来包装
    ychost
        10
    ychost  
       2024-07-11 09:21:38 +08:00
    超过 3 个参数就觉得不友好了
    shunia
        11
    shunia  
       2024-07-11 09:26:35 +08:00
    主要看是否有文档,有文档都是好设计,没文档你写出花来我用的时候也得骂你。
    Spute
        12
    Spute  
       2024-07-11 09:28:38 +08:00   ❤️ 2
    从设计的角度看,参数越多代表依赖的输入越多,意味着耦合性越高,这让相关代码很难修改,这个函数也难被复用。所有如非必要,方法的参数应该做的最少且必要。
    LowBi
        13
    LowBi  
       2024-07-11 09:29:33 +08:00
    算坏吧 多了可以选择放到一个对象里
    InkStone
        14
    InkStone  
       2024-07-11 09:30:05 +08:00
    参数太多的情况下应该通过结构体传入,正好结构体的 build 还能降低参数构造的复杂度。

    另外基本类型参数太多时,应该通过封装类型做区分,便于使用。

    尽量不要通过 key 为 string 的 map 传参数,每次看到这种东西都想砍人
    junmoxiao
        15
    junmoxiao  
       2024-07-11 09:35:02 +08:00
    百分百算差的,这种就该定义结构体
    shawnsh
        16
    shawnsh  
       2024-07-11 09:36:27 +08:00 via Android
    好与坏的标准是什么
    NizumaEiji
        17
    NizumaEiji  
       2024-07-11 09:37:45 +08:00
    当然不好 且不提参数多了写方法调用的时候很容易出错
    到时候有需要新增个参数 方法签名一变,一改一个不吱声。到时候要么改动上游调用代码 要么自己搞方法重载。
    所以一般超过一定的参数数量都是要求把入参合并到一个对象里。

    我目前见过参数最多的就是 go 的 wire ,不过好在这玩意儿中间的一些代码都是生成出来的,不用手动改,要不头都大了。
    magicfield
        18
    magicfield  
       2024-07-11 09:38:57 +08:00
    静态语言方法放一堆参数勉强能接受,但最好还是整个对象。
    动态语言一个方法塞一堆参数,甚至用**kwargs 这种狗屎特性之类,有时候真的想砍人
    Govda
        19
    Govda  
       2024-07-11 09:45:37 +08:00
    @HackerJax php8 已经改了,可以跟 Python 一样
    Rache1
        21
    Rache1  
       2024-07-11 09:53:17 +08:00
    @HackerJax #8 PHP 8.0 开始也支持像 Py 那样的命名参数了
    yanqing07
        22
    yanqing07  
       2024-07-11 09:53:55 +08:00
    @maokg #2 四个还好吧。五个参数我接受不了,IDE 提示要用滚动条了
    adoal
        23
    adoal  
       2024-07-11 09:55:51 +08:00
    平行的十几个参数,大概率是没设计好。至少应该按照参数的业务亲密性分组,封装到结构类型里。而且,很有可能,这个接口可以做拆分成更细的接口,或者对调用逻辑做重组设计。
    0xD800
        24
    0xD800  
       2024-07-11 09:58:21 +08:00
    不好的设计,应该放到一个结构体里面,否则接口签名变动的时候就抓狂了
    Rorysky
        25
    Rorysky  
       2024-07-11 10:05:00 +08:00
    封装在参数对象里
    miaotaizi
        26
    miaotaizi  
       2024-07-11 10:06:54 +08:00
    你确定你的场景都会把十几个参数都传吗?

    要不整理一下场景, 把函数重载一下?
    wqhui
        27
    wqhui  
       2024-07-11 10:10:37 +08:00
    有时候可以选择用个对象装载所有字段,也可以选择拆出来每个字段传参

    一般情况下,如果对象有 20 个字段,但方法只用到了其中 5 个,我倾向于只传这 5 个用到的字段,而不是整个对象丢进去,主要是为了明确这个方法只会被这几个字段影响运行,而不需要看方法具体逻辑。当然不嫌麻烦的话,为这个方法新建一个传参的对象装这 5 个字段也 ok ,参数多的话建议后者
    Cabana
        28
    Cabana  
       2024-07-11 10:11:42 +08:00
    哈哈, 写 Compose 的已经麻木了~
    aolifu
        29
    aolifu  
       2024-07-11 10:15:34 +08:00
    之前看过一个 OP 发的帖子,说是他们有的方法一百多个参数,我都惊了 /🤦‍♂️
    Sfilata
        30
    Sfilata  
       2024-07-11 10:17:11 +08:00
    我觉得主要看这个方法很多参数是不是有默认值。如果说正常使用,我可以只传一两个参数就可以使用通用功能,需要微调可以传特定的参数来改变行为的话,我觉得就是一个很好的设计。而且我感觉很多 shell 命令就是这么干的。
    UIXX
        31
    UIXX  
       2024-07-11 10:39:01 +08:00
    代码结构设计是一种平衡艺术,天平的两端可以是易调用性和易调试性。

    当然可以将几百个参数封装成大众接受数量的结构体,但这同时意味参数层级+1 ,在没有额外针对该结构的接口时,我更倾向于将它展开,除了更清晰的逻辑以及奥卡姆剃刀原则之外,显式地强调其中某些参数的用法也是这样设计的重要原因。
    lonelee
        32
    lonelee  
       2024-07-11 10:41:08 +08:00
    java 代码的话是不好的设计,
    kotlin 代码使用默认值+参数名指定完全没问题
    yb2313
        33
    yb2313  
       2024-07-11 10:42:55 +08:00
    喜欢多, 那就写**kwargs
    xz410236056
        34
    xz410236056  
       2024-07-11 10:50:31 +08:00
    所以现在新语言都有可变参数的设计,调用的时候你想传什么传什么
    xueling
        35
    xueling  
       2024-07-11 11:10:32 +08:00
    太多参数不好,完全没有复用性。
    NoOneNoBody
        36
    NoOneNoBody  
       2024-07-11 11:54:37 +08:00
    类方法没所谓,通过设计模式或者继承、抽象就能固定某些参数了
    参数太多难点是逻辑,里面估计很多判断
    底层的基础类参数多些能兼顾不同的“状态”,专用的符合业务模型的就继承基础类固定参数
    opengps
        37
    opengps  
       2024-07-11 11:57:22 +08:00
    这是按需,没法去界定啥。当然针对具体业务可能有更优的方案
    9c04C5dO01Sw5DNL
        38
    9c04C5dO01Sw5DNL  
       2024-07-11 13:06:31 +08:00
    @aolifu 有代码吗,看看
    tairan2006
        39
    tairan2006  
       2024-07-11 14:02:21 +08:00
    一般是不好的,不过有默认值的话有时候也可以,主要看还能不能保持常规情况下使用较为简单
    debuggeeker
        40
    debuggeeker  
       2024-07-11 14:45:37 +08:00
    参数多不是问题,把每个参数注释写清楚就行
    aolifu
        41
    aolifu  
       2024-07-11 15:23:40 +08:00
    @giiiiiithub 没有呢,有机会的话我也想涨涨见识
    blackmirror
        42
    blackmirror  
       2024-07-11 18:08:10 +08:00
    外包赶进度赚快钱就好,自己项目写就差
    yemuc
        43
    yemuc  
       2024-07-11 19:15:43 +08:00   ❤️ 1
    以前遇到过项目中全部使用 map 传参,想要多少参数就多少参数,整理接口时爽的要死
    dddd1919
        44
    dddd1919  
       2024-07-11 21:35:54 +08:00
    方法设计至多一个参数也行,这个参数可以有 n 多属性
    Ericcccccccc
        45
    Ericcccccccc  
       2024-07-11 21:39:32 +08:00   ❤️ 1
    多不是问题
    最好是:
    正交
    枚举清晰
    lisongeee
        46
    lisongeee  
       2024-07-11 23:27:15 +08:00
    java 没有像 kotlin/python/js 一样的具名参数+默认参数,所以这块参数多起来比较难维护吧

    fun test(name:String, age:Int, x: Int=0, y:Int=0){}

    test("my_name", 18)
    test(name="my_name", age=18)
    test("my_name", 18, y=9)
    xiangyuecn
        47
    xiangyuecn  
       2024-07-11 23:34:27 +08:00
    看情况吧:
    自己写的:这风格非常棒
    别人写的:纯属屎山雕花
    facebook47
        48
    facebook47  
       2024-07-12 07:02:07 +08:00 via Android
    不好,不说写麻烦,调用也累……确实🈶很多,封装一下最好
    cc666
        49
    cc666  
       2024-07-12 16:20:22 +08:00
    按照代码整洁之道的说法,这是不好的设计,一般不超过三个参数,参数多了函数内部的认知复杂度基本也会很高(很多的 if-else ),说简单点就是没封好
    enjoyCoding
        50
    enjoyCoding  
       2024-07-12 16:50:52 +08:00
    两三个必传的, 几十个可选的不会觉得是糟糕的涉及. 十几个全是必传的, 那是挺难用的.
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1445 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 16:59 · PVG 00:59 · LAX 09:59 · JFK 12:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.