如何避免"太多的参数"在API设计的问题? [英] How to avoid "too many parameters" problem in API design?

查看:139
本文介绍了如何避免"太多的参数"在API设计的问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个API函数:

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

我不喜欢它。由于参数顺序变得不必要显著。它变得更难增加新的领域。这是很难看到什么正在传递。这是很难重构方法成较小的部分,因为它创建传递的所有参数子功能的另一个开销。 code是难以阅读。

I don't like it. Because parameter order becomes unnecessarily significant. It becomes harder to add new fields. It's harder to see what's being passed around. It's harder to refactor method into smaller parts because it creates another overhead of passing all the parameters in sub functions. Code is harder to read.

我想出了最明显的想法:有一个对象封装数据,并通过它而不是一个路过的每个参数由一个。以下是我想出了:

I came up with the most obvious idea: have an object encapsulating the data and pass it around instead of passing each parameter one by one. Here is what I came up with:

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

这是我的API声明简化为:

That reduced my API declaration to:

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)

尼斯。看起来很无辜,但我们实际上引入了一个巨大的变化:我们推出的可变性。因为我们previously一直在做,实际上传递一个匿名的不可变对象:在堆叠功能参数。现在,我们创建了一个新类,这是非常易变的。我们创建操纵的来电者的状态的能力。 ,吸。现在我想我的对象不可变的,我该怎么办?

Nice. Looks very innocent but we actually introduced a huge change: we introduced mutability. Because what we previously had been doing was actually to pass an anonymous immutable object: function parameters on stack. Now we created a new class which is very mutable. We created the ability to manipulate the state of the caller. That sucks. Now I want my object immutable, what do I do?

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

正如你可以看到我居然重新创建了原来的问题:太多的参数。很明显,这不是要走的路。我该怎么办?最后一个选项来实现这种不变性是使用只读结构是这样的:

As you can see I actually re-created my original problem: too many parameters. It's obvious that that's not the way to go. What am I going to do? The last option to achieve such immutability is to use a "readonly" struct like this:

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

这让我们避免了构造带太多的参数,实现不变性。实际上,它解决所有的问题(参数排序等)。然而:

That allows us to avoid constructors with too many parameters and achieve immutability. Actually it fixes all the problems (parameter ordering etc). Yet:

  • Everybody (including FXCop & Jon Skeet) agree that exposing public fields are bad.
  • Eric Lippert et al say relying on readonly fields for immutability is a lie.

这时候,我糊涂了,并决定写这样一个问题:是什么在C#中最直接的方法,以避免太多的参数的问题,而不会引入可变性?是否有可能使用只读结构为目的,尚未有一个坏的API设计?

That's when I got confused and decided to write this question: What's the most straightforward way in C# to avoid "too many parameters" problem without introducing mutability? Is it possible to use a readonly struct for that purpose and yet not have a bad API design?

说明:


  • 请假设没有违反单responsibiltiy原则。在我原来的情况下,函数只是写定的参数到一个单一的数据库记录。

  • 我不寻求具体的解决办法,以给定的函数。我在寻找一个通用的方法来这样的问题。我在解决太多的参数的问题,而不会引入可变性或可怕的设计特别感兴趣。

更新

这里提供的答案有不同的优势/劣势。因此,我想将其转换为一个社区维基。我想用code样品和优点每个答案/缺点将使在今后类似的问题一个很好的指南。现在,我试图找出如何做到这一点。

The answers provided here have different advantages/disadvantages. Therefore I'd like to convert this to a community wiki. I think each answer with code sample and Pros/Cons would make a good guide for similar problems in the future. I'm now trying to find out how to do it.

推荐答案

使用建设者和特定领域的语言风格的API的组合 - 流畅的界面。该API是一个小更详细但随着智能感知是非常快的打字出来,很容易理解。

Use a combination of builder and domain-specific-language style API--Fluent Interface. The API is a little more verbose but with intellisense it's very quick to type out and easy to understand.

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());

这篇关于如何避免"太多的参数"在API设计的问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆