У мене є така функція 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;
}
Це дозволяє нам уникати конструкторів із занадто великою кількістю параметрів і досягти незмінності. Насправді він виправляє всі проблеми (впорядкування параметрів тощо). Ще:
- Усі (включаючи FXCop та Jon Skeet) погоджуються, що оголення публічних полів є поганим .
- Ерік Ліпперт та ін стверджують, що покладатися на поля, які читаються лише для незмінності, є брехнею .
Ось тоді я розгубився і вирішив написати це запитання: який найпростіший спосіб у C # уникнути проблеми "занадто багато параметрів" без введення змінності? Чи можна використовувати структуру для читання лише для цієї мети і все ж не мати поганий дизайн API?
ПОЯСНЕННЯ:
- Будь ласка, припустіть, що немає порушення принципу єдиної відповідальності. У моєму початковому випадку функція просто записує задані параметри в один запис БД.
- Я не шукаю конкретного рішення даної функції. Я шукаю узагальненого підходу до таких проблем. Мені спеціально цікаво вирішити проблему "занадто багато параметрів" без введення змінності або жахливого дизайну.
ОНОВЛЕННЯ
Надані тут відповіді мають різні переваги / недоліки. Тому я хотів би перетворити це на вікі спільноти. Я думаю, що кожна відповідь із зразком коду та плюсами / мінусами стане хорошим посібником для подібних проблем у майбутньому. Зараз я намагаюся з’ясувати, як це зробити.
DoSomeActionParameters
це об'єкт, що викидається, який буде відкинутий після виклику методу.