gpt4 book ai didi

c# - API设计中如何避免 "too many parameters"问题?

转载 作者:IT王子 更新时间:2023-10-29 03:31:17 25 4
gpt4 key购买 nike

我有这个 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)

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

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

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

那时我感到困惑并决定写这个问题:在 C# 中避免“太多参数”问题而不引入可变性的最直接方法是什么?是否可以为此目的使用只读结构,而 API 设计又不会很糟糕?

澄清:

  • 请假设没有违反单一职责原则。在我原来的例子中,该函数只是将给定的参数写入单个数据库记录。
  • 我不是在寻找针对给定功能的特定解决方案。我正在寻找解决此类问题的通用方法。我特别感兴趣的是在不引入可变性或糟糕设计的情况下解决“太多参数”问题。

更新

此处提供的答案各有优缺点。因此,我想将其转换为社区 Wiki。我认为每个带有代码示例和优点/缺点的答案都将为将来类似问题提供很好的指导。我现在正试图找出如何去做。

最佳答案

结合使用构建器和特定领域语言风格的 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());

关于c# - API设计中如何避免 "too many parameters"问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6239373/

25 4 0