Ostatnio było o debuggowaniu elixir z wykorzystaniem Visual Studio Code – co jest dalej uważam super opcją, mimo, że samo debugowanie ma swoje wady. Dziś zaś dla tycz wszystkich którzy nie lubią VS Code – wiem, że tacy są. Jak możemy nie tylko debuggować elixir, ale także erlang z wykorzystaniem narzędzi dostępnych w erlang OTP.

Dla celu krótkiego turoriala potrzebujemy jakiś prosty projekt który może robić nić albo może zawierać bencode.ex. Tą część przygotowawczą pozostawiam wam. Nie potrzebujemy niczego co będzie ładowane podczas startu. Więc naprawdę minimum jest wymagane.

Jak już wszystko mamy gotowe, to upewnijmy się, że przynajmniej mamy erlang w wersji 19 no i przypadłoby się zaktualizować elixir też. Ale jeżeli działało wam debugowanie w VS Code to tutaj nic nie musicie robić.

Zainicjalizowanie debuggera

Jeżeli mamy wszystko stworzone, wchodzimy za pomocą terminala do naszego katalogu projektu i odpalamy iex:

iex -S mix

Następnie z miejsca uruchamiamy debuggera:

:debugger.start()
Okno Monitora/Debuggera
Okno Monitora/Debuggera

Ale byśmy mogli coś debuggować, to potrzebujemy załadować nasz moduł. W tym celu mamy dyspozycji moduł :int i metodę ni/1:

:int.ni(Bencode)

To spowoduje, że nasz moduł zostanie dodany do listy załadowanych modułów:

Okno Monitora z załadowanym modułem
Okno Monitora z załadowanym modułem

Oczywiście moglibyśmy dodać nasz moduł poprzez menu Modules | Interpret

Okno dodawania modułu
Okno dodawania modułu

Ale tutaj nie udało mi się załadować nigdy skompilowanego modułu (plik beam). Nie wiem czemu gdyż większość metod (jak nie wszystkie) z :int są skrótem elementów z UI.

Mając nasz moduł załadowany, możemy go przeglądać Modules | Nasz Module | View albo po prostu dwu klik na module z lewej strony okna Monitor.

Okno podglądu załadowanego modułu
Okno podglądu załadowanego modułu

Ustawienie breakpoint

Wydawałoby się takie proste………. A jednak. No dobra, jest to dość proste, możemy to zrobić z poziomu iex:

:int.break(Bencode, 33)

Ale jest to o tyle trudne, że musimy znać linię kodu na której chcemy się zatrzymać. Na szczęście z widoku modułu (patrz poprzedni krok) możemy też dodawać breakpointy. Jeżeli otworzymy nasz moduł to mamy do dyspozycji trzy rodzaje breakpointów:

  • Line break – jak sama nazwa wskazuje, zatrzymuje się na określonej linii;
  • Conditional break – zatrzymuje się wtedy kiedy jakiś warunek zostanie spełniony;
  • Function break – zatrzymuje się przy wywołaniu konkretnej funkcji (jak i wszystkich jej przeciążeń).
Line Break Breakpoint
Line Break Breakpoint
Conditional Break Breakpoint
Conditional Break Breakpoint
Function Break Breakpoint
Function Break Breakpoint

 

Za każdym razem możemy ustawić breakpointy dość prostu, jednak jeżeli nam przycisk OK nie działa to wystarczy zmodyfikować domyślne wartości w oknie, to znaczy nawet usunąć znak i go dodać, usunąć cyfrę z numeru linii i ją dodać. To spowoduje, że przycisk będzie śmigał.

Jeżeli zaś mamy dobrą pamięć to ogólnie moduł :int daje nam bardzo dużo fajnych metod, warto przejrzeć je przynajmniej – możliwe, że ułatwią nam pracę, kto co lubi.

Proces debuggowania

Skoro mamy już wszystko przygotowane to w iex możemy wyzwolić debuggera za pomocą wywołania funkcji, na której mamy ustawiony breakpoint:

Bencode.decode("i15e")

To zablokuje działanie iex i w oknie Monitor zobaczymy taki o to widok:

Widok breakpointa w Monitor
Widok breakpointa w Monitor

Teraz jak klikniemy dwukrotnie na zaznaczonej linijce otworzy nam się nasze okno modułu z linijką, na której zatrzymał się debugger. Otwarcie tego za pomocą dwukliku na module, powoduje, że musimy kliknąć Step by zobaczyć zatrzymanie debuggera. Dziwne, ale tak działa. Więc ku pamięci, klikamy na liście procesów nie na liście modułów :)

Widok debuggera
Widok debuggera

Teraz za pomocą przycisków możemy sterować co i jak:

  • Step – wchodzenie w każdą możliwą linijkę, metodę;
  • Next – przechodzenie po kolejny linijkach danej metody;
  • Continue – przechodzi do następnego breakpoint albo końcy;
  • Finish – kończy;
  • Up i Down – pozwala przechodzić pomiędzy funkcjami/stack trace; tak jakby skąd tutaj trafiłem, wróć tam gdzie jestem.

Podsumowanie

To tyle, nie udało mi się zmienić wartości zmiennych, ale to chyba zrozumiałem ;) tylko Elixir na to zezwala a erlang nie, choć opcja edycji jest możliwa – nie wiem zaś czy ona działa czy też nie.

Temat debuggowania rozwiązań elixirowych nie jest skończony, są dodatkowe opcje i metody które są dużo bardziej wydajniejsze. Choć ja i tak dalej lubię okienkowe debuggowanie :) O tych innych opcjach, może jeszcze kiedyś napiszę :)