Как избежать проблемы «слишком много параметров» при разработке API?

У меня есть эта функция 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;        
}

Это позволяет нам избежать конструкторов со слишком большим количеством параметров и добиться неизменности. Фактически он решает все проблемы (порядок параметров и т. Д.). Тем не менее:

Вот тогда я запутался и решил написать этот вопрос: Какой самый простой способ в C # избежать проблемы «слишком много параметров» без введения изменяемости? Можно ли использовать для этой цели структуру, доступную только для чтения, и при этом не иметь плохого дизайна API?

УТОЧНЕНИЯ:

  • Предположим, что нет нарушения принципа единой ответственности. В моем первоначальном случае функция просто записывает заданные параметры в одну запись БД.
  • Я не ищу конкретного решения для данной функции. Я ищу общий подход к таким проблемам. Меня особенно интересует решение проблемы "слишком большого количества параметров" без введения изменчивости или ужасного дизайна.

ОБНОВЛЕНИЕ

Приведенные здесь ответы имеют разные преимущества / недостатки. Поэтому я хотел бы преобразовать это в вики сообщества. Я думаю, что каждый ответ с образцом кода и плюсами / минусами станет хорошим руководством для решения подобных проблем в будущем. Сейчас пытаюсь понять, как это сделать.

156
задан 3 revs 11 June 2011 в 09:33
поделиться