Wie man Bugs in der Programmierung vermeidet

Kategorie: Quick Tips Veröffentlicht: Freitag, 01. September 2017 Geschrieben von Kevin Chileong Lee
Bugs vermeiden

Kennst du das Problem, dass nach minutenlanger Programmierung erstmal gar nichts funktioniert? Wächst dein Code zu einer unübersichtlichen Wust an und du schlenderst von einem Bug zum nächsten? Wird der Kunde schon unruhig, weil immer wieder neue Fehler auftreten?

Ich zeige dir, wie du Fehler bei der Programmierung vermeidest.

Zunächst einmal sind Bugs was völlig normales. Tatsächlich gibt es kein Programm ohne Bugs. Jedoch muss man unterscheiden und die Bugs klassifizieren.

Klassifizierung von Bugs

Trivial

Trivial Bugs sind nichts ungewöhnliches und haben keinen echten Einfluss auf die Funktionalität deiner Software. Diese Bugs können von kosmetischer Natur sein, wie zum Beispiel leichte optische Fehler im CSS/HTML. 

Diese Fehler sind leicht zu identifizieren und zu beheben.

Minor

Minor Bugs haben ebenfalls keinen großen Einfluss auf die Hauptfunktionalität deiner Software. Diese Fehler sind weniger auffällig, wie die Trivial Bugs. Zum Beispiel sind das Fehler die nur auftreten, wenn man eine bestimmte Aktion ausführt. Das könnte eine fehlende Übersetzung auf einer bestimmten Seite sein oder das Fehlen einer Validierung eines Pflichtfeldes im Formular.
Auch das Problem was ich letztens bei einem Kunden hatte gehört dazu. Da wurde der Autorenname in der URL falsch dargestellt. Der Link funktionierte, jedoch war im Namen ein Tippfehler.

Major

Major Bugs sind schwerwiegende Fehler, die das Arbeiten mit der Software behindern und verhindern. Sie haben Einfluss auf die Hauptfunktionalitäten deiner Software. Das können Funktionen sein, die nicht funktionieren, aber die Software nicht zum Absturz bringen. Beispielsweise ein Mailformular, das keine Mails verschickt. 
Auf der Arbeit hatte unser Intranet bei einem Mitarbeiter die Abwesenheitstage nicht richtig gespeichert, jedoch erschien keine Fehlermeldung und das Programm lief normal weiter. Das wäre auch ein Beispiel für ein Major Bug.

Critical

Critical bugs sind alle Fehler die dazu führen, daß deine Software nicht mehr weitergenutzt werden kann. Du kennst es vielleicht, daß man eine Aktion ausführt und plötzlich erscheint eine Fehlermeldung und es geht nichts mehr. Die einzige Möglichkeit ist es die vorherige Seite neuzuladen und auf die Aktion/Funktion zu verzichten.
Diese Funktionen blockieren den Betrieb und sind die schwerwiegensten Fehler. Diese Fehler gilt es unbedingt zu vermeiden.

Fehlervermeidungsstrategien

Nachdem die Bugs klassifiziert sind, können wir nun Techniken entwickeln diese zu vermeiden. Dabei zielen wir insbesondere auf Major und Critical Bugs. Besonders letzteres gilt es zu vermeiden - und das ist möglich!

Ordentliche Namen vergeben

Die Fehlervermeidung fängt bereits mit der Vergabe der Namen für Variabeln, Funktionen und Klassen an. Namen sollten in der Programmierung so vergeben werden, dass sie eine Bedeutung haben. Das bedeutet, daß man die Aufgabe/Nutzen der Variable, Funktion und Klasse bereits am Namen erkennen kann. Generische Namen wie:

$listCount = count($list);
for(var $i = 0; $i < $listCount; $i++)...

function process();

class StuffUtility;

sollte man vermeiden. Denn es ist nicht ablesbar, welche Index durchlaufen wird oder welche Informationen im Array $list stehen. Um das herauszufinden, muss man weiter im Code suchen. Auch ist der Funktionsname process(); unzureichend. Was wird hier bearbeitet? Was ist das Ziel dieser Funktion?

Vergebe sinnvolle Namen die der Variable, Funktion und Klasse eine eindeutige Bedeutung geben.

Modularer Aufbau

Die Strukturierung deines Projektes ist sehr wichtig. Das fängt bei der Verzeichnisstruktur an und geht bis zur richtige Codeeinrückung im Quellcode. In Typo3 empfehle ich die Typo3 eigenen Coding Standards.

Lagere Funktionalitäten in Funktionen aus und beachte dabei folgende Punkte:

  • Eindeutige Funktionsnamen
  • Pre- und Postconditions aufschreiben als auch eine kurze Erläuterung, was diese Funktion leisten soll
  • So wenig Code und Funktionalität, wie möglich in eine Funktion kapseln
    • vermeide große Funktionen, sonst werden sie zu Spaghetti!
  • Verallgemeine die Funktionen, so dass sie universal einsetzbar sind
    • dadurch kommst du in die Situation vermehrt bereits erprobte Funktionen zu nutzen und produzierst weniger Fehler.

Vereine ähnliche Funktionen in Klassen. Dadurch kannst du mit der Zeit deine eigene Bibliothek von Utility Klassen erstellen.

Exception Handling

Ausnahmebehandlung ist sehr wichtig, insbesondere um deine Anwendung trotz Fehler in keinem Blockzustand kommen zu lassen. Wenn du mit Frameworks, wie Extbase, arbeitest, dann werden viele Funktionen im Fehlerfall Exceptions werfen. Auch du kannst Exceptions werfen:

throw new \Exception('Exception example', time());

falls eine Validierung fehlschlägt. Auf dieser Weise können Funktionen oder komplette Algorhitmen trotz Fehlerfälle weiterarbeiten. Zum Beispiel kann in einem Import von Daten Fehler auftreten, aber du möchtest im Fehlerfall nicht den kompletten Import abbrechen, sondern lediglich den aktuellen Eintrag. Oder du möchtest den Benutzer über den Fehler informieren mit einer entsprechenden Fehlermeldung.

Mit Exceptions kannst du das bequem machen und das Gute ist, dass jede Exception weitergeleitet werden kann. Zum Beispiel:


class CSVImportUtility
{
	public function importCsvFile($inCsvFileWithPath)
	{
	    try
	    {
	      if ($this->validateCsvFile($inCsvFileWithPath))
	      {
	         
	      }
	    }catch(\Exception $e)
	    {
	      throw new \Exception('Error validation in importCsvFile function', time(), $e);
	    }
    
		...
	}

  	public function validateCsvFile($inCsvFileWithPath)
  	{
	    if (!is_file($inCsvFileWithPath))
	    {
	       throw new \Exception('CSV file does not exit.', time());
	    }
	    
	    return TRUE;
  	}
}

$csvImportInstance = new CSVImportUtility();
try
{
	$csvImportInstance->importCsvFile('test.csv');
}catch(\Exception $e)
{
	$this->view->assign($e);
}

In der Zeile 34 starten wir den Import eine CSV Datei. In Zeile 8 wird als erstes die Validierungsfunktion aufgerufen. In Zeile 22 wird geprüft, ob es die Datei gibt und falls nicht in Zeile 24 eine Exception geworfen. Diese Exception wird in der Funktion: importCsvFile aufgefangen. In Zeile 14 wird ein neue Exception erstellt mit zusätzlicher Fehlermeldung und die Exception aus der Validierungsfunktion angehängt.
In Zeile 37 wird dann die Exception von der importCsvFile - Funktion aufgefangen und der View zur Anzeige weitergeleitet. Die View kann nun den kompletten Stacktrace von validateCsvFile bis importCsvFile mit den entsprechenden Fehlermeldungen anzeigen.

Auf dieser Weise kann man auf Fehler durch das Werfen von Exceptions reagieren, welche man so lange weiterleitet bis man an der View angekommen ist, um dort dann eine adäquate Fehlermeldung für den Benutzer zu erzeugen.

Unit Tests

Unit Tests sind ein zeitaufwendige Angelegenheit und auch ich habe beruflich selten dazu die Gelegenheit sie zu erstellen. Das bedauer ich sehr, da sie ein sehr gutes Instrument sind den Code automatisiert zu testen. Mit Unit Tests kannst du ein Frontendverhalten simulieren und dein Code testen. Die Tests sind jederzeit wiederholbar.

Leider muss man jeden Testfall, unter Berücksichtigung der Konventionen der Unit Test Bibliothek, selbst schreiben. Deswegen empfehle ich Unit Tests nur bei größeren Projekten einzusetzen. Da bei kleinen Projekten, meiner Erfahrung nach, immer die Zeit fehlt. 

Wenn du in dieses Thema einsteigen willst, dann gibt es für Typo3 ein offizielles Tutorial und ergänzend dazu die offizielle Seite von PHPUnit.

Im übrigen erzeugt der Extension Builder ebenfalls Unit Tests. D.h. du kannst ein neues Plugin erstellen und dort deine ersten Schritte in Typo3 und PHPUnit machen.

Fehlerunterdrückung

Mit dem try-catch - Block lassen sich nur Exceptions abfangen. Andere Fehler werden dennoch auf einer weißen Seite angezeigt, was zu einem Critical Fehler führt. Das lässt sich in vielen Funktionen unterbinden indem man ein @ vor dem Funktionsaufruf setzt. Beispiel:

@chmod($csvFile);

Dadurch werden auftretende Fehler ignoriert, also nicht angezeigt. Dadurch lassen sich eigentliche Critical Fehler auf Major oder Minor Fehler abschwächen.

Fazit

Auf dieser Weise lassen sich viele Fehler eliminieren und die Fehler die auftreten ordentlich abfangen. Dadurch bekommt der Benutzer eine bessere Arbeitserfahrung und eine aussagekräftige Fehlermeldung. Die Fehlerunterdrückung ist eine Möglichkeit Critical Bugs abzuschwächen und somit ein blockierenden Zustand vermeidbar.

Kennst du noch weitere Fehlervermeidungsstrategien? Dann schreibe sie auf meine Facebook Seite oder schicke sie mir über das Kontaktformular. Ich freue mich deine Erfahrungen zu lesen.

 

Cookies erleichtern die Bereitstellung unserer Dienste. Mit der Nutzung unserer Dienste erklären Sie sich damit einverstanden, dass wir Cookies verwenden.
Weitere Informationen Ok Ablehnen