Strona główna > Java > Jak to z błędem było: prezentowanie wyników wyszukiwania, a stosowanie if

Jak to z błędem było: prezentowanie wyników wyszukiwania, a stosowanie if

Ostatnio natknąłem się na pewien rodzaj błędu. Związany on jest z wyszukiwaniem; gdzie sytuacja jest prosta jak budowa cepa :): podanie kryteriów, wykonanie zapytania, i zaprezentowanie wyników użytkownikowi. Błąd ten jest o tyle złośliwy, ponieważ pojawia się tylko w części przypadków, dlatego też gdy już zostanie wprowadzony trudniejsze jest jego wykrycie.

Geneza jego jest następująca:
Na początek mamy typową wyszukiwarkę, schemat całego postępowania można przedstawić na poniższym obrazku.

Tak więc użytkownik definiuje kryteria wyszukiwania; co przekłada się następnie na odpowiednie zapytanie do bazy. Wynik, z wykonania zapytania, pakowany jest do obiektów (DTO), których to zbiór służy do wygenerowania prezentacji dla użytkownika.

Za pierwszym razem wszytko działa jak należy, ale klient życzy sobie pewnych modyfikacji. W prezentowanych wynikach, w niektórych przypadkach dla zwracanych rekordów wartość X jest nieprawidłowa (jest pusta). Związane jest to z brakiem odpowiednich danych w bazie. Braki te nie są zmartwieniem klienta, chodzi o prezentacje. Dlatego też, życzy on sobie, aby prawidłową wartość X dla tego przypadku pozyskiwać na podstawie innych wartości. Co w kodzie kończy się taką zmianą:

  public String getWartoscX() {
    if (wartoscX == null) {
      // tutaj poprawka
      return wartoscA + wartoscB;
    }
    return wartoscX;
  }

Zmiana jest wprowadzana; teraz wartości w każdym przypadku prezentują się poprawnie; zgłoszenie uznaję się za rozwiązany😉. Jednak wkradł się już błąd. Tutaj łatwiej go zauważyć: kryterium X dla modyfikowanych przypadków nie jest już poprawne. Jak już wspomniałem podmiana wartości X nie występuje zawsze, powiedzmy w 10% zwracanych rekordów, dlatego też błąd ten może istnieć długo zanim zostanie odkryty.

Dlaczego taka sytuacja powstała?
Oczywiście tutaj łatwiej widać absurdalność wykonania tej poprawki. W tym przypadku odpowiednim podejściem może być chociaż wprowadzenie widoku na bazie, co mogłoby wyglądać tak:

select NVL(wartoscX, wartoscA || wartoscB) as wartoscX, wartoscY, wartoscZ from tabela;

Jednak celem moim jest zastanowienie się dlaczego taka sytuacja mogła zajść (Skłoniło mnie do tego znalezienie w ostatnim czasie kliku przypadków takiego błędu):

  • pierwszą i główną przyczyną jest specyficzność przypadku, który dotyczy niewielkiego wycinka danych. Prowadzi to do tego, że osoba wykonująca poprawkę, może się błędnie sugerować prostotą rozwiązania jakie trzeba zastosować, i nie zastanawiać się bardziej nad jego prawidłowością.
  • drugą przyczyną jest złe skupienie uwagi co do miejsca w którym należy rozwiązać błąd. Nie na prezentacji wyników (tam umieszczać logikę rozwiązania), ale na zapytaniu i zwracanych wynikach. Powodem tego może być opis samego zgłoszenia, gdzie całość jest przedstawiona w łopatologicznej formie: „weź wartość A i wartość B; i dodaj do siebie”. Prawie jak poprawka literówki🙂.
  • kolejna sprawa to sugerowanie się domyślnym językiem używanym w pracy. Jak ktoś programuje w javie to łatwiej jest mu rozwiązać problem w tym języku, niż silić się na prace w sql.
  • jeszcze jeden powód to złożoność kodu, skutkujący tym że poprawiający ma trudność w uchwyceniu całego kontekstu. W przypadkach, które znalazłem, było to związane z dużym zamieszaniem w przekazaniu obiektów z danymi. Nie były to proste DTO, ale obiekty encji JPA przepakowane do pośrednich obiektów przy użyciu skomplikowanych reguł.

Ogólna rada na przyszłość to: jeśli poprawka dotyczy wycinka pewnego zbioru przyjrzeć się lepiej rozwiązaniu, traktować to bardziej podejrzliwie niż w przypadku gdy zmiany obejmują cały zbiór. Potrzeba wprowadzenia if_a powinna zapalać czerwone światełko🙂. Skłaniać do zastanowienia się czy w dobrym miejscu ten if jest umieszczany i czy znane są wszystkie miejsca w których powinien on być.
A co do wyszukiwarek dobrze jest rzeźbić je w sql, i nawet jeśli grozi to mnożeniem bytów, stosować szyte na miarę DTO (a nie kombinować z ponownym użyciem innych klas). Także nie umieszczać logiki biznesowej w prezentacji🙂.

Kategorie:Java Tags: , , , ,
  1. Brak komentarzy.
  1. No trackbacks yet.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: