Strona wykorzystuje ciasteczka by usprawnić komfort z jej korzystania. Korzystając ze strony akceptujesz naszą Politykę Ciasteczek. X

Debugowanie w lokalnym środowisku [podstawowy]

Ostatnim razem wspomniałem o kilku trikach debugowania w aplikacjach który już zostały wydane na świat - tym razem zerkniemy na debugowanie w lokalnym środowisku, w trakcie produkcji. Oczywiście wszystko w tym wypadku zależy od nas id od tego jak przygotujemy aplikację, jednak jest parę uniwersalnych rozwiązań które na pewno zawsze się przydadzą:

1. Pomiar prędkości działania
Pomijając fakt, że zawsze warto programować aplikacje biorąc pod uwagę również słabsze komputery, pomiar prędkości jest dobrym sposobem by przetestować poprawność algorytmów, szczególnie jeśli z góry znam czas jaki powinny osiągnąć. Do pomiarów najlepiej dodać pętle by łatwiej było dostrzec różnice w czasie:

public static function measureProcessTime(fun:Function, repeat:int = 10):Number {
	var time:Number = getTimer();
	for(var i:int = 0; i < repeat; i++) {
		fun();
	}
	return getTimer() - time;
}
Warto dodać, że w tym wypadku bardzo przydają się lokalne funkcje które we Flash'u można utworzyć dosłownie wszędzie i zawsze będą działać, wystarczy dowolny kod zamknąć w następujący sposób:
var someVar:Number = 0;
someVar = 1;
function debug() {
	var otherVar:Number = 10;
	someVar += otherVar;
}
trace(measureProcessTime(debug));
}

2. Wędrowanie przez pętle.
Kolejny sposób na testowanie algorytmów. Najprościej mówiąc chodzi tutaj o wyświetlanie informacji tylko na wybranym punkcie pętli ale tak, żeby w każdej chwili można było zmienić jego położenie. Przykładowa implementacja:

private static var DEBUG_COUNT:int = 0;
private static var DEBUG_STEP:int = 0;
public static function nextStep():void {
	DEBUG_STEP++;
}
public static function prevStep():void {
	DEBUG_STEP--;
	if(DEBUG_STEP<0) DEBUG_STEP=0;
}
public static function resetDebug():void {
	DEBUG_COUNT = 0;
}
public static function countDebug():Boolean {
	DEBUG_COUNT++;
	return  DEBUG_COUNT == DEBUG_STEP;
}
Funkcje nextStep i prevStep należy podpiąć pod klawisze strzałek by można było się poruszać po pętli. Funkcja resetDebug powinna się pojawić przed rozpoczęciem testowanej pętli. I w końcu countDebug która zwróci true gdy doliczy do wybranego kroku. Choć nie ma tutaj nic nadzwyczajnego, wędrowanie po pętli ułatwia debugowanie w nie porównywalnym stopniu. W działaniu, z wykorzystaniem algorytmu rysowania linii może to wyglądać tak:
(Użyj klawiszy góra i dół by wybrać krok algorytmu)

3. Nakładka graficzna.
Chyba nie ma wątpliwości, że wyświetlanie informacji w postaci przejrzystej grafiki zamiast listy zmiennych jest zawsze o niebo przyjemniejsze, dlatego każda porządna aplikacja powinna dawać możliwość rysowania (z wykorzystaniem klasy Graphics) ponad wszystkimi obiektami. Osiągnąć to można trzymając całą aplikację w jednym MovieClipie, coś na rodzaj "zbiornika", a tuż nad nim umieścić obiekt, np. Sprite, który będzie pusty, ale do którego zawsze będzie dostęp z każdej lokacji w aplikacji:
public static debug:Sprite;
public function DocumentClass() {
	var main:MyApplication = new MyApplication();
	addChild(main);

	var debug:Sprite = new Sprite();
	addChild(debug);
}
Teraz wystarczy napisać DocumentClass.debug.graphics by mieć dostęp do grafiki widocznej ponad całą aplikacją. Osobiście często korzystam z tego by sprawdzić rozmiary obiektów znajdujących się na ekranie:

Debugowanie po stronie użytkownika [podstawowy]

Debugowanie to potoczna nazwa procesu usuwania błędów (lub po prostu nie pożądanego działania) z kodu źródłowego. Programując w Flash Professional lub FlashDevelop mamy dostęp do narzędzie debuggera które swoją rolę sprawuje całkiem nieźle i na pewno nie jednej osobie pomogło już usunąć błędy we własnych projektach. Niestety debugger jest narzędziem dostępnym jedynie twórcom aplikacji którzy jednak nie zawsze są w stanie przewidzieć (i sprawdzić) wszystkie możliwe scenariusze działania które podejmie docelowy odbiorca. Dlatego dla pewności zawsze warto zaimplementować system wyłapywania błędów od strony korzystających z aplikacji użytkowników - w tym celu przyjrzymy się kilku najpopularniejszym mechanizmom.

1. Główna pętla.
Ten, zdawać by się mogło, trywialny element powinien być częścią każdej szanującej się aplikacji i to nie tylko dlatego, że ułatwia debugowanie ale również czyni kod przejrzystszym i mniej podatnym na wycieki pamięci. Ale czym właściwie jest "główna pętla"? We Flash'u sprowadza się do posiadania tylko JEDNEGO zdarzenia "ENTER_FRAME" w całej aplikacji, co oznacza, że wszystkie inny wykonywane funkcja będą wywodzić się bezpośrednio (lub pośrednio) z głównej pętli. Takie podejście ułatwia wyłapywanie błędów w nieporównywalnym stopniu bo wystarczy, że kod głównej pętli obejmiemy słowami kluczowymi try i catch, a już żaden wyrzucony Error nie umknie naszej uwadze. Główna pętla z try i catch może wyglądać na przykład tak:

public function render(e:Event):void {
	try {
		processPlayer();
		processEnemy();
		processMap();
	} catch(e:Error) {
		trace("Error!");
	}
}

2. Dziennik.
Chociaż wyłapywanie błędów jest bardzo ważne, to jednak samo w sobie może okazać się mniej istotne niż na przykład okoliczności w których doszło do wyrzucenia wyjątku, dlatego drugim bardzo ważnym elementem każdej aplikacji powinien być dziennik zapisujący wykonywanie wszystkich kluczowych funkcji przez użytkownika - w jakim stanie rozpoczął korzystanie z aplikacji (wersja Flash, system operacyjny itd.), jakich przycisków używał, przez jakie okienka przeszedł itp. A jeśli będzie to gra, to na pewno na jakiej jest mapie, w jakiej jest pozycji i z czym miał już do czynienia. Przechowując wszystkie te informacji łatwiej będzie nam odtworzyć warunki w jakich użytkownik otrzymał błąd.
Klasa dziennika jest zawsze najprostszym elementem do zaimplementowania:

public class Log {
	private static var log:String = "";
	public function Log() {}
	public static function add(s:String):void {
		log += s+"n";
	}
	public static function toClipboard():void {
		System.setClipboard(log);
	}
}

3. Konsola.
Chyba każdy gracz chociaż raz korzystał z konsoli w grach PC, choćby po to żeby sobie wpisać "kody na nieśmiertelność". Konsola to potoczne określenie (zwykle ukrytej) linii komend w aplikacji, pozwalająca użytkownikowi wymusić działanie pewnych, z góry ustalonych funkcji. Zaimplementowanie dobrej konsoli to już nieco roboty, na szczęście w Internecie można znaleźć sporo gotowych rozwiązań, jak na przykład: Flash Console. Zdecydowanie każdy powinien mieć linie komend w swojej aplikacji - jeden raz wystarczy by już na zawsze się w niech zakochać.

Na koniec gdy nasza aplikacja jest już gotowa, warto w głównej pętli pozbyć się funkcji trace i zastąpić ją czymś co pozwoli nam otrzymać informacje o ewentualnych błędach, na przykład wysyłając je sobie na e-mail.