Mam tę funkcję API:
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, out Guid code)
Nie podoba mi się to. Ponieważ kolejność parametrów staje się niepotrzebnie znacząca. Trudniej jest dodawać nowe pola. Trudniej jest zobaczyć, co się dzieje. Trudniej jest dokonać refaktoryzacji metody na mniejsze części, ponieważ powoduje to dodatkowe obciążenie związane z przekazywaniem wszystkich parametrów w podfunkcjach. Kod jest trudniejszy do odczytania.
Wpadłem na najbardziej oczywisty pomysł: mieć obiekt hermetyzujący dane i przekazywać go zamiast przekazywania każdego parametru jeden po drugim. Oto co wymyśliłem:
public class DoSomeActionParameters
{
public string A;
public string B;
public DateTime C;
public OtherEnum D;
public string E;
public string F;
}
To zredukowało moją deklarację API do:
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)
Miły. Wygląda bardzo niewinnie, ale tak naprawdę wprowadziliśmy ogromną zmianę: wprowadziliśmy zmienność. Ponieważ to, co wcześniej robiliśmy, polegało na przekazaniu anonimowego niezmiennego obiektu: parametrów funkcji na stosie. Teraz stworzyliśmy nową klasę, która jest bardzo zmienna. Stworzyliśmy możliwość manipulowania stanem rozmówcy . To jest do bani. Teraz chcę, aby mój obiekt był niezmienny, co mam zrobić?
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
}
}
Jak widać, odtworzyłem mój pierwotny problem: zbyt wiele parametrów. To oczywiste, że to nie jest droga. Co ja mam zrobić? Ostatnią opcją osiągnięcia takiej niezmienności jest użycie struktury „tylko do odczytu”, takiej jak ta:
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;
}
Pozwala to uniknąć konstruktorów ze zbyt dużą liczbą parametrów i uzyskać niezmienność. Właściwie to rozwiązuje wszystkie problemy (porządkowanie parametrów itp.). Jeszcze:
- Wszyscy (w tym FXCop i Jon Skeet) zgadzają się, że ujawnianie pól publicznych jest złe .
- Eric Lippert i wsp. Twierdzą, że poleganie na polach tylko do odczytu dla niezmienności jest kłamstwem .
Wtedy zdezorientowałem się i postanowiłem napisać to pytanie: Jaki jest najprostszy sposób w C # na uniknięcie problemu „zbyt wielu parametrów” bez wprowadzania zmienności? Czy można użyć do tego celu struktury tylko do odczytu, a jednocześnie nie mieć złego projektu API?
OBJAŚNIENIA:
- Proszę założyć, że nie doszło do naruszenia zasady odpowiedzialności pojedynczej. W moim oryginalnym przypadku funkcja po prostu zapisuje podane parametry do pojedynczego rekordu DB.
- Nie szukam konkretnego rozwiązania dla danej funkcji. Szukam uogólnionego podejścia do takich problemów. Szczególnie interesuje mnie rozwiązanie problemu „zbyt wielu parametrów” bez wprowadzania zmienności lub okropnego projektu.
AKTUALIZACJA
Podane tutaj odpowiedzi mają różne zalety / wady. Dlatego chciałbym przekształcić to w wiki społeczności. Myślę, że każda odpowiedź z próbką kodu i zaletami / wadami byłaby dobrym przewodnikiem po podobnych problemach w przyszłości. Teraz próbuję dowiedzieć się, jak to zrobić.
DoSomeActionParameters
jest to obiekt jednorazowy, który zostanie odrzucony po wywołaniu metody.