Metody debugowania kodu (sytuacja koszmaru)

16

Często mam zadanie debugowania aplikacji w mojej pracy. Jest to aplikacja BI, którą wdrażamy w firmach, która obejmuje środowisko testowe i środowisko produkcyjne. Zastanawiam się, czy istnieją jakieś aplikacje / narzędzia / metody, które ludzie mogą sugerować na podstawie tych ograniczeń:

  1. Debugera nie można używać na stronie klienta ani lokalnie, ponieważ oprogramowanie zależy od niestandardowych aplikacji innych firm, dla których nie mamy środowisk testowych. (EDYCJA: aby być uczciwym, w niektórych przypadkach możliwe jest lokalne debugowanie. Jeśli użyjemy tylko kodu podstawowego. Znaczna część problematycznego kodu znajduje się w bibliotece DLL, która zawiera komunikację specyficzną dla strony trzeciej: gniazda, potoki przetwarzania, wywołania mydła, niestandardowa logika, która zmienia zachowanie kodu podstawowego. Zwykle podczas implementacji lub rozszerzenia dla klienta pisalibyśmy nowy kod w tym obszarze).

  2. W naszych aplikacjach praktycznie nie jest rejestrowane. Nie ma testów jednostkowych.

  3. Kontrola wersji ma tylko 1 wersję pełnego rozwiązania (przy użyciu bezpiecznego źródła 2005). Nie można więc uzyskać poprzedniej wersji całego rozwiązania, a jedynie pojedyncze pliki. (Chyba że ktoś wie, jak to obejść).

  4. Nie można odtworzyć lokalnie, często nie można odtworzyć w środowisku testowym (wysokie prawdopodobieństwo, że testy i produkcja nie są tą samą wersją).

  5. Istnieje duża szansa, że ​​wersja, której używa klient, różni się od wersji bezpiecznej dla źródła. Jest tak, ponieważ poszczególne pliki są aktualizowane, które mają wbudowaną niestandardową logikę dla tego konkretnego klienta. Często zdarza się, że aktualizuje się plik binarny, co wymaga zmian w kilku innych plikach binarnych, ale po dokonaniu zatwierdzenia nikt nie ma na ten temat żadnego zapisu ani wiedzy. Dość częstym błędem, jaki widzę, jest „Nie znaleziono funkcji / metody” lub „Wywołanie metody ma za dużo / za mało określonych parametrów” w środowisku klienta.

  6. To jest rozwiązanie .NET VB

  7. Nie można zainstalować żadnego oprogramowania na stronach klienckich, ale można lokalnie

  8. Nasza aplikacja jest niezwykle konfigurowalna, ale niestety logika dostosowywania jest rozłożona na wszystkie klasy i pliki, od interfejsu użytkownika aż po warstwę danych, w tym niestandardowe zmiany w bazie danych dla poszczególnych klientów.

  9. W kodzie nie ma praktycznie żadnych komentarzy. Brak dokumentacji dotyczącej architektury. Brak dokumentacji dotyczącej interfejsu API. Jedyne, co mamy, to setki setek łańcuchów e-mail, które nieco wyjaśniają, co się dzieje. Jedyni ludzie, którzy znają kod, to ci, którzy go napisali, ale nie są już programistami, więc nie angażują się zbytnio.

I zanim to powiesz ... tak, wiem; Ja też chcę się zastrzelić. To nie pomaga, że ​​jest kod spaghetti, setki ostrzeżeń kompilatora i zepsuty polimorfizm, który NAPRAWDĘ powinien zostać naprawiony, ale nie mam w tym nic do powiedzenia.

Najczęstsze rodzaje błędów, na które natrafiam, to błędy odniesienia o wartości zerowej, niepoprawne rzutowania i brak zgodności funkcji / podpisów funkcji. Czasami mam szczęście, a przeglądarka zdarzeń rejestruje komunikat o klasie, metodzie i wyjątku. To nie jest najbardziej pomocne, ale wciąż coś. Najgorsze są błędy, które nie mają śladu, żadnych kroków repro oprócz zrzutu ekranu i są ogólnymi komunikatami o błędach, jak te wspomniane powyżej. Czasami nie można dowiedzieć się, dlaczego się wydarzyły, tylko modlić się, aby środowisko nie było odpowiednio skonfigurowane i że zniknie później.

Wiem, że to brzmi jak grzeczność i do pewnego stopnia tak jest. Ale desperacko szukam opcji. Czy mogę użyć innych metod / narzędzi?

Igneous01
źródło
43
Masz CV?
Robert Harvey
5
+1 za „Też chcę się zastrzelić”. Źródło Safe 2005, ouch. Przynajmniej powinieneś „skoncentrować się” na wspaniałej lekcji historii - jesteś w zasadzie podróżnikiem w czasie! Nauczysz się lekcji dziesięciolecia starannie opracowanej wiedzy na temat „dlatego już tego nie robimy”. Godspeed, konik polny.
BrianH
7
Biorąc pod uwagę wymaganie nr 1 jedynym sposobem na skuteczne debugowanie tego bałaganu jest bycie jasnowidzem. Poważnie, nie ma magicznej kuli, która sprawiłaby, że byłaby to jakaś bzdura. W pewnym sensie powinno to odciążyć cię od presji, ponieważ debugowanie jest koniecznie kwestią szczęścia. A może kierownictwo każe ci mieć szczęście? Oczywiście nie jest to zrównoważone, więc powinieneś szukać innych możliwości.
Charles E. Grant
14
Oto kilka faktycznych porad dotyczących kariery: Spędź zbyt długo w domu, w którym panują straszne praktyki inżynierii oprogramowania, a kierownictwo prawdopodobnie będzie cię winić za to, że jesteś złym programistą problemów, które nieuchronnie się pojawią. Byłem tam i jestem pewien, że inni też. W najlepszym razie prowadzi to do złych nawyków rozwojowych.
Gort the Robot
2
jak radzę sobie z tymi sytuacjami: jeśli nie zarabiam znacznie powyżej rynku, szukam czegoś innego.
kevin cline

Odpowiedzi:

22

Rada Roberta Harveya jest prawdopodobnie najlepsza, ale ponieważ porady dotyczące kariery są nie na temat, dam odpowiedź, jaką można udzielić:

Jesteś na dnie bardzo stromej góry pokrytej jeżynami, błotem i drażliwymi kozami górskimi. Nie ma łatwej drogi do góry. Jeśli chcesz dostać się na szczyt, musisz wspiąć się o jeden niezwykle bolesny krok na raz.

Wygląda na to, że wiesz dokładnie, jak powinno działać. Jeśli nikt inny ci nie pomoże (ponownie, ignorując porady dotyczące kariery), jedynym wyborem jest samodzielne naprawienie tych rzeczy.

Po pierwsze, dla wszystkiego, co święte, zdobądź te rzeczy w prawdziwym systemie kontroli wersji. Prawie wszystko, z wyjątkiem sejfu źródłowego, który jest znany jako śmierdząca kupa śmieci. gitjest bezpłatny i można go łatwo skonfigurować. Nie można naprawić problemów z brakiem kontroli wersji w przeszłości, ale przynajmniej powstrzymać problem przed kontynuowaniem w przyszłości.

Następnie zajrzyj do logowania. Znajdź lub, w najgorszym przypadku, napisz system rejestrujący i zacznij go używać. Użyj jednego, który może być również używany na stronach klienckich, więc gdy coś pójdzie na boki, masz przynajmniej coś.

I zacznij pisać testy, przynajmniej dla nowych wprowadzanych zmian.

Nie ma na nim cukru: nie ma tu odpowiedzi, która nie wymagałaby dużo pracy ani nie traktowałaby tego jako kwestii kariery.

Gort the Robot
źródło
Uwierz mi, nie chciałbym niczego więcej, niż dodawać aserty, zabezpieczenia i rejestrowanie, prawdopodobnie też przepiszę warstwę danych (piszę weryfikator konfiguracji, aby zdiagnozować typowe problemy z konfiguracją). Niestety to nie zależy ode mnie. Mogę poprosić o przekazanie czegoś do źródła bezpiecznego, ale typowa odpowiedź brzmi: „Twoje intencje są dobre, ale nie na tym powinniśmy się koncentrować”. Niestety jestem młodszy z 1/2 letnim doświadczeniem. Będę przez chwilę wspinać się na tę górę.
Igneous01
9
@ Igneous01 Szczerze mówiąc, spróbuj znaleźć inną górę do wspinaczki. Warunki pracy w innych miejscach mogą nie być idealne, ale myślę, że przynajmniej większość jest znacznie lepsza niż to, czego doświadczasz. Jeśli twoi strażnicy odrzucą twoje ulepszenia słowami „nie jest to coś, na czym powinniśmy się koncentrować”, podejmą decyzję i będą czerpać wyniki tej nieudanej polityki (tracą już mnóstwo pieniędzy pod względem straconego czasu rozwoju) . Pytanie brzmi: czy chcesz się z nimi trzymać, dopóki tego nie zrobią?
cmaster
6
I pamiętaj, że gdy zawodzą złe zasady, wszyscy zaangażowani wyglądają źle, nawet ci, którzy się nie zgadzają.
Gort the Robot
1
Tak, zacznij rejestrować i śledzić. Rozpocznij także dokumentowanie i dodawanie komentarzy. Stopniowo wszystko się sumuje. Mówisz też, że masz szczęście, że nadal masz niektórych oryginalnych programistów w firmie, jeśli nie w zespole. Wciśnij kierownictwo, aby uzyskać do nich dostęp Jeśli to możliwe, przekonaj ich, że wolą tworzyć jakieś dokumenty niż ciągłe pytania.
Mawg mówi o przywróceniu Moniki
4
@ Igneous01: Biegnij, nie idź. To miejsce jest chore i sprawi, że będziesz chory.
Przywróć Monikę - M. Schröder
8

1) Debugera nie można używać na stronie klienta ...

To jest całkowicie normalne.

... lub lokalnie

To jest problem.

2) W naszych aplikacjach praktycznie nie jest rejestrowane.

Rejestrowanie to debugowanie produkcyjne.

Nie ma testów jednostkowych.

O jej. Jednak wszystkie są wspólne.

3) Kontrola wersji ma tylko 1 wersję pełnego rozwiązania

Więc nie używasz kontroli wersji.

4) Nie można odtworzyć lokalnie, często nie można odtworzyć w środowisku testowym (istnieje duże prawdopodobieństwo, że testy i produkcja nie są tą samą wersją).

Tak więc tylko wdrożone środowisko klienta wyświetla błędy.

W takim przypadku konieczne jest wbudowane w kod aplikacji rejestrowanie disgnostic, które (a) wychwytuje i [w pełni] rejestruje [fatalne] błędy i (b) może być „wybierane” na żądanie w celu uzyskania dodatkowej, ciągłej diagnostyki, która jest przydatna w śledzenie problemu (problemów).

5) Istnieje duża szansa, że ​​wersja, której używa klient, różni się od wersji bezpiecznej dla źródła.

Ponownie, po prostu nie używasz kontroli wersji na swoją korzyść.

8) Nasza aplikacja jest niezwykle konfigurowalna

To dość typowe.

Różnicami specyficznymi dla witryny należy zarządzać za pomocą „Rozgałęzienia” kontroli wersji.

9) W kodzie nie ma praktycznie żadnych komentarzy.

Znowu, to jest zbyt powszechne, ponieważ programiści piszą kodowanie „samodokumentujące”, prawda?
A przynajmniej kod, który rozumieją w dniu, w którym go piszą.

Brak dokumentacji dotyczącej architektury.

O jej.

Brak dokumentacji dotyczącej interfejsu API.

Och kochanie, och kochanie.

I zanim to powiesz ... tak, wiem; Ja też chcę się zastrzelić.

Nie; chcesz zastrzelić ludzi, którzy napisali te wszystkie rzeczy, stworzyli nieudokumentowany, niemożliwy do utrzymania bałagan, a następnie przenieśli się na nowe pastwiska, pozostawiając za sobą niewygodny bałagan.

Najczęstsze rodzaje błędów, na które natrafiam, to błędy odniesienia o wartości zerowej, niepoprawne rzutowania i brak zgodności funkcji / podpisów funkcji.

Odwołania zerowe i nieprawidłowe rzutowania są błędami w czasie wykonywania; do pewnego stopnia powinieneś się ich spodziewać, a fakt, że je otrzymujesz, często sugeruje brak programowania obronnego (lub nadwyżkę optymizmu) przez oryginalnych autorów.

Niedopasowanie sygnatur funkcji powinno spowodować uszkodzenie kompilacji ; powinny one powodować „zepsute wersje” i nigdy nie powinny wychodzić z drzwi!

Phill W.
źródło
2
„Zawsze
koduj
Błędy w czasie wykonywania są bardziej spowodowane brakiem zrozumienia niż brakiem programowania obronnego. Programowanie defensywne to tylko sposób na ukrycie faktu, że kod nie działa.
user253751
1
„Brak dokumentacji o architekturze” zwykle oznacza „brak architektury” ...
gnasher729,
The site-specific differences should be managed through Version Control "Branching".- Nie sądzę, że to najlepszy sposób na kontynuację. Używanie plików konfiguracyjnych i przełączników funkcji wydaje się być bardziej powszechne i łatwiejsze do przemyślenia.
sixtyfootersdude
5

Zacznij od logowania. Będzie to miało największy wpływ. Zaimplementuj strukturę rejestrowania w bazie kodu, takiej jak Log4Net lub podobna. Rozpocznij rejestrowanie działania kodu.

Debugowanie powinno być możliwe lokalnie. Jeśli nie, pracuj nad pobraniem plików symboli (PDB), abyś mógł debugować w bibliotekach DLL innych firm, aby uzyskać pełny obraz występujących problemów. Narzędzia takie jak WINDBG mogą wskazywać, które biblioteki DLL są problematyczne w przypadku awarii systemu. Każdy serwer można skonfigurować tak, aby zrzucał pamięć w przypadku awarii. Zasadniczo jest to migawka tego, co działo się, gdy wystąpił problem. Można zbadać zrzuty lokalnie, aby znaleźć wskazówki na temat tego, co się dzieje. Jeśli debugowanie nie jest możliwe, pracuj nad tym, aby było to możliwe. Dokumentuj kroki niezbędne do debugowania. Kiedyś na skomplikowanych systemach, do pełnego debugowania potrzebna jest całkiem spora konfiguracja.

Śledzenie błędów ... Jeśli go nie używasz, zacznij go używać. Idzie to ręka w rękę z odpowiednim systemem kontroli wersji. Zasadniczo rozpocznij śledzenie błędów i poprawek kodu. Zacznij budować historię systemu.

Wykonaj analizę kodu statycznego. Zainwestuj w narzędzie takie jak ReSharper. Szybko wskaże wszystkie możliwe wyjątki zerowe i inne złe praktyki kodowania. Może pomóc w poprawieniu kodu za pomocą zaledwie kilku kliknięć i zautomatyzować żmudne elementy, takie jak formatowanie kodu, nazywanie zmiennych itp. Zmierz swój kod, dowiedz się, gdzie są najgorętsze punkty do refaktoryzacji za pomocą wskaźników kodu.

Testy refaktorowe i jednostkowe. Zakładam, że prawdopodobnie większość napisanego kodu nie jest bardzo testowalna, więc nie zawracałbym sobie głowy dodawaniem testów. Dowolny nowy kod, utwórz projekt testowy i zacznij pisać testy, zarówno jednostkowe, jak i integracyjne. Jeśli testy jednostkowe zakończą się niepowodzeniem, nie powiedzie się kompilacja. Tak więc, kiedy refaktoryzujesz, powinny być testy. Jedną z rzeczy w testach jest to, że można napisać test wywołujący dowolną metodę i debugować tę metodę bez ładowania całej aplikacji lub bazy kodu. Jest to przydatne, aby pomóc w rozwiązywaniu problemów.

W razie potrzeby udokumentuj wszelką wiedzę plemienną. Kod powinien sam się dokumentować, więc komentarze powinny być rzadkie, ale wiele systemów ma „niezwykłe” sposoby robienia rzeczy, wskazuj je w kodującym WIKI lub innym nieformalnym repozytorium. Rozważ także wymyślenie standardów i praktyk kodowania. Egzekwuj te standardy za pomocą zestawu narzędzi, takiego jak Resharper. Ponieważ większość kodu prawdopodobnie nie jest zgodna z żadnym standardem i wytycznymi, zaimplementuj standardy dotyczące nowego napisanego kodu.

Od waszego nowego potraktowałbym to jak podróż służbową. 6 miesięcy do 2 lat, a następnie dokonaj wyboru, aby zostać lub przejść dalej. Czerp satysfakcję z robienia rzeczy nieco lepszych niż dzień wcześniej.

Jon Raynor
źródło
4

Po pierwsze, wszystkie powyższe ... to samo.

Niektóre heurystyki:

  • Użyj kontroli źródła na swoim komputerze programistycznym. To najlepsza rzecz, jaką zrobiłem. Nie zastępuje kontroli wersji projektu, którą mamy. Jest to narzędzie, które daje niesamowitą swobodę w nieustraszonym eksperymentowaniu, hakowaniu, rozwiązywaniu problemów jednocześnie, ale niezależnie, itp. Jestem lepszy w używaniu kontroli wersji, ponieważ mam swobodę bycia odważnym, spieprzyć i uczyć się.
  • W zakresie, w jakim dodajesz komentarze, nadaj priorytet elementom interfejsu publicznego, aby skorzystać z intellisense. Zrób to, gdy odszyfrujesz podczas przygód debugowania.
  • Bądź wytrwały dzięki drobnym refaktoryzacjom. Wcześniej czy później, dla danego kawałka kodu, dojdziesz do masy krytycznej, która umożliwia duże refaktoryzacje, takie jak OSUSZANIE nadmiarowego kodu między klasami.
  • Nie mieszaj formatowania kodu i faktycznych zmian w tych samych zatwierdzeniach kontroli wersji.
  • SOLIDNE zasady
    • Nigdy nie ignoruj ​​pojedynczej odpowiedzialności. Dobra robota, to jest ścieżka do obietnicy zorientowanej obiektowo; MOIM ZDANIEM.
    • Zawsze ignoruj ​​otwarte / zamknięte.
    • Nie mówimy tutaj o nowym kodzie.
    • Tworzenie interfejsów bez celowego projektowania utrudnia konserwację.
  • Refaktoryzacja
  • Niektóre pliki kodu wymagają pełnego przeformatowania, zmiany nazwy itp. Przed próbą debugowania. Nie wstydź się korzystać z menu refaktora studia wizualnego bez testów jednostkowych.
  • Jedyna dokumentacja, której nie można zgubić, znajduje się w plikach kodu.
  • Kiedy uzyskasz kontrolę wersji, rozważ plan VC. I udokumentuj to! I wymyśl konwencję nazewnictwa dla gałęzi, znaczników, które podkreślą główne wersje oprogramowania i kamienie milowe.
  • Używaj dobrego sprzętu
  • Ćwicz debugowanie gumowej gumki
  • Czasami najgorsze, co może się zdarzyć, to to, że cię nie zwalniają.

Edytować

Rozwój aplikacji Brownfield w .NET

Wypróbuj tę książkę. Prawdopodobnie najlepsza jest pierwsza od początku do końca lektura. Ta książka pomoże ci myśleć o dużym obrazie, możliwościach i opracowywać strategiczne i taktyczne plany ataku.

Wystaje

Zostań, powiedzmy, 1,5 roku, jeśli możesz; wystarczająco długo, aby wiedzieć, czy robisz postępy doświadczalne. Będziesz wiedział, czy zdobywasz 2 lata doświadczenia lub 6 miesięcy doświadczenia 4 razy.

Będąc „młodszym z 1/2 letnim doświadczeniem” obawiam się, że potencjalny pracodawca postrzega to jako ratowanie wcześnie, ponieważ nie można go zhakować. To jedno, by powiedzieć, że nauczyłeś się z, y, x, wziąłeś kilka nazwisk i skopałeś tyłek - ale nie pozwolono ci przyczynić się do twoich możliwości; i inne po prostu ryzykując wyjaśnienie zadania, kodu, zarządzania itp.

Być może nie bazuję na tym, ale moje „najlepsze i najgorsze czasy” to moja pierwsza praca, która okazała się dosłownie niemożliwym do utrzymania kodem. Miałem świetnego opiekuna (cała reszta pochodziła z programu hodowlanego), który dał mi przestrzeń do napisania kilku kluczowych programów. To doświadczenie było objawieniem.

koniec Edytuj

radarbob
źródło
+1 za Nie mieszaj formatowania kodu i faktycznych zmian w tej samej kontroli wersji. - świetna rada
Kiwiron
0

Powiedziałbym, że (5) musisz naprawić w pierwszej kolejności. Jeśli nie wiesz, który kod działa w środowisku produkcyjnym, nie masz bezpiecznego sposobu na odtworzenie i naprawienie problemów. Powoduje to, że wszelkie wprowadzane zmiany są niebezpieczne, ponieważ mogą powodować problemy, których nie można przewidzieć i których nie można odtworzyć.

Konieczne może być wykonanie pracy detektywistycznej i być może inżynierii wstecznej, aby dowiedzieć się, które wersje kodu i które biblioteki są wdrożone. (I potrzebujesz spójnego systemu kompilacji i wdrażania, aby cały wdrożony kod był zgodny z kontrolą źródła.)

Może być konieczne zbudowanie wielu środowisk testowych w celu replikacji różnych wdrożeń. (Oczywiście najprostszym rozwiązaniem jest stworzenie nowej czystej wersji i konsekwentne wdrażanie jej wszędzie, ale wygląda na to, że nie jest to możliwe?)

Tylko wtedy, gdy znasz dokładne wdrożone wersje i masz odpowiednie środowiska testowe, powinieneś zacząć próbować naprawić / poprawić kod.

Kolejnym priorytetem powinna być konsolidacja do jednej bazy kodu, którą można wdrożyć wszędzie. Wygląda na to, że masz różne wersje kodu wdrożone z powodu dostosowywania? Należy skonsolidować do jednej wersji, a następnie użyć przełączników konfiguracji dla niestandardowej logiki.

Następnie możesz zacząć ostrożnie ulepszać bazę kodu, aby ułatwić debugowanie. Dodanie rejestrowania jest prawdopodobnie najmniej ryzykowną poprawą.

Będziesz chciał dodać testy automatyczne, ale często najtrudniej jest dodać do projektu, który początkowo nie jest przeznaczony do testowania. Zamiast tego zalecam rozpoczęcie od zautomatyzowanych kompleksowych testów integracyjnych. Są one trudniejsze w konfiguracji, ale nie wymagają ponownej architektury rozwiązania, więc są mniej ryzykowne.

JacquesB
źródło
0

Ignorując problemy występujące w zespole, wydaje się, że pierwszym, który należy rozwiązać, jest debugowanie kodu pasującego do tego, co jest w produkcji. W przeciwnym razie możesz gonić za błędem, który został już naprawiony w kodzie, który masz w „Kontroli źródła”. Ponieważ jest to .NET, możesz łatwo „zdekompilować” produkcyjne pliki binarne w celu porównania kodu z tym, co masz. Nie jest to łatwe zadanie, ale jeśli ci się powiedzie, jest to silny argument za lepszym narzędziem kontroli źródła, które może oznaczać wydane wersje.

20c
źródło
Kiedy masz na myśli dekompilację, masz na myśli użycie IDA Pro do przeglądania kodu maszynowego? Prawdopodobnie byłbym wtedy jedynym, który go używał, ponieważ nikt tutaj nie zna asemblera (i znam podstawy).
Igneous01,
Ponieważ jest to .NET, pliki binarne nie są kodem maszynowym, są w CIL ( en.wikipedia.org/wiki/Common_Intermediate_Language ). Można to dość łatwo i dokładnie przekonwertować z powrotem na kod c # lub VB, szczególnie jeśli nie było zaciemnione. Możesz spróbować na przykład z ILSpy ( ilspy.net ), ale prawdopodobnie istnieją inne narzędzia, których możesz użyć.
20c