Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何避免API设计中参数过多的问题?

如何避免API设计中参数过多的问题?
EN

Stack Overflow用户
提问于 2011-06-04 21:01:08
回答 13查看 34.4K关注 0票数 170

我有这个API函数:

代码语言:javascript
运行
AI代码解释
复制
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d, 
     string e, string f, out Guid code)

我不喜欢这个。因为参数顺序变得不必要地重要。添加新字段变得更加困难。很难看到正在传递的是什么。很难将方法重构为更小的部分,因为这会增加传递子函数中所有参数的额外开销。代码更难读。

我想出了最明显的想法:让一个对象封装数据并传递它,而不是一个接一个地传递每个参数。这是我想出来的:

代码语言:javascript
运行
AI代码解释
复制
public class DoSomeActionParameters
{
    public string A;
    public string B;
    public DateTime C;
    public OtherEnum D;
    public string E;
    public string F;        
}

这将我的API声明简化为:

代码语言:javascript
运行
AI代码解释
复制
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)

好的。看起来很简单,但我们实际上引入了一个巨大的变化:我们引入了可变性。因为我们之前所做的实际上是传递一个匿名的不可变对象:堆栈上的函数参数。现在我们创建了一个非常可变的新类。我们创建了操纵调用者的状态的功能。这太糟糕了。现在我希望我的对象是不可变的,我该怎么办?

代码语言:javascript
运行
AI代码解释
复制
public class DoSomeActionParameters
{
    public string A { get; private set; }
    public string B { get; private set; }
    public DateTime C { get; private set; }
    public OtherEnum D { get; private set; }
    public string E { get; private set; }
    public string F { get; private set; }        

    public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d, 
     string e, string f)
    {
        this.A = a;
        this.B = b;
        // ... tears erased the text here
    }
}

正如您所看到的,我实际上重新创建了我的原始问题:参数太多。很明显,这不是我们应该走的路。我该怎么办呢?实现这种不变性的最后一种选择是使用“只读”结构,如下所示:

代码语言:javascript
运行
AI代码解释
复制
public struct DoSomeActionParameters
{
    public readonly string A;
    public readonly string B;
    public readonly DateTime C;
    public readonly OtherEnum D;
    public readonly string E;
    public readonly string F;        
}

这使我们可以避免使用过多参数的构造函数,并实现不变性。实际上,它解决了所有问题(参数排序等)。然而:

每个人(包括exposing public fields are bad.

就在那时,我感到困惑,并决定写这个问题:在C#中,什么是在不引入易变性的情况下避免“太多参数”问题的最直接的方法?有没有可能使用只读结构来达到这个目的,而不是有一个糟糕的API设计呢?

CLARIFICATIONS:

  • 请假定没有违反单一责任原则。在我最初的例子中,这个函数只是将给定的参数写入到单个数据库记录中。

  • ,我不是在寻找给定函数的特定解决方案。我正在寻求一种通用的方法来解决这些问题。我特别感兴趣的是在不引入易变性或糟糕的设计的情况下解决“太多参数”的问题。

更新

这里提供的答案有不同的优点/缺点。因此,我想把它转换成一个社区维基。我认为每一个带有代码样本和优点/缺点的答案都会成为未来类似问题的很好指南。我现在正在尝试找出如何做到这一点。

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2011-06-04 21:12:52

框架中包含的一种风格通常类似于将相关参数分组到相关类中(但在可变性方面仍存在问题):

代码语言:javascript
运行
AI代码解释
复制
var request = new HttpWebRequest(a, b);
var service = new RestService(request, c, d, e);
var client = new RestClient(service, f, g);
var resource = client.RequestRestResource(); // O params after 3 objects
票数 25
EN

Stack Overflow用户

发布于 2011-06-04 21:59:07

使用构建器和特定于域的语言风格的API的组合--Fluent Interface。API有点冗长,但使用intellisense可以非常快速地输入内容,并且易于理解。

代码语言:javascript
运行
AI代码解释
复制
public class Param
{
        public string A { get; private set; }
        public string B { get; private set; }
        public string C { get; private set; }


  public class Builder
  {
        private string a;
        private string b;
        private string c;

        public Builder WithA(string value)
        {
              a = value;
              return this;
        }

        public Builder WithB(string value)
        {
              b = value;
              return this;
        }

        public Builder WithC(string value)
        {
              c = value;
              return this;
        }

        public Param Build()
        {
              return new Param { A = a, B = b, C = c };
        }
  }


  DoSomeAction(new Param.Builder()
        .WithA("a")
        .WithB("b")
        .WithC("c")
        .Build());
票数 91
EN

Stack Overflow用户

发布于 2011-06-04 21:23:19

这里有一个非常明确的指示,这个类违反了Single Responsibility Principle,因为它有太多的依赖项。寻找将这些依赖项重构为Facade Dependencies集群的方法。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6239373

复制
相关文章
如何避免微服务设计中的耦合问题
译自:How to Avoid Coupling in Microservices Design
charlieroro
2021/03/02
1.7K0
如何避免微服务设计中的耦合问题
CA1005:避免泛型类型的参数过多
泛型类型包含的类型参数越多,越难以知道并记住每个类型参数各代表什么。 它通常有一个类型参数,如在 List<T> 中,而在某些情况下有两个类型参数,如在 Dictionary<TKey, TValue> 中。 如果存在两个以上的类型参数,则大多数用户都会感到过于困难(例如 C# 中的 TooManyTypeParameters<T, K, V> 或 Visual Basic 中的 TooManyTypeParameters(Of T, K, V))。
用户4268038
2022/01/09
1.1K0
如何解决代码中 if…else 过多的问题?
if...else 是所有高级编程语言都有的必备功能。但现实中的代码往往存在着过多的 if...else。虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性、可维护性造成很大伤害,进而危害到整个软件系统。现在软件开发领域出现了很多新技术、新概念,但 if...else 这种基本的程序形式并没有发生太大变化。使用好 if...else 不仅对于现在,而且对于将来,都是十分有意义的。今天我们就来看看如何“干掉”代码中的 if...else,还代码以清爽。
杰哥的IT之旅
2020/06/18
2.2K0
如何解决代码中if…else 过多的问题
if...else 是所有高级编程语言都有的必备功能。但现实中的代码往往存在着过多的 if...else。虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性、可维护性造成很大伤害,进而危害到整个软件系统。现在软件开发领域出现了很多新技术、新概念,但 if...else 这种基本的程序形式并没有发生太大变化。使用好 if...else 不仅对于现在,而且对于将来,都是十分有意义的。今天我们就来看看如何“干掉”代码中的 if...else,还代码以清爽。
java架构师
2019/03/20
3K0
避免在 JS 中过多使用 IF 语句优化技巧
最近在重构代码时,我发现早期的代码使用太多的 if 语句,其程度是我从未见过的。这就是为什么我认为分享这些简单的技巧是非常重要的,这些技巧可以帮助我们避免过多的使用 if 语句。
前端小智@大迁世界
2020/10/26
2.3K0
python避免if-else过多的办法
方法一:来自http://biancheng.dnbcw.net/python/417264.html
py3study
2020/01/06
1.7K0
sparksql udf自定义函数中参数过多问题的解决
在进行spark sql数据库操作中,常常需要一些spark系统本身不支持的函数,如获取某一列值中的字符串。 如要获取 “aaaakkkkk”中的第4-第8个字符。 针对这种需求,只有设置UDF来实现了。 如 val fun:((String,Int,Int) => String) = (args:String, k1:Int, k2:Int) => { args.substr(k1,k2)}  val sqlfunc = udf(fun) df.withColumn("column22", sqlfunc
sparkexpert
2018/01/09
1.8K0
如何在 ClickHouse 中避免深度分页问题
在日常的业务场景中,我们经常会遇到查询 TOP N 的需求。在 ClickHouse 中,一种常见的实现 TOP N 的 SQL 模板如下所示:
Nauu
2020/05/29
8.8K1
Android开发笔记(一百七十九)避免方法数过多的问题
一个大规模的App工程,往往引入了数量繁多的第三方开发库,其中既有官方的Jetpack库,也有第三方厂商的开源包。有时候运行这种App会报错“Cannot fit requested classes in a single dex file (# methods: 65894 > 65536)”,意思是App内部引用的方法数量超过了65536个,导致App异常退出。 原来Android的每个App代码都放在一个dex文件中,系统会把内部方法的索引保存在一个链表结构里,由于这个链表的长度变量是short类型(short类型的数字占两个字节共16位),使得链表的最大长度不能超过65536(2的16次方),因此App方法数超过65536的话,链表索引溢出就报错了。为了解决方法数过多的问题,Android推出了名叫MultiDex的解决方案,也就是在打包时把应用分成多个dex文件,每个dex的方法数量均不超过65536个,由此规避了方法数过多的限制。 若想让App工程支持MultiDex,需要对其略加改造,具体改造步骤说明如下。 首先要修改模块的build.gradle文件,往dependencies节点添加下面一行配置,表示导入指定版本的MultiDex库:
aqi00
2022/03/09
3990
避免 proxysql 跟后端建立过多连接的方法
原文地址: https://www.percona.com/blog/2019/09/27/multiplexing-mux-in-proxysql/
保持热爱奔赴山海
2019/11/21
1.3K0
如何避免你的问题烂尾
本节主要介绍我在工作中遇到了什么问题,遇到问题后我们如何去解决的思考过程,同时下文结合了《提问的智慧》(https://www.cnblogs.com/guyk/p/11000432.html)和个人工作经历整理来介绍“如何避免你的问题烂尾”,如果你在阅读文章过程中有更好的答案或建议欢迎给我留言,我会把好的解决方案(保留原作者)更新到我的文档中。 本文主要以云计算服务提供商“腾讯云”为例,帮助用户如何问高质量的问题,并从问问题的过程中收获更多的知识来提升自己。
研究僧
2020/06/07
2.2K0
解决MySQL中Sleep连接过多的问题
有时候你在mysql中运行SHOW PROCESSLIST;后会发现数据库中有很多这样的进程:
老高的技术博客
2022/12/28
2.6K0
解决MySQL中Sleep连接过多的问题
这些优化技巧可以避免我们在 JS 中过多的使用 IF 语句
最近在重构代码时,我发现早期的代码使用太多的 if 语句,其程度是我从未见过的。这就是为什么我认为分享这些简单的技巧是非常重要的,这些技巧可以帮助我们避免过多的使用 if 语句。
前端小智@大迁世界
2020/05/11
3.3K0
如何避免问渣问题?
其实这个问题已经被无数的人列举过、讨论过、吐槽过。但似乎很多人,特别是初学者/职业的入门者总是在问渣问题,而且自我感觉良好。如果非得要在大学加一门课的话,我特别希望就是“如何避免问渣问题“。并且特别希望它成为必修课之一。 当然,有些人问问题其实并不是在问问题,而可能是在讽刺、挖坑(知乎里特别流行)或者秀逼格。我不是很擅长这些,所以本文不在这些领域班门弄斧。 避免问愚蠢的问题 在提问之前,思考下这个问题是不是非常的愚蠢。尽管所有人(包括我)在内都愚蠢过,并且每个人也并不是会通晓所有领域。但是问的问题过度弱智,
大宽宽
2018/05/14
1.5K2
如何避免 Java 中的“NullPointerException”
NullPointerException (NPE) 是 Java 中最常见的异常。此异常的原因是已知的,但在大多数情况下,开发人员更愿意忽略它并且不采取任何措施。我个人认为这种行为的原因如下:
终码一生
2022/04/15
3K0
如何避免 Java 中的“NullPointerException”
API如何设计
在之前《应对变化》[1]中提到模块之间合的策略:缩小依赖范围,API是两个模块间唯一的联结点
码农戏码
2021/07/29
5570
如何设计 API?
在前后端分离的设计中,不管使用什么语言,后端都需要提供 WebAPI 给前端使用。如果是一个平台级的产品,还有可能需要将平台的公共 API 提供给第三方系统使用,这些都要考虑到 API 的设计。
oec2003
2023/10/25
2450
如何设计 API?
Kotlin 是如何避免空指针问题的
在谈Kotlin的优势的时候,大家都会想到空指针安全这一点,那么Kotlin又是如何避免这些问题的呢?下面从Kotlin的一些语法规则上给出介绍。 可空类型 默认声明的变量是不能为 null 的,如果
xiangzhihong
2018/02/06
2.3K0
Kotlin 是如何避免空指针问题的
在谈Kotlin的优势的时候,大家都会想到空指针安全这一点,那么Kotlin又是如何避免这些问题的呢?下面从Kotlin的一些语法规则上给出介绍。 可空类型 默认声明的变量是不能为 null 的,如果
xiangzhihong
2018/01/26
1.7K0
Go中的死锁以及如何避免
死锁是指两个或更多的进程永久性地互相等待对方释放资源的情况。这通常发生在每个进程都持有至少一个资源,但又需要另一个当前被其他进程持有的资源才能继续执行。
运维开发王义杰
2023/08/10
5240
Go中的死锁以及如何避免

相似问题

如何避免过多的参数传递?

64

如何避免在AsyncTask中传递过多的输入参数?

22

如何在避免“过多参数”的同时执行grep?

50

Python:避免关于过多参数的Pylint警告

101

如何避免过多的If语句?

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档