Jak przekonać członków zespołu o istnieniu „mandelbug”

20

Opracowujemy aplikację; zawiera bibliotekę opracowaną przez innego programistę, ta biblioteka komunikuje się z serwerem za pośrednictwem wielu połączeń sieciowych, a to wymaga współpracy wielu wątków. Kod po stronie serwera jest dość skomplikowany i nie mamy dostępu do kodu źródłowego.

Ostatnio odkryłem, że czasami występuje błąd powodujący awarię aplikacji. Mógłbym to odtworzyć raz i uzyskać ślad stosu, więc otworzyłem raport o błędzie. Sam błąd można łatwo naprawić (nieprzechwycony wyjątek sieciowy w jednym z wątków w tle, który powoduje, że CLR kończy działanie programu).

Problem polega na tym, że programista odmawia naprawy błędu, ponieważ „nie jest przekonany, że istnieje”. Niestety dla mnie szef jest po jego stronie i mówi, że tego błędu nie da się naprawić, chyba że zrobię „solidny test”, aby udowodnić istnienie błędu i przeprowadzić test jednostkowy w celu sprawdzenia, czy zniknął. Co jest w zasadzie niemożliwe z powodu natury błędu.

Jakakolwiek rada?

fithu
źródło
12
Powiedziałbym, że to całkiem proste. Utwórz test jednostkowy, który potwierdzi, że to, co mówisz, jest prawdą.
Charles Sprayberry
1
Czy zapisałeś stacktrace w jakiejś formie? Np. Czy masz zrzut ekranu swojego IDE pokazujący ślad stosu awarii?
Giorgio
7
@fithu: jesteś trochę zbyt przekonany, że odtworzenie tego rodzaju błędu jest niemożliwe - może być trudne, ale rzadko „niemożliwe”. A skąd możesz wiedzieć, że błąd można łatwo naprawić, gdy nie masz dostępu do kodu źródłowego? Samo złapanie wyjątku może tak naprawdę nie rozwiązać problemu. A może mówisz o kodzie biblioteki, do którego masz dostęp, a już dokładnie wskazałeś linię, w której pojawia się błąd? Jeśli tak, to dlaczego nie zaproponujesz poprawki w kodzie?
Doc Brown
2
@fithu: twój oryginalny tytuł był czymś w rodzaju sprzeczki z szefem. Zmieniłem to w nadziei, że zapobiegnie to szybkiemu zamknięciu twojego pytania, rantsy nie są zbyt popularne na tej stronie. Jeśli nowy tytuł nie odzwierciedla twojego pytania poprawnie, możesz go ulepszyć.
Doc Brown
4
@Giorgio: ślad stosu jest dowodem na to, że program może ulec awarii w określonej linii, nie dowodzi, że linia ta jest główną przyczyną błędu. To wydaje się być faktem, że OP źle zrozumiał, i dlatego miałem problemy ze zrozumieniem niektórych pytań.
Doktor Brown

Odpowiedzi:

35

Jeśli to możliwe, poświęć trochę czasu, aby sprawdzić, czy tę wadę można odtworzyć , wprowadzając trochę snu lub blokady w kodzie aplikacji. Ale nie spędzaj zbyt wiele czasu. Ponieważ ten problem wynika z wielorakiej interpretacji (a także, jak zauważyłeś), jego występowanie będzie rzadkie.

Radzę, żeby się nie przejmować zbyt mocno. Kontynuuj swoją pracę. Ilekroć natkniesz się na tę awarię, zaktualizuj swój raport o błędzie za pomocą śledzenia stosu, mówiąc, że jest to powtórzenie i zmieniając właściciela na programistę biblioteki. Pozwól kierownictwu / klientowi zdecydować, czy to naprawić, czy nie, w zależności od jego częstotliwości.

Spróbuj także zrozumieć mentalność programisty. Powiedziałeś „nieprzechwycony wyjątek internetowy”. Deweloper na tym etapie może nie być do końca pewien, jakie będą inne skutki złapania tego . Być może niechętnie dotyka kodu.

Manoj R.
źródło
10

Tak więc, na podstawie twoich mniej lub bardziej wyjaśniających komentarzy, otrzymałem to w ten sposób:

Jesteś pewien, że brakuje tylko prostej dodatkowej obsługi wyjątków i już wiesz, która linia kodu w lib jest problematyczna i jak można ją naprawić.

Dlaczego więc nie dodasz kilku brakujących wierszy kodu do biblioteki, poproś zespół o przetestowanie biblioteki z tymi zmianami? Upewnij się, że jest to zmiana niskiego ryzyka, łatwa do zrozumienia dla twórcy odpowiedzialnego za lib. Najgorsze, co może się zdarzyć, to to, że ktoś musi cofnąć tę zmianę w twoim VCS, jeśli twoja poprawka powoduje jakieś nieoczekiwane zachowanie.

Większość ludzi łatwiej przekonać, kiedy praca jest już wykonana. Ponadto lepiej reagują na „tutaj jest ulepszone rozwiązanie”, w przeciwieństwie do „ten kod jest nieprawidłowy, jakoś go naprawić”.

EDYCJA: gdy deweloper nadal odmawia dodania tej zmiany, najlepszą opcją jest próba sprawienia, by problematyczny kod działał w odizolowanej wiązce testowej, w której symulujesz błąd sieci. Skuteczna praca ze starszym kodem opisuje wiele technik radzenia sobie z tego rodzaju problemami. Na przykład możesz utworzyć testową wersję biblioteki, zawierającą tylko problematyczne moduły i funkcje, i stworzyć wokół niej „fałszywe środowisko”, w którym można symulować „wyjątek sieciowy” w kontrolowanych warunkach. Na pierwszy rzut oka może to wydawać się zbyt dużym wysiłkiem, ale kiedy już masz takie środowisko, możesz dodać do niego wiele dodatkowych testów (i myślę, że to będzie miało sens, ponieważ kiedy autor biblioteki odmawia dodania brakującego obsługa wyjątków w jednym miejscu,

Doktor Brown
źródło
Odmawia połączenia tej zmiany, ponieważ „nie jest to konieczne”
2013 r
@fithu: zobacz moją edycję.
Doc Brown
4
@DocBrown +1 dla Oni (ludzie) lepiej reagują na „tutaj jest ulepszone rozwiązanie”, w przeciwieństwie do „ten kod jest nieprawidłowy, jakoś to naprawić”.
laika
2
@fithu: Wymyśl więc przypadek testowy, który wyzwala nieobsługiwany wyjątek. Tzn. Znajdź parametry, które go wyzwalają.
wirrbel
2

W przypadku błędu takiego jak ten, automatyczne testowanie fuzzów (zwane również testowaniem losowym) może być pomocne w próbie jego odtworzenia. To automatyzuje proces znajdowania błędu, losowo ustalony zestaw parametrów (lub danych wejściowych) w testowanej rzeczy. Przy każdym uruchomieniu testowym parametry są zapisywane w pliku dziennika, w tym znaczniki czasu itp., Dzięki czemu po awarii można (teoretycznie) odtworzyć test, używając tych samych parametrów, aby go odtworzyć.

Od momentu zautomatyzowania proces testowy może przeprowadzić wiele testów w krótkim czasie. Często można go uruchomić przez noc, a rano można sprawdzić plik dziennika, aby sprawdzić, czy odtworzył awarię.

dodgy_coder
źródło
3
„po prostu powtórz test, używając tych samych parametrów, aby go odtworzyć” - tak naprawdę nie jest to możliwe w przypadku problemów z wątkami / siecią. Ale podoba mi się ten pomysł.
fithu
2

Adwokat diabła sugeruje inną ścieżkę.

Drugi programista stwierdził wprost, że nie ma tam żadnego błędu.

Czy potrafisz wymyślić sposób, by zestresować się z jego rzekomo nieistniejącym błędem i sprawić, że często ulega awarii?

John R. Strohm
źródło
2

Ślad stosu jest wyraźnym dowodem na to, że błąd istnieje, a przynajmniej istniał w określonej wersji. To, czego nie masz, to dowód, że błąd został naprawiony. Głupotą jest ignorowanie tego. Błędy były „niemożliwe do odtworzenia” po setkach tysięcy zautomatyzowanych prób na wielu systemach, które były uruchamiane za każdym razem w systemie klienta.

Dostaję kilka takich błędów rocznie, większość bez nawet śladu stosu. W prawie każdym przypadku, mimo że nie mogłem go wcześniej odtworzyć, z łatwością mogłem wykonać zautomatyzowany test po jego naprawieniu.

Na przykład kilka miesięcy temu naprawiłem błąd, który pojawiał się tylko wtedy, gdy użytkownik pisał szybciej niż 96 słów na minutę. Zanim to naprawiłem, wiedziałem tylko, że błąd zdarzał się „czasami”. Nigdy nie przyszło mi do głowy, aby napisać test jednostkowy do szybkiego pisania. Jednak po tym, jak poznałem pierwotną przyczynę, wykonanie tego testu było banalne.

Nawet w tych rzadkich przypadkach, w których błędu nie można odtworzyć nawet po naprawieniu, można go zamknąć przez sprawdzenie kodu.

Karl Bielefeldt
źródło
jak przeprowadzasz automatyczny test dla takich rzeczy? (aby uniknąć nieporozumień, wszystko, co napisałeś, odpowiada mojemu doświadczeniu i przekonaniom) Mój najnowszy błąd, taki jak wyścig, polegał na wyścigu danych w celu uzyskania niezsynchronizowanego dostępu, zarówno błąd, jak i poprawka były bardzo łatwe do udowodnienia przez kontrolę kodu, ale nie mogę wyobraź sobie, jak niezawodnie to przetestować. (Przeważnie mam małe problemy z projektowaniem testów dla współbieżnych rzeczy, ale nie mogę znaleźć kodu testowego, aby udowodnić brak wyścigu danych)
gnat
1
Może to wpaść w mój wyjątek dotyczący sprawdzania kodu, ale możesz także uruchomić warunki wyścigu, wprowadzając opóźnienie w jednym z wątków. Często możesz to zrobić, opóźniając zewnętrzny bodziec, lub, co gorsza, możesz umieścić opóźnienie bezpośrednio w kodzie podczas testowania.
Karl Bielefeldt
Rozumiem dzięki. Brzmi interesująco, muszę dać mu trochę myśli ...
gnat