czwartek, 27 września 2018

Życie bez wyboru

Podczas refaktoryzacji mojego kodu, eliminowaniu powtórzeń, odwracaniu zależności itp... zaczęła mnie dręczyć myśl czy da się wyeliminować instrukcje warunkowe z kodu.
Pierwszy raz te pytanie pojawiło się kilka miesięcy temu gdy oglądałem na pluralsiajcie wykład na temat SOLID-a. Zaciekawił mnie trochę temat, zgłębiłem ale nic szczególnego nie odkryłem.
Dopiero kilka dni temu gdy  oglądałem na yuotubach, filmik o wzorcach projektowych spotkałem się z wzorcem Strategia. W książce "gangu czterech" jest opis, że dzięki "Strategi" można wyeliminować instrukcje warunkowe. Ciekawe, pytanie czy wszystkie IF-?, do tej pory nie umiałem sobie wyobrazić jak miałby wyglądać kod bez IF-a. Czy to możliwe?
Próbowałem tego przy refaktoryzacji filtrów w aplikacji Maratonu, owszem udało się wyeliminować warunki ale nie wszystkie. Zostały te, które uznałem za najpotrzebniejsze, przeniosłem je do osobnych  funkcji.
Temat "strategi" będę jeszcze drążył ale takie proste sposoby na zastąpienia instrukcji warunkowej można by opisać np tak (przykład z mojej refaktoryzacji).:

Mam funkcje, jednym z parametrów jest  "kontrola" typu int (parametr o nazwie kontrola), parametr ten opisuje pewną kolumnę w bazie, która przyjmuje wartość True, False lub null dlaczego i po co nie, ma teraz znaczenia. Oryginalnie tam są jeszcze inne parametry ale je pomijam.
Do nie dawna kod wyglądał by tak

void writeToViewBag(int kontrola)
        {
            if (kontrola == 0)
            {
                ViewBag.kontrola = null;
            }
            if (kontrola == 1)
            {
                ViewBag.kontrola = true;
            }
            if (kontrola == 2)
            {
                ViewBag.kontrola = false;
            }      
      }

Funkcje nic nie zwraca, trzy warunki, sprawdzam stan parametru i na tej podstawie przekierowuje "ruch" i wrzucam wartość do ViewBag-a.
Czym jest dla mnie instrukcja warunkowa? Nie będę pisał regułki bo jej nie pamiętam, opis jaki mi się nasuwa to IF jest jak zwrotnica (szyny, pociąg, itd...) przekierowuje nas na odpowiedni tor, celem dojechania w odpowiednie miejsce tutaj celem jest VieBag.Kontrola i przypisanie wartości ale może być to cokolwiek innego.
To jest sytuacja prosta bo nie mamy zagnieżdżonych warunków, sprawdzamy prostego int-a, a gdy by to był obiekt którego stan determinuje zachowanie całej aplikacji?
Dobra usunę teraz z funkcji instrukcję warunkową, sposobów jest kilka mi się nasuwają dwa ale jest więcej (jak mi się przypomni resztę też napiszę):
  • Dodaje słownik (Dictionary<key,value>) listę: klucz, wartość
  void writeToVieBag(int kontrola)
        {
          Dictionary<int, bool?> slownikKontrola = new Dictionary<int, bool?>();
            slownikKontrola.Add(0, null);
            slownikKontrola.Add(1, true);
            slownikKontrola.Add(2, false);

   ViewBag.kontrola =slownikKontrola.Where(x => x.Key == kontrola).FirstOrDefault().Value;
 }

Uproszczone? tak, difinicja słownika może być poza funkcją,  trzy instrukcje warunkowe zastąpione jedną linijką. Ktoś powie że to nieprawda przecież muszę zdefiniować "slownikKontrola" tak ale  mogę go wykorzystać w wielu miejscach. Jeżeli będę musiał zwiększyć liczbę możliwości odszukam definicję słownika i po prostu dodam kolejne pozycje. Zmiana typów to też nie jest problem.
  • Dodaje klasę SlownikKontrola

public class SlownikKontrola

        {
            public int key { get; set; }
            public bool? Value { get; set; }
        }

void writeToViewBag(int kontrola, bool popup, string komunikat, bool kontrolaPonowna)
        {

            List<SlownikKontrola> lista = new List<SlownikKontrola>();
            lista.Add(new SlownikKontrola { key = 1, Value = null });
            lista.Add(new SlownikKontrola { key = 2, Value = true });
            lista.Add(new SlownikKontrola { key = 3, Value = false });
            ViewBag.kontrola = lista.Where(x => x.key == kontrola).FirstOrDefault().Value;
        }

Zalety takie jak w przypadku słownika, tylko trochę więcej pisania (definicja klasy) ale można był by poprzez interfejs zrobić i nie powoływać obiektu do życia tylko wywołać samą metodę typu 
bool? getElementOfTheSlownik(int kontrola), która zwróci nam konkretną wartość, zależność odwrócić. 

To akurat proste przykłady, temat sposobów zastąpienia instrukcji warunkowej się nie wyczerpał.A dlaczego poruszyłem? no cóż ciekawi mnie to czy faktycznie da się osiągnąć pełne zastąpienie IF-a.
Myślę, że zysk był by duży ale czy kod nie okazał by się zbyt skomplikowany, a nakład pracy większy niż spodziewany efekt?
Za nie długo się dowiem...


Brak komentarzy:

Prześlij komentarz

 Po wielu miesiącach przerwy Czteroletnim exodusie do bloga ismartdev, który zdechł w zeszłym roku w listopadzie, na powrót wstąpiłem w ten ...