Co zrobić, gdy wyczerpałeś wszystkie możliwości naprawy błędu

13

Jestem młodszym programistą (do tej pory 4-miesięczne doświadczenie zawodowe), pracuję nad aplikacją mobilną dla wielu platform (zespół 1-osobowy - więc to tylko ja).

Mam błąd w tym programie / aplikacji, który jest dość duży (30 różnych plików nagłówkowych, każdy z własnym plikiem cpp). Próbowałem dokładnie wyśledzić, co się dzieje z błędem, a także go naprawić (nawet próbowałem użyć kilku hacków, aby go uruchomić), ale około kilkunastu lub więcej rozwiązań (mam pomysły na to, co powoduje problem) ) Nie znalazłem niczego, co doprowadziło mnie do dokładnego śledzenia błędu i naprawiłem błąd.

Czy masz jakieś porady dla młodszego programisty na temat niektórych szerokich technik (idź pobiegać, wydrukuj cały mój kod na papierze i przejrzyj go za pomocą pióra itp.) Przydałby mi się ten błąd?

Aby dać nieco więcej kontekstu dla mojego błędu; obejmuje wieloplatformowy interfejs API Mosync, kiedy wykonuję określoną sekwencję czynności, bieżący ekran nie przerysowuje (i wydaje się), że poprzednio wyświetlany ekran nadal odbiera zdarzenia wskaźnika / naciśnięcia klawisza, a nie bieżący ekran.

Określona sekwencja:
- Wyświetlany ekran menu - kliknij „Pokaż poprzedni przycisk zamówienia”
- Poprzedni Wyświetlony ekran zamówień - kliknij „Załaduj plik”, a następnie kliknij przycisk menu i otwórz ekran
dostawy - Wyświetlony ekran dostawy - Kliknij przycisk menu i otwórz ekran
zakupu - Wyświetlony ekran zakupu - Błąd tutaj, dane wejściowe do tego ekranu nie są wyświetlane / nie reagują, ListViews nie przewijają się, przyciski nie reagują na kliknięcia, komórki ListView nie reagują na kliknięcia


Wezmę radę na pokładzie, błąd można odtworzyć w 100% po tych samych krokach za każdym razem, chociaż nadal bardzo trudno jest ustalić, w jaki sposób transmitowane są zdarzenia wskaźnika i na jaki ekran ze względu na fakt, że jest to część interfejsu API, którego nie mogę osiągnąć (lub nie wiem jak).

Chciałbym również, aby moja para oczu patrzyła na moją pracę i wskazywała błąd, ale ponieważ powiedziałem, że jestem zespołem 1, mój szef kieruje mną, jest właścicielem firmy i ma pomysły na aplikację, ale ma nie znam c ++ ani żadnych najnowszych języków (cobal? Myślę, że to wszystko). Wszelkie porady, jak zdobyć drugą parę oczu bez naruszania / popisywania się intelektualnym kodem / własnością firmy?

... i nie odejście z tego płatnego stażu nie jest opcją, umowa mówi, że jeśli odejdę przed 6 miesiącami kontraktu na 12 miesięcy, być może będę musiał zapłacić 30% mojej rocznej pensji

użytkownik14321
źródło
6
Czy to w 100% powtarzalne?
5
Prosta odpowiedź polega na zaangażowaniu współpracowników . Jako zespół rozwiążesz go za chwilę.
Fattie
2
@Joe - nie zawsze. Na przykład błędy w zbiorowym zachowaniu wielu złożonych wzajemnie oddziałujących podsystemów, w których zbudowano różne podsystemy z subtelnie niekompatybilnymi widokami ich ról, wynikającymi z nieoczywistych dwuznaczności w specyfikacjach - zazwyczaj bardzo niewiele osób ma szczegółową wiedzę na temat wielu podsystemów i ich interakcji aby móc zdiagnozować te problemy. Czasami musisz zmusić wszystkie zespoły do ​​rozmowy, a kiedy dwie osoby zaczną nazywać się kretynami, istnieje szansa, że ​​dyskutują o czymś peryferyjnie związanym z niezgodnymi założeniami.
Steve314
Połączyłem twoje konta. Możesz użyć Yahoo OpenID, aby się zalogować. Ja również edytuję twoje pytanie, aby zamieścić informacje, które opublikowałeś jako odpowiedź.
Adam Lear
btw. Oprócz mojej odpowiedzi poniżej, przeczytałem na Wikipedii, że Mosync nie jest już obsługiwany?
Brad Thomas

Odpowiedzi:

19

Jeśli możesz odtworzyć problem w 100% przypadków, ustaw punkt przerwania w ostatnim kroku (tak wcześnie, jak to możliwe). Jeśli przejdziesz przez cały stos wywołań, jestem prawie pewien, że dojdziesz gdzieś do nieoczekiwanych wartości lub czegoś, co powinno zostać wywołane, ale nie jest.

Edytować:

A jeśli siedzisz na końcu dowcipu, próbując naprawić błąd i publikujesz tutaj, mając nadzieję, że dostaniesz świecącą radę, odejdź . Oczyść głowę i wróć później (najlepiej jutro lub po weekendzie). Wiele razy spędziłem cały dzień, szukając rozwiązania konkretnego problemu, aby po prostu odejść, wrócić następnego dnia z czystą głową i znaleźć go w ciągu dziesięciu minut.

Demian Brecht
źródło
4
i jeśli z jakiegokolwiek powodu nie możesz użyć debugera, umieść trochę informacji o śledzeniu wokół fragmentu kodu, który Twoim zdaniem się nie udaje, który rejestruje wywołania funkcji w pliku tekstowym.
3
+1 za „Odejdź”. Potrzeba dużo doświadczenia, aby wiedzieć, że odejście będzie prawdopodobnie bardziej produktywne niż rozwiązywanie problemu. Twoja sytuacja wydaje się dobrym miejscem na rozpoczęcie zbierania tego konkretnego doświadczenia.
Mike Sherrill „Cat Recall”
Jeśli twoje oprogramowanie potrzebuje punktu przerwania, aby wykryć błąd, twój mózg też go potrzebuje. Oszczędza to więcej czasu niż zmuszanie się i nie odchodzenie.
setzamora
Znalazłem funkcje rejestrowania, które rejestrują wartości, które mogą być istotne, są często lepszym sposobem śledzenia tego rodzaju rzeczy. Sformatuj wiersze dziennika za pomocą schludnych kolumn, aby wszelkie zmiany wyróżniały się na pierwszy rzut oka. Często wywoływaj tę funkcję rejestrowania z identyfikatorem skąd jest wywoływana. Możesz sprawdzić plik dziennika znacznie szybciej niż krok po kroku monitorować zmienne.
Loren Pechtel
10

Debugowanie polega raczej na wyodrębnieniu i zrozumieniu, na czym polega problem (w porównaniu do zastosowania poprawki)

Jedną z rzeczy, na które należy uważać podczas debugowania, jest to, że zaczynasz zauważać, że skaczesz za różnymi teoriami, ponieważ często wydaje się, że trwa to dłużej i nie eliminuje systematycznie możliwych problemów.

Zwykle najlepszym sposobem na debugowanie tego rodzaju sytuacji jest nudne, systematyczne podejście, polegające na rozbiciu systemu na małe kawałki i doprowadzeniu każdego z nich do pracy w izolacji i dodawaniu każdego elementu złożoności jeden po drugim, aż się zepsuje. Następnie wyodrębniłeś dokładny problem. W ten sposób może wydawać się trochę żmudna i nieco bardziej pracochłonna, ale usuwa zmienne i utrzymuje mózg przy zdrowych zmysłach podczas próby debugowania złożonego oprogramowania.

leora
źródło
5

To tylko niektóre rzeczy, które robiłem w przeszłości, oczywiście nie wszystkie będą działać w każdej sytuacji:

  1. Zrozum, że to tylko kod, a gdzieś tam jest błąd (to nie tylko czarna magia), który MOŻESZ naprawić.
  2. Zrób sobie przerwę.
  3. Krok po kroku bardzo powoli, analizując każdy krok i upewniając się, że rozumiesz i co robi, a nie glosując na niczym.
  4. Zdobądź drugą parę oczu, aby spojrzeć na problem.
  5. Idź spać i zapomnij o tym do jutra (oczyść głowę), przyjdź z nową perspektywą).
  6. Wydrukuj kod i przeanalizuj każdą linię, robiąc notatki na marginesach, rozumiejąc każdy wpływ każdej linii
  7. Jeśli nie jest to błąd krytyczny, ale powoduje błędy, o których użytkownik nie musi wiedzieć, złapałem (wstydząco, ale szczerze) pułapkę i połknąłem ! Jeśli nie jest to niebezpieczne, a nie możesz znaleźć przyczyny, czasami po prostu łapiesz ją i nie dajesz znać użytkownikowi, że coś się stało. Chodzi o zwrot z inwestycji dla klienta, a czasem nie jest tego wart.
  8. Powiedz ustnie, że zamierzasz go wytropić i zabić. Czasami ucieknie. :-)
Richard
źródło
+1, bo to nie czarna magia!
Guy Sirton,
Ze wszystkimi złożonymi zależnościami, które przyjmujemy dzisiaj w naszym kodzie, jest to czarna magia. Ale możesz sobie z tym
poradzić
3

Zazwyczaj mam takie podejście podczas rozwiązywania błędów.

  1. Utwórz ładny krok po kroku, aby odtworzyć błąd
  2. Uprość krok po kroku
  3. Gdzie w kodzie występuje błąd? Podobnie jak w przypadku jakich funkcji?
  4. Jaką ścieżkę wybiera kod, gdy wystąpi błąd, łańcuch połączeń.
  5. Skoncentruj się na lokalizacji, kiedy jest w porządku, a kiedy nie. Powtarzaj to często, aż znajdziesz dokładnie miejsce, w którym występuje błąd.
  6. Dlaczego to się dzieje?

W tym momencie zazwyczaj jest trochę jasne, co się stało, ponieważ tyle się uczę podczas skupiania się na problemie, że wiem, co robić. Albo mam dość skoncentrowane pytanie, które mogę zadać na forum.

Następnie próbuję rozwiązać problem i krok po kroku utworzyłeś w kroku pierwszym, aby sprawdzić, czy błąd został naprawiony.

Johan
źródło
3

Wszystkie poprzednie porady są doskonałe, a większość z nich ma na celu zweryfikowanie założeń dotyczących błędu / błędu, a następnie przeprowadzenie procesu debugowania w celu zlokalizowania błędu (czasami poprzez badanie środowiska wokół błędu, a czasem bezpośrednio w kodzie).

Takie podejście nie zawsze zadziała, niezależnie od stażu pracy lub doświadczenia. Czasami potrzebujesz po prostu innego spojrzenia na problem. Znajdź kogoś, kto omówi problem lub sesję debugowania z tobą - często po prostu rozmawianie przez kod doprowadzi cię do błędu.

Przydatny idiota
źródło
Zgadzam się, że to często działało dla mnie.
Mike Dunlavey
1

Jak powiedzieli inni: 1) być w stanie niezawodnie go odtworzyć, i 2) przejść do przodu w debuggerze do momentu, w którym to się dzieje.

Jeśli nie mogę tego zrobić, z jakiegokolwiek powodu, mam dwie inne metody, które wymagają posiadania innej wersji kodu, która nie wykazuje błędu.

  1. Uruchom obie wersje kodu obok siebie w debuggerach. Krok po kroku, aż zły zrobi coś innego niż dobry.

  2. Alternatywne uruchamianie dobrych i złych wersji kodu. Mają diff lub jakąś inną listę różnic między wersjami. Następnie stopniowo zwiększaj kod każdej wersji, aby lepiej pasowała do drugiej. Jeśli zły stanie się dobry lub dobry stanie się zły, wycofuję się ze zmiany i dokonuję mniejszej zmiany. W ten sposób docieram do błędu. Myślę o tym jako o „pokonaniu obu stron problemu i dążeniu do centrum”. Ta metoda nie wymaga debuggera.

Jeśli problem jest trudny do odtworzenia, potrzebuję tyle informacji, ile mogę, takich jak zrzut stosu, kiedy to się stanie. Dlatego upewniam się, że mogę uzyskać diagnostykę, poczekam na wystąpienie problemu i mam nadzieję, że mam wystarczającą ilość informacji, aby go znaleźć.

Mike Dunlavey
źródło
1

Jeśli zostałeś przydzielony do pracy pod ręką jako młodszy programista, istnieje co najmniej jedna osoba, która wierzyła, że ​​jesteś w stanie poradzić sobie z tym wszystkim samodzielnie.

Następnie, zanim poprosisz o pomoc swoich przełożonych, zapisz na kartce papieru, listę kroków / metod, które podjąłeś w celu wykrycia błędu, jak daleko się posunąłeś, dlaczego zrezygnowałeś z każdej metody i czego się nauczyłeś w każdej próbie. Podsumuj także to, czego nauczyłeś się o projekcie.

Są szanse, że kiedy skończysz zapisywać to, co można zrobić, powinno stać się oślepiająco oczywiste. Jeśli tak, wystarczy postępować zgodnie z tym, co się ujawniło, aby odtworzyć błąd, i spróbuj naprawić. Jeśli nie, masz podstawy, na których możesz rozmawiać z przełożonymi. Jeśli poprosisz o pomoc, nie pokazując, co zrobiłeś, mogą wywrzeć na tobie negatywne wrażenie.

Ale jeśli oczyścisz głowę i wrócisz po weekendzie, możesz być w stanie rozwiązać ją w krótkim czasie, bez niczyjej pomocy. To się zdarza cały czas.

vpit3833
źródło
„Jeśli zostałeś przydzielony do wykonywania pracy jako młodszy programista, istnieje co najmniej jedna osoba, która wierzyła, że ​​jesteś w stanie poradzić sobie z tym wszystkim samodzielnie”. Gdy pracuję, wszyscy programiści powinni prosić o pomoc, jeśli po zrobieniu swojej pracy domowej nie mają rozwiązania, nazywa się to pracą zespołową.
mattnz
@mattnz Wszystko, co proponuję, to przed prośbą o pomoc sporządzić dokumentację dotychczasowych wysiłków i dopilnować, aby wszystkie znane opcje zostały wyczerpane. Nie wiem, jak to nazwać, ale nigdy nie kwestionowałem tego, co mówisz o pracy zespołowej.
vpit3833
Chciałem zwrócić uwagę na „... zdolne poradzić sobie z tym wszystkim samemu”, sugerując mi, że jesteś sam. Cieszę się, że zinterpretowałem to nieco mocniej niż zamierzałeś.
mattnz
0

Musimy wiedzieć, jak trudno jest się rozmnażać, ponieważ metoda jest zupełnie inna. W przypadku rzetelnie odtworzonej wady zautomatyzuj powodowanie wady. Używaj debugerów i śladów debugowania (ślady mają najmniejszy wpływ na wady typu wyścigowego). Bądź metodyczny. Jeden krok na raz, każdy krok dostarcza więcej informacji, nawet potwierdzając to, co już wiesz. Jeśli otrzymasz wynik niespodzianki, przestań, zanim przejdziesz dalej, zrozum go w 100%. Jest boleśnie powolny, ale zawsze doprowadza cię do końcowego wyniku, jeśli dasz mu wystarczająco dużo czasu.

Jeśli nie możesz go odtworzyć, masz problem, w jaki sposób potwierdzasz, że to naprawiłeś. Wprowadź kod debugowania i zostaw go tam. W końcu zadaj sobie pytanie, czy „Zamknięty: DNR” jest prawidłową opcją? (Nie / Nie można ponownie wydrukować). W biznesie ostatecznie decyzja o kosztach / korzyściach.

Nie zakładaj, że twoje biblioteki są poprawne, potwierdź, że są.

Zrób sobie przerwę, bądź pragmatyczny w kwestii kosztu w porównaniu do konieczności naprawy, a przede wszystkim poproś kogoś innego, aby usiadł obok ciebie i pomógł.

mattnz
źródło
0

Wiele dobrych odpowiedzi tutaj. Kilka innych wskazówek:

Interfejsy rzadko żyją w izolacji. Zbuduj program testowy z minimalnym zestawem funkcji wymaganych do odtworzenia błędu. Jeśli interfejs użytkownika jest dobrze zaprojektowany, powinieneś być w stanie oddzielić niesprawne komponenty interfejsu użytkownika i uruchomić je w izolacji w programie testowym. Czy nadal możesz odtworzyć problem? Jeśli tak, problem prawdopodobnie występuje w strukturze lub strukturze interfejsu użytkownika. Sprawdź swoją strukturę interfejsu - szczególnie uważaj na niewidoczne elementy. Spróbuj dowiedzieć się dokładnie, co się stanie, gdy klikniesz ten ListView, który nie odpowiada - jakie procedury obsługi zdarzeń są wywoływane? Pamiętaj, że w samym interfejsie użytkownika mogą występować błędy - nie przeskakuj do tego wniosku, ale nie wykluczaj go wprost. Szybki test polega na zaktualizowaniu wersji Mosync i sprawdzeniu, czy objawy się utrzymują.

W przeciwnym razie: co pozostało z twojego programu testowego? Zrozum wszystkie składniki tego, co pozostało, szczególnie wszelkie działające wątki. Coś robi konserwację bazy danych w tle? Bufor plików? Kod monitorowania zachowania użytkownika NSA? Czy interfejs użytkownika działa z niektórymi z tych komponentów (być może za kulisami)? Od jakich operacji w tle zależy interfejs użytkownika?

Podczas czytania kodu - co powinieneś spędzać dużo czasu, biorąc pod uwagę trudność w błędzie - uważaj na złe praktyki, które mogą ukrywać twój błąd. Czy widzisz coś takiego?

try {
    SaveTheWorld();
} catch (std::exception& ex) { /* oh it didn't work, let's just ignore it */ }

To niewiarygodnie słaba praktyka i jako taka jest dość powszechna (hej, nie rozbił się!). Upewnij się, że uaktualniasz kod, który to robi, aby przynajmniej go zarejestrować - najlepiej całkowicie usuń obsługę fałszywych wyjątków. (Ogólna zasada jest taka, że ​​jeśli nie wiesz, co to jest wyjątek, nie jesteś przygotowany, aby sobie z tym poradzić.) Jeśli wchodzi on w interakcje z interfejsami API w stylu C, uważaj na odrzucone wartości zwracane z kodem błędu i upewnij się, że sprawdzasz informacje o stanie błędu za pomocą narzędzi, z którymi współpracujesz.

Widząc, jak twój program testowy poprawnie obsługuje teraz awarie i przeczytałeś utworzony w ten sposób dziennik, ale nadal nic nie wyróżnia błędu, poszukaj interfejsów, które możesz sondować. Czy pod przykryciem jest transakcja sieciowa? Jeśli tak, kliknij w Wireshark. Transakcja bazy danych? Spróbuj zalogować się do kwerendy lub sprawdź status serwera bazy danych. Uderzony jest system plików lub udziały sieciowe? Sprawdź pliki pośrednie lub użyj debugera do śledzenia operacji we / wy. Sprzętowe We / Wy? Monitoruj i sonduj. Bądź empiryczny. Interfejs użytkownika może zostać zawieszony podczas operacji w tle, której się nie spodziewałeś.

Wreszcie: nie panikuj. Zachowaj spokój i śledź to, czego próbowałeś. Jeśli nadal nie możesz go znaleźć, musi to być „znany problem”, aby zostać wyśledzonym w deszczowy dzień. Będziesz potrzebował wielu materiałów, które uzasadnią tę decyzję, jeśli musi iść w tym kierunku.

lyngvi
źródło
0

W schemacie rzeczy powtarzalne błędy są (stosunkowo) łatwe! Dlaczego? Ponieważ zawsze możesz zhakować kod do absolutnego minimum, dopóki błąd nie zniknie, a następnie wróć, aby dowiedzieć się, jaki kod go powoduje. To jest jedna metoda. Jest odtwarzalny, masz pod kontrolą zwierzaka. Możesz go szturchać i eksperymentować z nim. Możesz to zrobić nawet jeśli chcesz.

Twoim pierwszym celem jest zrozumienie, dlaczego błąd występuje w twoim kodzie. Nie próbuj go początkowo naprawiać. Po prostu spróbuj to zrozumieć . Jeśli spróbujesz go naprawić, nie rozumiejąc go, będziesz hakować i prawdopodobnie spowoduje zadłużenie techniczne , nawet jeśli go rozwiążesz.

Krok po kroku przez zachowanie aplikacji, linia po linii. Obserwuj wartości zmiennych. Obserwuj przepływ kontroli. Gdzie zachowanie najpierw odbiega od tego, co mówi ci twoje zrozumienie, że powinno być? Czy rozumiesz, w jaki sposób system operacyjny wysyła zdarzenia do Twojej aplikacji? Jeśli przeszkadza ci problem z „czarną skrzynką”, czy możesz zdobyć źródło skompilowanych bibliotek / frameworków, umożliwiając ci przejście na głębszy poziom, jeśli musisz?

Czy masz system zatwierdzania wersji, który nie powoduje tego błędu? (Używasz kontroli wersji, prawda?) Jeśli masz takie zatwierdzenie, możesz przeszukać binarnie historię, aby dowiedzieć się, gdzie dokładnie został wprowadzony błąd.

Twoim celem powinno być (1) zrozumienie - określenie przyczyny i w tym celu, próba (2) zbadanie, szczegółowe zrozumienie zachowania aplikacji (3) odizolowanie problemu poprzez jego odejście, a następnie zbadanie i zrozumienie delty, która pozwoliło ci to zrobić

Ale zdecydowanie nie siedź tam od tygodni, jeśli naprawdę utkniesz. Musisz też powiedzieć o tym komuś w swojej organizacji. Poproś o pomoc tam, gdzie możesz i po przekroczeniu pewnego punktu, z pewnością obowiązkiem jest poinformowanie kierownictwa, że ​​czujesz, że natrafiłeś na barierę postępu. Ale prawdopodobnie będziesz w stanie rozwiązać ten problem, jeśli uderzysz go z różnych punktów widzenia, wszystkie skupione na nauce i zrozumieniu.

Brad Thomas
źródło