首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何避免API设计中参数过多的问题?

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

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

我有这个API函数:

public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d, 
     string e, string f, out Guid code)

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

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

public class DoSomeActionParameters
{
    public string A;
    public string B;
    public DateTime C;
    public OtherEnum D;
    public string E;
    public string F;        
}

这将我的API声明简化为:

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)

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

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
    }
}

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

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-05 05:12:52

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

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-05 05:59:07

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

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-05 05:23:19

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

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

https://stackoverflow.com/questions/6239373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档