Jak najskuteczniej debugować kod? [Zamknięte]

33

Błędy wkradające się do kodu można zminimalizować, ale nie do końca wyeliminować, ponieważ jest napisane - programiści, choć wielu by się nie zgodziło , tylko ludzie.

Kiedy wykryjemy błąd w naszym kodzie, co możemy zrobić, aby go usunąć? Jak powinniśmy do tego podejść, aby jak najbardziej efektywnie wykorzystać nasz cenny czas i pozwolić nam poświęcać mniej czasu na szukanie go, a więcej na kodowanie? Czego powinniśmy unikać podczas debugowania?

Zauważ tutaj, że nie mówimy o zapobieganiu błędom; mówimy o tym, co zrobić, gdy błędy nie pojawiają. Wiem, że to szerokie pole i może być w dużym stopniu zależne od języka, platformy i narzędzi. Jeśli tak, staraj się obejmować odpowiedzi, takie jak sposób myślenia i ogólne metody.

gablin
źródło
Powiązane pytanie zostało usunięte.
1
Myślę, że podejście jest w rzeczywistości proste. Jeśli opracowałeś go sam, wiesz o tym wszystko. Możesz nawet naprawić błąd bez debugowania. Mając to na uwadze, najlepszym sposobem jest wykorzystanie czasu na kodowanie czegoś innego, dopóki ktoś, kto dużo o tym wie, może odpowiedzieć na pytanie, jak to naprawić; lub pozwól mu odpocząć, koduj inne rzeczy, aż przyjdzie ci do głowy pomysł, aby to naprawić, abyś nie tracił czasu ani energii. Sądzę, że twoje pytanie dotyczy zarządzania zespołem przedsiębiorstw.
Aquarius Power
Myślę, że Raid. Gotowy spray do zabijania owadów. Czy to pytanie filozoficzne? Książki powstają z przewagi ...
ejbytes

Odpowiedzi:

38

Sposób myślenia i podejście do debugowania jest być może najważniejszą częścią, ponieważ określa, jak skutecznie naprawisz błąd i czego się z niego nauczysz - jeśli w ogóle.

Klasyki dotyczące tworzenia oprogramowania, takie jak The Pragmatic Programmer i Code Complete, w zasadzie przemawiają za tym samym podejściem: każdy błąd jest okazją do nauki, prawie zawsze o sobie (ponieważ tylko początkujący obwiniają kompilator / komputer jako pierwszy).

Więc potraktuj to jako tajemnicę, która będzie interesująca do złamania. I łamanie tej tajemnicy powinno odbywać się systematycznie, poprzez wyrażanie naszych założeń (sobie lub innym), a następnie testowanie naszych założeń, jeden po drugim, w razie potrzeby - przy użyciu każdego dostępnego narzędzia, zwłaszcza debuggerów i zautomatyzowanych platform testowych. Następnie po rozwiązaniu tajemnicy możesz zrobić jeszcze lepiej, przeglądając cały kod pod kątem podobnych błędów, które mogłeś popełnić; i napisz automatyczny test, aby upewnić się, że błąd nie powtórzy się nieświadomie.

Ostatnia uwaga - wolę nazywać błędy „błędami”, a nie „błędami” - Dijkstra skarcił kolegom, że użyli tego drugiego terminu, ponieważ jest nieuczciwy, popierając pomysł, że zgubne i niestabilne wróżki robaków podsycały błędy w naszych programach, gdy my „ patrzę, zamiast być tam z powodu naszego (niechlujnego) myślenia: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1036.html

Możemy na przykład zacząć od oczyszczenia naszego języka, nie nazywając błędu błędem, ale nazywając go błędem. Jest to o wiele bardziej uczciwe, ponieważ wprost obwinia winę tam, gdzie należy, a mianowicie. z programistą, który popełnił błąd. Animistyczna metafora błędu, który złośliwie wkradł się, gdy programista nie patrzył, jest intelektualnie nieuczciwy, ponieważ ukrywa, że ​​błąd jest dziełem programisty. Zaletą tej prostej zmiany słownictwa jest to, że ma tak głęboki efekt: podczas gdy wcześniej program z jednym błędem był „prawie poprawny”, później program z błędem jest po prostu „zły” (ponieważ w błąd).

limist
źródło
7
Właściwie podoba mi się termin „błąd”, a nie „błąd”, nie dlatego, że obwinia „programistę, który popełnił błąd”, ale dlatego, że wyjaśnia, że ​​to nie mógł być wina programisty. Dla mnie „błąd” oznacza błąd w kodzie; podczas gdy „błąd” oznacza gdzieś błąd . Może w kodzie, może w konfiguracji środowiska, może w wymaganiach. Doprowadza mnie do szału, gdy mój szef ma „listę błędów”, w której połowa problemów to zmiany wymagań. Nazwij to listą zadań, ferchrissakes!
Carson63000,
2
+1 za „każdy błąd jest okazją do nauki, prawie zawsze o sobie (ponieważ tylko początkujący obwiniają kompilator / komputer jako pierwszy)”
Md Mahbubur Rahman,
Znasz historię terminu „błąd”, prawda? Mam na myśli, jak stosowane w rozwoju oprogramowania. Oczywiście nie mamy dzisiaj tego problemu, ale błąd faktycznie wpadł na sprzęt komputera niezauważony przez programistę i spowodował problem. Aby ktoś nie pomyślał o poprawieniu mnie, wiem, że Edison użył tego terminu na długo przed incydentem z ćmą, dlatego użyłem słowa „historia”, a nie „pochodzenie”. Zobacz computerworld.com/article/2515435/app-development/... i en.wikipedia.org/wiki/Software_bug#Etymology
thre
@ threed Oczywiście. Ale od dłuższego czasu owady nie spowodowały zdecydowanej większości błędów oprogramowania.
limist
16
  1. Napisz testy. Testowanie jest nie tylko świetne w zapobieganiu błędom (z mojego doświadczenia, dobrze wykonane TDD eliminuje prawie wszystkie trywialne, głupie błędy), ale także bardzo pomaga w debugowaniu. Testowanie zmusza projekt do raczej modułowej budowy, co znacznie ułatwia izolowanie i replikowanie problemu. Ponadto kontrolujesz środowisko, więc będzie mniej niespodzianek. Co więcej, gdy otrzymasz niesprawny przypadek testowy, możesz być całkiem pewny, że trafiłeś na prawdziwą przyczynę niepokojącego Cię zachowania.

  2. Dowiedz się, jak korzystać z debugera. printinstrukcje mogą działać dość dobrze na pewnym poziomie, ale debugger przez większość czasu jest bardzo pomocny (a gdy już wiesz, jak go używać, jest o wiele wygodniejszy niż printinstrukcje).

  3. Porozmawiaj o kimś z twoim problemem, nawet jeśli to tylko gumowe kaczątko . Zmuszenie się do wyrażenia problemu, nad którym pracujesz słowami, naprawdę czyni cuda.

  4. Daj sobie limit czasu. Jeśli na przykład po 45 minutach poczujesz, że nigdzie się nie wybierasz, po prostu przełącz się na inne zadania na jakiś czas. Kiedy wrócisz do swojego błędu, możesz mieć nadzieję, że zobaczysz inne możliwe rozwiązania, których wcześniej nie wziąłbyś pod uwagę.

Ryszard Szopa
źródło
2
+1 za „Zmuszenie się do wyrażenia problemu, nad którym pracujesz słowami, naprawdę czyni cuda”.
Md Mahbubur Rahman
I dodając do (1), prawie każdy błąd, który widzisz w kodzie, oznacza, że ​​w pakiecie testowym jest błąd - lub przynajmniej przeoczenie. Napraw oba w tym samym czasie i nie tylko udowodnisz, że naprawiłeś dany problem, ale jesteś bezpieczny przed jego ponownym wprowadzeniem.
Julia Hayward
3

Myślę, że odtworzenie błędu jest również ważne. Wszystkie przypadki, które odtwarzają błąd, mogą być wymienione, a następnie możesz upewnić się, że poprawka błędu obejmuje wszystkie te przypadki.

aslisabanci
źródło
3

Jest świetna książka, którą przeczytałem na ten temat, zatytułowana „ Dlaczego programy nie działają” , która przedstawia różne strategie znajdowania błędów, od zastosowania metody naukowej do izolacji i rozwiązania błędu, po debugowanie delta. Inną interesującą częścią tej książki jest to, że eliminuje ona termin „błąd”. Podejście Zellera to:

(1) Programista tworzy defekt w kodzie. (2) Wada powoduje infekcję (3) Infekcja się rozprzestrzenia (4) Infekcja powoduje awarię.

Jeśli chcesz poprawić swoje umiejętności debugowania, bardzo polecam tę książkę.

Z własnego doświadczenia wynika, że ​​w naszej aplikacji znalazłem wiele błędów, ale zarządzanie po prostu naciska na nas, aby udostępnić nowe funkcje. Często słyszałem: „Znaleźliśmy ten błąd, a klient jeszcze go nie zauważył, więc zostaw go, dopóki nie zauważy”. Myślę, że bycie reaktywnym w przeciwieństwie do proaktywnego naprawiania błędów jest bardzo złym pomysłem, ponieważ kiedy przychodzi czas na naprawę, masz inne problemy, które wymagają rozwiązania, a zarządzanie funkcjami wymaga natychmiastowego działania, więc jesteś złapany jak najszybciej w błędnym cyklu, który może prowadzić do dużego stresu i wypalenia, a ostatecznie do wadliwego systemu.

Komunikacja jest także kolejnym czynnikiem w przypadku wykrycia błędów. Wysłanie wiadomości e-mail lub udokumentowanie jej w narzędziu do śledzenia błędów jest w porządku i dobrze, ale z własnego doświadczenia wynika, że ​​inni programiści odnajdują podobny błąd i zamiast ponownie użyć rozwiązania podjętego w celu naprawy kodu (ponieważ o tym zapomnieli ), dodają własne wersje, więc masz w swoim kodzie 5 różnych rozwiązań, przez co wygląda to na bardziej rozdętą i mylącą. Tak więc, kiedy naprawisz błąd, upewnij się, że kilka osób zapoznało się z poprawką i przekazało informacje zwrotne na wypadek, gdyby naprawili coś podobnego i znaleźli dobrą strategię radzenia sobie z tym.

limist wspomniał o książce The Pragmatic Programmer, która zawiera interesujące materiały na temat naprawiania błędów. Korzystając z przykładu podanego w poprzednim akapicie, przyjrzałbym się temu: Entrofia oprogramowania , w której zastosowano analogię zepsutą wdową. Jeśli pojawią się dwa zepsute okna, twoja drużyna może być apatyczna, aby je naprawić, chyba że podejmiesz proaktywne podejście.

Desolate Planet
źródło
Słyszałem: „Znaleźliśmy ten błąd, a klient jeszcze go nie zauważył, więc po prostu zostaw go, dopóki nie zauważy” zbyt wiele razy. I udała się na wizyty w terenie, często klient nie zauważył, ale nie podano go. Czasami dlatego, że myślą, że nie ma sensu, ponieważ nie zostanie to naprawione, czasem dlatego, że już patrzą na zastępstwo konkurenta, a czasem (słusznie lub niesłusznie) „cóż, to i tak cała kupa bzdur”.
Julia Hayward
@JuliaHayward - tak często się zdarza, ale w twojej sytuacji klienci mogą być zadowoleni z funkcjonalności i nie przejmować się tym, co dzieje się pod maską. Problem zaczyna się ujawniać, gdy klient wraca z prośbą o dodatkowe funkcje i musisz dodać kolejne ulepszenia, takie jak uczynienie swojej aplikacji wielojęzyczną, zgodną z urządzeniami mobilnymi bla bla bla bla, zaczynasz patrzeć na to, co masz i zobaczyć wszystkie pęknięcia w ścianie.
Desolate Planet
Po prostu pokazuje, że wszystkie książki na świecie dotyczące projektowania oprogramowania, testowania i dobrej komunikacji, a także wiele produktów, nad którymi pracujesz, to rozległy bałagan. Pomimo wiedzy o tym, co jest właściwe, stres i nierealne terminy (w obliczu już i tak pomieszanego kodu) są przyczyną, dla których kod jest w stanie, w jakim jest. Sam nie mam na to odpowiedzi, jestem dość wyróżniający się w biurze jako jęcząca twarz ******, gdy kopię i krzyczę, aby zachować zdrowy kod i płynność procesu programowania, ale czasami zespół tego nie robi dobrze wiążą się ze sobą.
Desolate Planet
3

Błąd, błąd, problem, wada - jakkolwiek chcesz to nazwać, nie ma to wielkiego znaczenia. Będę trzymać się problemu, ponieważ do tego jestem przyzwyczajony.

  1. Dowiedz się, jakie jest postrzeganie problemu: przetłumacz z „Roberta wciąż nie ma w systemie” na „Kiedy próbuję utworzyć rekord użytkownika dla Roberta, nie udaje się to ze zduplikowanym kluczowym wyjątkiem, chociaż Bob jeszcze nie jest tam'
  2. Zastanów się, czy to naprawdę problem, czy tylko nieporozumienie (w rzeczywistości Boba tam nie ma, nikt nie nazywa się bob, a wstawka powinna działać).
  3. Postaraj się uzyskać minimalne rzetelne kroki, które możesz wykonać, aby odtworzyć problem - coś w rodzaju „Biorąc pod uwagę system z rekordem użytkownika„ Bruce ”, po wstawieniu rekordu użytkownika„ Bob ”następuje wyjątek”
  4. To jest twój test - jeśli to możliwe, włóż go do zautomatyzowanej uprzęży testowej, którą możesz uruchamiać wielokrotnie, będzie to nieocenione podczas debugowania. Możesz także włączyć go do zestawu testów, aby upewnić się, że ten konkretny problem nie pojawi się ponownie później.
  5. Wyjmij swój debugger i zacznij stawiać punkty przerwania - po uruchomieniu testu ustal ścieżkę do kodu i określ, co jest nie tak. Robiąc to, możesz również sprecyzować swój test, zmniejszając go do minimum - najlepiej test jednostkowy.
  6. Napraw to - sprawdź swoje testy zaliczające.
  7. Sprawdź, czy oryginalny problem opisany przez klienta został również naprawiony (bardzo ważne - być może właśnie naprawiłeś podzbiór problemu). Sprawdź, czy nie wprowadziłeś regresji w innych aspektach programu.

Jeśli znasz kod, lub problem lub naprawa jest oczywista, możesz pominąć niektóre z tych kroków.

Jak powinniśmy do tego podejść, aby jak najbardziej efektywnie wykorzystać nasz cenny czas i pozwolić nam poświęcać mniej czasu na szukanie go, a więcej na kodowanie?

Mam z tym problem, ponieważ sugeruje, że pisanie nowego kodu jest cenne w ruchu niż posiadanie wysokiej jakości działającego programu. Nie ma nic złego w byciu jak najbardziej skutecznym w rozwiązywaniu problemów, ale program niekoniecznie poprawia się po prostu dodając do niego więcej kodu.

ptyx
źródło
to najlepsza odpowiedź IMO
marcusshep
3

Podoba mi się większość innych odpowiedzi, ale oto kilka wskazówek, co robić PRZED zrobieniem tego. Zaoszczędzi ci czas na beaucoup.

  1. Sprawdź, czy naprawdę występuje błąd. Błąd jest ZAWSZE różnicą między zachowaniem systemu a wymaganiami; tester powinien być w stanie wyrazić oczekiwane i rzeczywiste zachowanie. Jeśli nie jest w stanie zapewnić oczekiwanego zachowania, nie ma wymagań i nie ma błędu - tylko czyjaś opinia. Odeślij to.

  2. Rozważ możliwość, że oczekiwane zachowanie jest nieprawidłowe. Może to wynikać z błędnej interpretacji wymogu. Może to być również spowodowane wadą samego wymagania (różnica między wymaganiem szczegółowym a wymaganiem biznesowym). Możesz je również odesłać.

  3. Wyizoluj problem. Tylko doświadczenie nauczy Cię najszybszego sposobu, aby to zrobić - niektórzy ludzie mogą to zrobić prawie z jelitami. Jedno podstawowe podejście polega na różnicowaniu jednej rzeczy przy jednoczesnym utrzymaniu wszystkich pozostałych rzeczy na stałym poziomie (czy problem występuje w innych środowiskach? Z innymi przeglądarkami? W innym obszarze testowym? O różnych porach dnia?) Innym podejściem jest przyjrzenie się zrzutom stosów lub komunikaty o błędach - czasem po sposobie sformatowania można stwierdzić, który składnik systemu wyrzucił pierwotny błąd (np. jeśli jest w języku niemieckim, można winić osobę trzecią, z którą pracujesz w Berlinie).

  4. Jeśli zawęziłeś go do dwóch współpracujących systemów, sprawdź komunikaty między tymi dwoma systemami za pomocą monitora ruchu lub plików dziennika i ustal, który system działa zgodnie ze specyfikacją, a który nie. Jeśli w scenariuszu występują więcej niż dwa systemy, możesz przeprowadzić sprawdzanie parami i pracować w dół „stosu” aplikacji.

  5. Powodem, dla którego izolowanie problemu jest tak ważne, jest to, że przyczyną problemu nie może być defekt w kodzie, nad którym sprawujesz kontrolę (np. Systemy stron trzecich lub środowisko) i chcesz, aby ta strona przejęła jak najszybciej . Ma to na celu zarówno oszczędność pracy, jak i natychmiastowe rozpoczęcie pracy, aby rozdzielczość mogła zostać osiągnięta w jak najkrótszym czasie. Nie chcesz pracować nad problemem przez dziesięć dni, aby odkryć, że to naprawdę problem z czyjąś usługą internetową.

  6. Jeśli ustalisz, że naprawdę istnieje usterka i naprawdę kontrolujesz kod, możesz dalej izolować problem, szukając ostatniej „znanej dobrej” wersji i sprawdzając dzienniki kontroli źródła pod kątem zmian, które mogły spowodować problem. To może zaoszczędzić dużo czasu.

  7. Jeśli nie możesz tego zrozumieć na podstawie kontroli źródła, nadszedł czas, aby dołączyć swój debugger i przejść przez kod, aby to rozgryźć. Możliwe, że i tak masz całkiem dobre pojęcie o problemie.

Gdy wiesz, gdzie jest błąd i możesz wymyślić poprawkę, oto dobra procedura naprawy:

  1. Napisz test jednostkowy, który odtwarza problem i kończy się niepowodzeniem.

  2. Bez modyfikowania testu jednostkowego należy go przekazać (modyfikując kod aplikacji).

  3. Zachowaj test jednostkowy w swoim zestawie testów, aby zapobiec / wykryć regresję.

John Wu
źródło
1

Oto jak to robię:

  1. używaj tej samej metody za każdym razem, aby znaleźć problem. Poprawi to czas reakcji na błędy.
  2. Najlepszym sposobem jest prawdopodobnie odczytanie kodu. Jest tak, ponieważ wszystkie informacje są dostępne w kodzie. Potrzebujesz tylko skutecznych sposobów na znalezienie właściwej pozycji i umiejętności zrozumienia wszystkich szczegółów.
  3. debugowanie jest bardzo powolne i konieczne tylko wtedy, gdy programiści nie rozumieją jeszcze, jak komputer wykonuje instrukcje asm / nie rozumieją stosów wywołań i podstawowych rzeczy
  4. Spróbuj opracować techniki dowodowe, takie jak wykorzystanie prototypów funkcji do uzasadnienia zachowania programu. Pomoże to w szybszym znalezieniu właściwej pozycji
tp1
źródło
1

Kiedy wykryjemy błąd w naszym kodzie, co możemy zrobić, aby go usunąć? Jak powinniśmy do tego podejść, aby jak najbardziej efektywnie wykorzystać nasz cenny czas i pozwolić nam poświęcać mniej czasu na szukanie go, a więcej na kodowanie? Czego powinniśmy unikać podczas debugowania?

Zakładając, że jesteś w środowisku produkcyjnym, oto, co musisz zrobić:

  1. Prawidłowo opisz „błąd” i zidentyfikuj zdarzenia, które go powodują.

  2. Sprawdź, czy „błąd” jest błędem kodu lub błędem specyfikacji. Na przykład wpisanie 1-literowej nazwy może być traktowane jako błąd w niektórych systemach, ale w innych systemach jest to akceptowalne zachowanie. Czasami użytkownik zgłasza błąd, który uważa za problem, ale oczekiwanie użytkownika na zachowanie systemu nie było częścią wymagań.

  3. Jeśli udowodniono, że wystąpił błąd, a błąd wynika z kodu, możesz określić, które fragmenty kodu należy naprawić, aby zapobiec błędowi. Zbadaj również wpływ zachowania na bieżące dane i przyszłe operacje systemowe (analiza wpływu na kod i dane).

  4. W tym momencie prawdopodobnie będziesz mieć szacunkową ilość zasobów, które zostaną zużyte na naprawę błędu. Możesz to naprawić od razu lub zaplanować poprawkę w nadchodzącym wydaniu oprogramowania. Zależy to również od tego, czy użytkownik końcowy jest skłonny zapłacić za poprawkę. Powinieneś także ocenić różne dostępne opcje, aby naprawić błąd. Może być więcej niż jeden sposób. Musisz wybrać podejście, które najlepiej pasuje do sytuacji.

  5. Przeanalizuj przyczyny, które spowodowały pojawienie się tego błędu (wymagania, kodowanie, testowanie itp.). Wymuszaj procesy, które zapobiegną ponownemu wystąpieniu warunku.

  6. Odpowiednio udokumentuj odcinek.

  7. Wydaj poprawkę (lub nową wersję)

Bez szans
źródło