Witam i zapraszam.
W tym wykładzie chciałbym opowiedzieć o debugowaniu.
Jest to bardzo ważna koncepcja, którą musisz zrozumieć w szczególności, musisz zrozumieć niektóre z narzędzi
i niektóre z metod, które możesz zastosować, aby znaleźć i naprawić błędy.
Tak więc debugowanie to proces znajdowania i naprawiania błędów w programie.
Zazwyczaj są to błędy logiczne.
I powiem ci różnicę między błędami logicznymi i składniowymi, ale może również obejmować błędy składni
kompilatora.
To cały proces dla błędów składniowych.
Debugowanie to zrozumienie tego, co mówi ci kompilator.
Zawsze chcesz się skupić na naprawie pierwszego wykrytego problemu.
Chcę przejść przez niektóre z powszechnych błędów kompilatora i ostrzeżeń, które możesz otrzymać, ale
jedną z rzeczy, które zawsze chcesz wiedzieć o kompilatorze, jest to, że kompilator może dać ci
kilka błędów.
Zawsze chcesz skupić się na pierwszym błędzie, ponieważ ten pierwszy błąd może spowodować inne błędy.
Więc może to być bardzo mylące, jeśli widzisz pięć błędów w programie, który kompilator mówi ci, możesz mieć tylko
jeden błąd i ten pierwszy błąd może powodować inne błędy.
Dlatego ważne jest, aby zawsze patrzeć na ten pierwszy górny błąd i naprawić go najpierw.
W tym bardzo uproszczonym przykładzie mamy wiele błędów w tym kodzie.
Nie mamy.
Nie mamy początkującego lewego nawiasu, nawiasu klamrowego.
Nie mamy średnika.
Zwracamy ciąg znaków.
I tak, kiedy zapisujemy to i idziemy go skompilować i faktycznie widzisz kilka czerwonych
błędów, kiedy idziemy go skompilować, to faktycznie mówi nam, że mamy trzy błędy.
Nigdy nie chcesz po prostu wybrać ostatniego błędu w linii siódmej, nawet jeśli w tym przypadku jest to rzeczywisty błąd.
Zawsze chcesz po prostu naprawić pierwszy błąd.
Więc widzisz pierwszy błąd wymieniony tutaj i naprawiasz ten pierwszy błąd, a następnie rekompilujesz i uruchamiasz go ponownie.
Ale powodem, dla którego należy to zrobić, jest tylko naprawienie tego błędu najwyższego poziomu, ponieważ ten błąd może powodować
inne problemy.
Więc zawsze skup się na naprawie tego pierwszego błędu debugowanie i proces znajdowania i naprawiania błędów może
być bardzo złożony od znalezienia prostych błędów do zbierania dużych ilości danych do analizy.
To wszystko zależy.
Czasami nie masz żadnych informacji dostarczonych z tobą poza logowaniem, a w takim przypadku musisz
analizować rzeczy.
Czasami będziesz miał błędy, które nie są powtarzalne.
Nie da się tego odtworzyć, bo zdarza się to w tak rzadkich przypadkach.
To zwykle wtedy, gdy musisz przeanalizować logi lub jakąś odmianę tego.
Umiejętność debugowania przez programistę jest niezbędną umiejętnością.
To naprawdę umiejętność rozwiązywania problemów, która może zaoszczędzić Ci ogromną ilość czasu i pieniędzy.
Jest to więc ważna umiejętność do opanowania.
To ważna umiejętność, którą należy rozwijać.
To wymaga praktyki.
To nie jest tak, że to nie przyjdzie samo do ciebie.
Istnieją pewne techniki, które możesz zastosować i metody, które możesz zastosować, abyś był lepszy
w debugowaniu.
Znam sporo programistów, którzy są naprawdę dobrzy w pisaniu oprogramowania pisząc kod.
Rozumieją język bardzo dobrze, ale ich umiejętności debugowania są bardzo słabe.
Mogą dostać błąd i ich pierwsza inklinacja do rozwiązania tego błędu jest naprawdę jakby poza torem.
I znowu, to przychodzi z praktyką.
Będziesz coraz lepszy w debugowaniu i zrozumieniu, jak znaleźć i naprawić problemy, ale jest
to coś, czego musisz się również nauczyć.
Faza utrzymania jest najdroższą fazą cyklu życia oprogramowania.
Faza utrzymania jest po wydaniu swojego produktu i teraz trzeba go utrzymać.
Utrzymanie go oznacza naprawianie wszelkich nowych błędów, które się pojawią, a także dodawanie nowych funkcji.
Tak więc, na przykład, kiedy Windows wypuszcza nowy system operacyjny, taki jak Windows 10, nie kończy produkcji
tego oprogramowania.
Będzie w terenie przez pewnie z dziesięć lat.
I nadal obowiązkiem Microsoftu jest, gdy pojawią się jakieś nowe błędy lub znajdą nowe błędy dla tego oprogramowania, aby je naprawić.
I to jest powód, dla którego pchają automatyczne aktualizacje i robią takie rzeczy.
I wtedy też zauważą, że system operacyjny będzie wychodził nowymi funkcjami wraz ze zmianami na rynku
i zmianami technologicznymi.
Tak więc konserwacja jest bardzo ważna.
A co za tym idzie, znalezienie i naprawienie swoich błędów jest bardzo ważne.
Zrozum jednak, że błędy są nieuniknione.
Wszystkie programy mają błędy.
Nikt nie może napisać idealnego kodu i nawet niekoniecznie chodzi o pisanie idealnego kodu.
Po prostu z czasem wszystko się zmienia.
Więc to też może skutkować bugami.
Musisz zrozumieć, że to, że oprogramowanie ma błędy, nie oznacza, że jest to źle napisany kod.
To w pewnym sensie nieuniknione.
Więc to jest w porządku, aby mieć błędy w, wiesz, kiedy kiedy znajdziesz i naprawisz je, to jest jeszcze większe, ponieważ
faktycznie czujesz, że osiągasz coś.
Częste problemy.
A my będziemy mówić bardziej o konkretnych problemach związanych z see.
Ale powszechne problemy, gdy próbujesz debugować, to błędy logiczne.
Błędy logiczne mają związek z nie z przeciwieństwem rodzaju błędów składniowych, które twój kod faktycznie kompiluje.
Działa, ale nie robi tego, co ma robić.
Więc jest jakaś logika lub zamierzona funkcjonalność, która jest nieprawidłowa.
Może masz deklarację IF i wskakujesz do tej instrukcji if na złym warunku.
Może masz pętlę i pętla nie wykonuje się odpowiednią liczbę razy lub nie sortujesz poprawnie.
Funkcjonalność jest zepsuta, ale kompilator mówi: Hej, wszystko wygląda dobrze.
Oto przykład błędu logicznego.
Błąd logiczny jest tam, gdzie składnia jest poprawna, ale pożądane wyniki nie są poprawne z powodu jakiegoś problemu
logicznego.
Więc w tym kodzie widzisz, że pętla for ma średnik na końcu, który jest poprawny składniowo.
Ale oczekujesz, że ta pętla for będzie działać pięć razy.
Ale tak nie jest.
To będzie tylko jeden czas biegu.
Więc jeśli powiemy build i zbudujemy ten projekt, zobaczymy ostrzeżenie, co jest miłe i zawsze powinieneś naprawić wszystkie swoje
ostrzeżenia.
Ale udało się go skompilować z powodzeniem.
Kiedy więc uruchomimy ten projekt, zauważysz, że w rzeczywistości uruchamia się on tylko raz i
raz wypisuje Hello World.
Jest to więc przykład błędu logicznego.
Błędy składniowe są bezpośrednio związane z kompilatorem.
Są to rzeczy niezgodne z zasadami języka.
Nie masz średnika na końcu oświadczenia.
Nie masz zakończenia, prawda?
Nawiasy z lewej strony, nawiasy.
Brakuje ci wspornika.
Nie używasz odpowiedniego słowa kluczowego, rzeczy tego typu.
Błędy składniowe są zwykle powodowane przez kompilator Błędy logiczne będą powodowane przez programistę
w fazie testów.
Korupcja pamięci jest również częstym problemem, szczególnie w C.
Jeśli nie uwalniasz pamięci po jej prawidłowym przydzieleniu, możesz mieć
takie rzeczy, jak dangling references, a także możesz mieć problemy z pamięcią związane z pamięcią, która nie jest używana.
Możesz mieć wycieki pamięci.
Oto przykład błędu pamięci.
W tym konkretnym kodzie mamy właściwie wyciek pamięci, więc nie rozmawialiśmy jeszcze o wskaźnikach.
Nie rozmawialiśmy jeszcze o dynamicznym przydzielaniu pamięci.
Ale w C możesz przydzielić pamięć podczas działania twojego programu.
Możesz użyć funkcji malloc.
I tak oto zaznaczamy, przydzielamy pamięć, ale nigdy jej nie zwalniamy.
Więc możemy zbudować ten kod i możemy go uruchomić i wszystko jest dobre, ale w rzeczywistości nie uwalniamy tego
błędu.
Więc to, co musielibyśmy faktycznie zrobić, aby naprawić ten błąd pamięci, to musielibyśmy powiedzieć free, a następnie musimy
powiedzieć free i X, aby zwolnić ten wskaźnik.
Ale zawsze, gdy przydzielasz pamięć, nie zwalniasz jej.
To jest wyciek pamięci.
A następnie innym przykładem byłoby, gdybyśmy nie przydzielili pamięci, jeśli utworzymy wskaźnik, a następnie
spróbujemy go przypisać, będziemy mieli korupcję pamięci, ponieważ ta pamięć nie ma żadnej alokacji dla
niej i próbujemy przypisać do niej wartość.
Więc to tylko mała, mała ciekawostka niektórych przykładów dla pamięci, korupcji, wydajności i skalowalności.
Może to być problem, w którym twoja funkcjonalność jest przeznaczona tak, jak jest, a twój kod składniowo
jest poprawny, ale nie jest zbyt wydajny lub nie masz sprzętu do jego obsługi.
Jeśli więc uruchamiasz serwer i nie masz wystarczającej ilości sprzętu do obsługi wszystkich żądań, będzie
on działał bardzo, bardzo wolno.
Albo jeśli napisałeś swój program do pracy z dziesięcioma użytkownikami, ale kiedy dostaje dużo użytkowników,
może nie jest tak szybki, ponieważ baza danych zamula się lub cokolwiek innego.
Kod działa, ale nie jest zaprojektowany poprawnie, aby obsłużyć wiele, wiele ilości użytkowników lub cokolwiek
to jest.
Brak spójności.
Może to być problem w twoim kodzie, który zmniejsza jakość związaną z tym, że twój kod robi za dużo lub
funkcja robi za dużo.
Nie jest to pojedynczy fokus lub nawet aplikacja ma zbyt dużą funkcjonalność, ma funkcje, które
nigdy nie są używane, a więc prawdopodobnie wymagałoby to przeprojektowania.
Oto przykład programu, który nie byłby zmodularyzowany, który nie jest spójny.
Masz jedną dużą funkcję, która robi zdecydowanie zbyt wiele rzeczy setki linii kodu, tysiące
linii kodu.
Chcesz rozbić funkcję na funkcje pomocnicze, oddzielne moduły.
To sprawia, że twój program jest o wiele bardziej spójny, łatwiejszy do utrzymania.
Więc zamiast mieć jak dużą główną metodę, która robi inicjalizację czytającą wejście, znaleźć trochę,
znaleźć różnicę, znaleźć produkt, znaleźć iloraz, możesz stworzyć cały ten kod i umieścić go w modułach
pomocniczych i oddzielić kod, a więc separacja może pomóc znaleźć i naprawić twoje błędy znacznie łatwiej.
Spójność jest zawsze ważna w C i zwykle jest rozwiązywana tam, gdzie masz wysoką spójność, zapewniając metody
pomocnicze.
Ciasne sprzężenie.
Ma to również związek z jakością kodu.
To jest miejsce, w którym masz wiele zależności.
Sprzężenie to coś innego niż spójność.
Spójność jest twoim jedynym celem.
Sprzężenie jest tam, gdzie masz zależności między może funkcje lub między obiektami.
Mówiliśmy o sprzężeniu, mówiliśmy o zmiennych globalnych.
Jeśli zmienna globalna jest używana w wielu różnych funkcjach, może powodować zależności między
tymi funkcjami.
Więc to, do czego chcesz dążyć, gdy piszesz kod i piszesz wysokiej jakości kod, to chcesz
mieć bardzo wysoką spójność i bardzo niskie sprzężenie.
Proces debugowania.
Pierwszą rzeczą, którą musisz zrobić, zanim znajdziesz i naprawisz w każdym błędzie, jest zrozumienie
problemu.
To jest relatywne do po prostu nie nurkuj i zacznij patrzeć na kod, usiądź z testerem, zrozum
wymagania, zrozumienie, co się dzieje.
Bo jeśli nie rozumiesz, co się dzieje, to nawet nie będziesz w stanie.
Nie powinieneś nawet próbować próbować go rozwiązać.
Kiedy już zrozumiesz błąd, spróbuj go odtworzyć, ponieważ odtworzenie błędu może pomóc Ci zebrać więcej
informacji.
Nie zawsze jest możliwe odtworzenie błędów, ponieważ mogą one wystąpić w naprawdę rzadkich okolicznościach.
Tak więc na przykład błędy, które mają jak warunki wyścigu lub nawet uszkodzenie pamięci, mogą wystąpić tylko w bardzo
specyficznych przypadkach użycia i mogą być przerywanymi problemami.
I czy tak jest w tym przypadku?
I nie da się tego odtworzyć.
To będzie coraz trudniejsze do debugowania.
Jeśli jesteś w stanie go odtworzyć, zwykle możesz zebrać wystarczająco dużo informacji, aby go naprawić.
Większość problemów da się naprawić.
Również możesz mieć problemy z niemożnością odtworzenia problemu, jeśli masz środowisko wielowątkowe,
procesy równoległe lub problemy z wątkami.
Te są również bardzo trudne do debugowania, ale zdecydowanie spróbuj odtworzyć go, gdy już zorientujesz
się, jaki problem faktycznie jest w kategoriach jesteś w stanie zrozumieć raz jesteś w stanie odtworzyć, jeśli
nie jesteś, to chcesz spróbować podejść zastosować jakiś rodzaj podziału i podboju.
Chcesz spróbować wyizolować błąd, uprościć problem, ponieważ bycie w stanie zredukować da ci informacje
z powrotem, ale może niekoniecznie powiedzieć, w jakiej części kodu jest błąd.
Więc to, co możesz zrobić, aby spróbować uprościć problem, to usunąć części oryginalnego przypadku testowego, abyś
nie testował zbyt wiele.
Możesz wyizolować problem jeszcze mniejszy, mówiąc: Och, to się dzieje tylko w tej konkretnej sytuacji.
Możesz również wykomentować kod.
Rozmawialiśmy o funkcjach po prostu mających stuby i nie mających implementacji.
Czasami jest to zatrudnione w testach, aby mogło ograniczyć zestaw problemów.
Ponadto, jeśli skomentujesz kod, będziesz miał mniej kodu, w którym błąd może faktycznie wystąpić.
Tak więc podczas komentowania kodu lub wycofywania zmian, błąd może zniknąć, a jeśli błąd zniknie, to
mówi ci, że kod, który skomentowałeś mógł go spowodować.
To, co zasadniczo chcesz zrobić, to przekształcić duży program w wiele małych programów, albo poprzez
testowanie, albo komentowanie.
Inną popularną techniką jest posiadanie testów jednostkowych wokół twojego kodu.
Jeśli test jednostkowy się nie powiedzie, może to powiedzieć ci dokładnie, gdzie logika lub problem może być w twoim kodzie.
Po wyizolowaniu błędu, ty i to pomoże ci znaleźć źródło problemu w kodzie, konkretny kod, który
powoduje problem.
Czasami będzie to wymagało użycia narzędzi do debugowania, takich jak debugger.
Będziemy mówić o debugerze w konkretach, ale zwykle w zależności od tego, jakiego IDE zintegrowanego rozwoju
używasz, są debuggery, które przychodzą z IDE.
Są też debugery, które mogą lądować standalone.
Duży ważny debugger, którego będziemy używać do programowania w C, nazywa się GDB.
Jest to debugger GNU, więc jest to miłe narzędzie, które jest właściwie narzędziem graficznym, gdzie można
zatrzymać wykonywanie programu i dodać punkty przerwania.
A następnie, gdy zatrzymasz wykonanie, możesz przejść linia po linii w swoim kodzie i spojrzeć na wartość zmiennych.
Możesz więc zobaczyć dokładnie, co dzieje się w twoim kodzie podczas jego działania.
Jest to nieocenione narzędzie.
To po prostu jest tak przydatne.
Przechodzimy przez debugger.
Pokażę ci, jak dodać punkty przerwania.
Pokażę ci, jak skonfigurować zegarek, abyś mógł spojrzeć na zmienne, gdy się zmieniają, a także następnie przejść
przez kod.
Po zidentyfikowaniu źródła problemu, trzeba go następnie naprawić.
Wymaga to dużego doświadczenia i praktyki.
Tylko dlatego, że znalazłeś źródło problemu, nadal możesz nie być w stanie go naprawić tylko na podstawie
swojego doświadczenia.
To czasami obejmuje przeprojektowanie lub refaktoryzację innego kodu, że szczególnie z problemami skalowalności lub wydajności,
możesz być zmuszony do przeprojektowania, aby umożliwić oprogramowanie, aby było bardziej skalowalne.
Nie zawsze więc łatwo jest po prostu znaleźć problem, a potem go naprawić.
Problem czasami, zwłaszcza jeszcze trudniejsze problemy, takie jak gwintowanie lub przetwarzanie równoległe,
te są jeszcze trudniejsze do naprawienia.
Ale w miarę jak będziesz pisał coraz więcej kodu, stanie się to łatwiejsze do zrobienia.
I na koniec trzeba było testować jak szalony.
Zawsze testuj wiele różnych granic.
Dobre przypadki, złe przypadki między przypadkami, aby sprawdzić, czy rzeczywiście naprawiłeś problem.
Niektóre z dostępnych technik i narzędzi.
Jednym z powszechnych i bardzo, bardzo używanych narzędzi jest użycie deklaracji print.
Możesz użyć instrukcji print, aby w zasadzie prześledzić swój kod.
Więc w C możesz użyć instrukcji print F i możesz umieścić ją w wielu liniach w swoim kodzie, aby oznaczyć,
gdzie jesteś.
Jest to również przydatne, bardzo przydatne, gdy twój program się zawiesza.
Może to pomóc w identyfikacji miejsca, w którym się rozbił.
W miarę dodawania tych instrukcji drukowania śledzących twój kod, możesz dodać dane wyjściowe w instrukcjach
drukowania, aby zobaczyć wartość zmiennych, ponieważ wartość zmiennych może wpływać na stan i może powodować
problemy z logiką.
Więc po prostu dodanie deklaracji print jest bardzo, bardzo przydatne.
Może pokazać przepływ wykonania i może pomóc w wyizolowaniu błędu.
Debugery jak wspomniałem jeden w GDB, te potrafią monitorować wykonanie programu.
Możesz go zatrzymać, możesz uruchomić linię po linii, zrestartować go, ustawić punkty przerwania, obserwować zmienne i pamięć.
Bardzo, bardzo pomocne przy próbie zdiagnozowania, gdzie tkwi problem.
Pliki dziennika.
Pliki dziennika są również bardzo przydatne, zwłaszcza w przypadku błędów, których nie można odtworzyć.
Możesz je przeanalizować w późniejszym terminie, aby zobaczyć dokładnie, co działo się w momencie wystąpienia błędu.
Oznacza to więc, że musisz zapewnić dobre oświadczenia dotyczące logowania w samym kodzie,
aby było to przydatne.
Możesz więc utworzyć własny plik dziennika, a następnie napisać do tego dziennika podczas działania programu, aby w przypadku wystąpienia
błędu można było wysłać te dzienniki do programistów.
Stosujemy to dość często w firmie Xerox, ponieważ kiedy napotykamy problemy, nie zawsze możemy je odtworzyć lub
możemy je napotkać w terenie.
Musimy mieć dostęp do tych logów, aby zobaczyć, co się działo, gdy wystąpił ten błąd.
Oprogramowanie monitorujące.
Istnieje oprogramowanie, które może monitorować i mieć runtime analizy wykorzystania pamięci, zagrożenia ruchu sieciowego
i informacji o obiektach.
To może ci powiedzieć, czy może przydzielasz zbyt dużo pamięci i nie usuwasz jej.
Jeśli masz narzędzie do wykorzystania pamięci ruch sieciowy, który może powiedzieć, czy wysyłasz
zbyt wiele pakietów lub czy twoje oprogramowanie jest skalowalne, jeśli masz wzrost ruchu sieciowego
i widzisz, że twój czas odpowiedzi ulega pogorszeniu.
Możesz również monitorować wątki i informacje o obiektach do przetwarzania równoległego, aby zobaczyć, co dzieje się
w niektórych wątkach i co dzieje się w innym wątku.
To pomoże Ci zdiagnozować wszelkie problemy związane z gwintem.
Niektóre inne wspólne narzędzia do debugowania, które możesz zatrudnić, aby znaleźć i naprawić błędy.
Możesz użyć obsługi wyjątków.
Wiele języków programowania posiada obsługę wyjątków.
Niestety, C nie obsługa wyjątków faktycznie zapobiegnie awariom i zrobi wiele rzeczy w czasie
biegu.
To nie ma zastosowania do widzenia, ale nadal jest to dobra rzecz, aby zrozumieć.
Bloki trycatch, rzeczy tego typu.
Analizatory statyczne.
Istnieje wiele dostępnych analizatorów statycznych dla C.
Analizuj kod źródłowy bez rzeczywistego pliku wykonywalnego.
Uruchamianie programu nie musi się odbywać.
Przechodzi linia po linii i patrzy na kod źródłowy.
A gdy analizuje kod źródłowy, szuka wszelkich znanych problemów.
Może więc sprawdzić semantykę.
Może zapewnić, że.
To wszystko.
Nie masz żadnych niezainicjowanych zmiennych, jeśli jesteś, jeśli przydzielasz nową pamięć, którą usuwasz.
Jeśli masz jakiś martwy kod, w którym kod nie jest faktycznie wykonywany, możesz usunąć ten kod.
Analizuje również takie rzeczy jak warunki wyścigu i deadlocki.
Zatrudniamy kilka analizatorów statycznych, gdzie pracuję.
Mamy jeden o nazwie Coverity, który jest dość popularny, i jest narzędzie sonaru kodu, którego również używamy, i uruchomimy go
na naszej całej linii podstawowej, naszym całym zestawie źródeł.
I za każdym razem, gdy wprowadzimy nowe pliki i nowy kod, narzędzie to zostanie uruchomione na tym kodzie i będzie w stanie zidentyfikować
natychmiastowe problemy z kodem, takie jak niezainicjowane zmienne, wycieki pamięci i tak dalej.
Nie analizuje składni.
Po to właśnie jest kompilator.
Istnieje również wiele pakietów testowych, które uruchamiają zestaw kompleksowych testów systemowych end to end, które możesz uruchomić
na swoim oprogramowaniu.
Testowanie jest zawsze ważne, ale jeśli możesz to jakoś zautomatyzować, aby uruchomić pewne testy za każdym razem,
gdy robisz nowy build, na przykład, może to być bardzo pomocne i może to faktycznie zapobiec błędom, ale
także pomaga zdiagnozować błędy, jak również.
Debugowanie programu po jego awarii.
Będziemy mówić o czymś, co nazywa się stosem wywołań.
Jest to bardzo przydatny mechanizm do zobaczenia, szczególnie w języku takim jak C, gdzie masz awarię i wszystkie ty jedyne informacje,
które otrzymujesz, to coś w rodzaju błędu segmentacji.
Kiedy masz ten wypadek, co dzieje się wiele razy, w zależności od tego, jak się rozbił, plik rdzeniowy zostanie wygenerowany
i możesz przeanalizować plik rdzeniowy, aby spojrzeć na stos wywołań, aby zobaczyć dokładnie, gdzie ten program umarł.
Poinformuje cię o linii kodu, w której program umarł.
I tak oto będziemy poznawać stos wywołań.
A jeśli chodzi o analizę plików rdzeniowych, to jest to bardziej zaawansowana technika.
Ale w C można wygenerować plik rdzenia i można go przeanalizować.
To trochę bardziej zaawansowana technika, ale to kolejny sposób, w jaki możesz zrobić debugowanie w swoim oprogramowaniu.
A co z zapobieganiem błędom?
Wiemy, że debugowanie to znajdowanie i naprawianie błędów, ale jeśli możesz zapobiec błędom, to jeszcze lepiej.
Jednym ze sposobów, w jaki możesz zapobiec błędom, jest pisanie wysokiej jakości kodu.
To naprawdę nie jest przedmiotem zainteresowania wielu inżynierów oprogramowania.
Wielu inżynierów oprogramowania pisze kod i dopóki działa, to wszystko, o co się
troszczą, lub dopóki dane wyjściowe są poprawne, wtedy uważają się za skończonych.
Ale jest coś takiego jak słaba jakość kodu i nie chcesz tego pisać.
Część z tego zademonstrowałem podczas wykładów, ale takie rzeczy jak używanie sensownych nazw zmiennych
bardzo ważne.
Lub jeśli piszesz nieefektywny kod, w którym używasz pętli może więcej niż trzeba, lub używając instrukcji
if lub nie musisz tego robić.
Wszystkie tego typu rzeczy stanowią słabą jakość kodu.
Jeśli masz funkcję, która robi 100 innych rzeczy i nie jest spójna, jeśli masz 5000 linii w funkcji,
jeśli twój kod nie jest zorganizowany w sposób modułowy lub jeśli masz wiele zależności
między funkcjami, ponownie, wszystko to jest słabą jakością kodu i chcesz dążyć do tego, aby nie robić tego.
Chcesz zastosować techniki, w których twój program jest zorganizowany.
Jest łatwy do utrzymania, jest wysoce spójny, ma niskie sprzężenie i używasz znaczących nazw zmiennych.
Bardzo, bardzo ważne.
Znowu, to jest bardzo ważne również dlatego, że faza utrzymania jest tak, tak droga.
Jeśli piszesz kod o niskiej jakości, staje się on znacznie trudniejszy do utrzymania.
Trudniej jest wyizolować błędy i trudniej jest dodać nowe funkcje.
Więc pracownik dobre techniki wysokiej jakości podczas pisania swojego kodu.
Testy jednostkowe.
Testy jednostkowe w ogromnym stopniu pomagają zapobiegać błędom.
Testy jednostkowe są wykonywane zwykle automatycznie, gdy kompilujesz testy jednostkowe mogą pomóc uniknąć regresji.
To jeden z najważniejszych czynników.
Regresja jest wtedy, gdy piszesz nowy kod i wprowadzasz błąd na czymś, co wcześniej działało.
Złamałeś stary kod.
Nie chcesz tego robić.
Jeśli jakieś oprogramowanie działa, a potem coś nowego, co zrobiłeś, zepsuło je, chcesz być natychmiast
powiadomiony i testy jednostkowe mogą pomóc w tym, ponieważ testy jednostkowe będą działać na tym starym kodzie i powiedzą,
Hej, to działało, teraz zawodzi.
Może również znaleźć błędy w nowym kodzie, zanim zostanie dostarczony, ponieważ ponownie, uruchamiają się po zbudowaniu
i natychmiast powie ci, że coś jest nie tak.
Istnieje koncepcja test driven development, która staje się naprawdę, naprawdę popularna.
To jest, gdzie najpierw piszesz swoje testy, a następnie rozwijasz swój kod po.
A celem tutaj jest, gdy piszesz swój pierwszy test, twój test jest nieudany, a następnie piszesz kod, aby uzyskać
go do przejścia.
Jest wiele zalet TDD i jest to rodzaj odwrotnego sposobu myślenia.
Zwykle ludzie, gdy piszą kod, najpierw piszą kod, a następnie piszą test po.
Ale z TDD, to faktycznie daje ci inny sposób myślenia, tak że pracujesz w naprawdę małych kawałkach
i masz tendencję do pisania bardzo spójnego kodu i nie masz kodu, nie ma wielu zależności,
ponieważ zgadnij co?
Jeśli jesteś w stanie przetestować kod, oznacza to, że kod nie ma tak wielu zależności.
Jeśli twój test jednostkowy jest naprawdę, naprawdę duży i wyśmiewasz wszystkie te różne rzeczy,
to zwykle jest to duży wskaźnik, że twój kod jest bardzo, bardzo zależny od innych rzeczy.
Więc poprzez zastosowanie TDD, zmusza cię do pisania bardzo luźno sprzężonego kodu, który nie ma zależności i zmusza
cię do tego, aby twoje funkcje były bardzo spójne.
Istnieje wiele zalet TDD.
Chcesz również zapewnić dobrą dokumentację i chcesz zrobić odpowiednie planowanie.
Nie tylko zanurzaj się w kodzie i zacznij wdrażać.
Zapisz swój projekt na papierze.
Wykorzystanie pseudokodu.
Racja.
Zaplanuj swój kod.
Jeśli zaplanujesz swój kod, zrozumiesz wymagania i masz dobry przemyślany projekt, możesz
zapobiec wielu, wielu błędom.
I wspomniałem o tym w całym kursie, ale bardzo, bardzo ważne jest, aby mieć podejście
typu "dziel i zwyciężaj", pracować małymi krokami i stale testować po każdym kroku, nie pisać 1000 linii kodu, a następnie
powiedzieć, ok, skompiluj i przetestuj.
To nie jest dobre podejście.
Unikaj zbyt wielu zmian na raz.
Wprowadzając zmiany, stosuj je przyrostowo, dodaj jedną zmianę, a następnie dokładnie przetestuj przed rozpoczęciem
kolejnego kroku.
Może to pomóc w zmniejszeniu wszelkiego rodzaju błędów, a także ogranicza twój zestaw problemów.
Więc jeśli masz błąd, natychmiast wiesz, gdzie jest w kodzie, ponieważ właśnie skompilowałeś
i właśnie dodałeś tę linię lub liczbę linii.
Ponownie, nie mogę podkreślić znaczenia debugowania pisania wysokiej jakości kodu, zapobiegania błędom.
Te techniki rozwiązywania problemów pozwolą Ci zaoszczędzić tonę czasu i sprawią, że będziesz znacznie lepszym programistą
top tier.
Dlatego w kolejnych wykładach chcę opowiedzieć o kilku typowych błędach, które widzimy w języku programowania
c.
Ponadto chcę trochę porozmawiać o stosie wywołań.
Chcę przejść przez debugger, który wprowadza cię do opcji menu i jak możesz zatrzymać i uruchomić
zegarki i tak dalej.
I chcę również pomóc w identyfikacji niektórych wspólnych błędów kompilatora, które widzisz, jak interpretować kompilatory, ostrzeżenia
i błędy kompilatora.
Co to znaczy, jeśli kompilator mówi o tym?
Co to znaczy, jeśli kompilator daje ci to ostrzeżenie?
Dziękuję.