How to avoid "too many parameters" problem in API design?

What you have there is a pretty sure indication that the class in question is violating the Single Responsibility Principle because it has too many dependencies. Look for ways to refactor those dependencies into clusters of Facade Dependencies.


One style embraced in the frameworks is usually like grouping related parameters into related classes (but yet again problematic with mutability):

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

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

Just change your parameter data structure from a class to a struct and you’re good to go.

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

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code) 

The method will now get its own copy of the structure. Changes made to the argument variable cannot be observed by the method, and changes the method makes to the variable can not be observed by the caller. Isolation is achieved without immutability.

Pros:

  • Easiest to implement
  • Least change of behavior in underlying mechanics

Cons:

  • Immutability is not obvious, requires developer attention.
  • Unnecessary copying to maintain immutability
  • Occupies stack space