\chapter{Debugging} \shortquote{60\% of coding time is finding errors}{Famous last words} Es hilft ungemein, wenn zusammengeh\"orige Skripte und Funktionen im gleichen Ordner auf der Festplatte zu finden sind. Es bietet sich also an, f\"ur jede Analyse einen eigenen Ordner anzulegen und in diesem die zugeh\"origen \codeterm{m-files} abzulegen. Auf eine tiefere Schachtelung in weitere Unterordner kann in der Regel verzichtet werden. \matlab{} erzeugt einen ``MATLAB'' Ordner im eigenen \file{Documents} (Linux) oder \file{Eigene Dokumente} (Windows) Ordner. Es bietet sich an, diesen Ordner als Wurzelverzeichnis f\"ur eigene Arbeiten zu verwenden. Nat\"urlich kann auch jeder andere Ort gew\"ahlt werden. In dem Beispiel in \figref{fileorganizationfig} wird innerhalb dieses Ordners f\"ur jedes Projekt ein eigener Unterordner erstellt, in welchem wiederum f\"ur jedes Problem, jede Analyse ein weiterer Unterodner erstellt wird. In diesen liegen sowohl die ben\"otigten \codeterm{m-files} also auch die Resultate der Analyse (Abbildungen, Daten-Dateien). Zu bemerken sind noch zwei weitere Dinge. Im Projektordner existiert ein Skript (analysis.m), das dazu gedacht ist, alle Analysen aufzurufen. Des Weiteren gibt es parallel zu den Projektordnern einen \file{functions}-Ordner in dem Funktionen liegen, die in mehr als einem Projekt oder einer Analyse gebraucht werden. Beim Betrachten dieses Layouts f\"allt auf, dass es sehr wahrscheinlich ist, dass bestimmte Namen f\"ur Funktionen und Skripte mehrfach verwendet werden. Es ist nicht verwunderlich, wenn eine \file{load\_data.m} Funktion in jeder Analyse vorkommt. In der Regel wird dies nicht zu Konflikten f\"uhren, da \matlab{} zuerst im aktuellen Ordner nach passenden Dateien sucht (mehr Information zum \matlab-Suchpfad in Box~\ref{matlabpathbox}). \begin{figure}[tp] \includegraphics[width=0.75\textwidth]{no_bug} \titlecaption{\label{fileorganizationfig} M\"ogliche Organisation von Programmcode im Dateisystem.}{ F\"ur jedes Projekt werden Unterordner f\"ur die einzelnen Analysen angelegt. Auf Ebene des Projektes k\"onnte es ein Skript (hier ``analysis.m'') geben, welches alle Analysen in den Unterordnern anst\"o{\ss}t.} \end{figure} \begin{ibox}[tp]{\label{matlabpathbox}Der \matlab{} Suchpfad} Der Suchpfad definiert, wo \matlab{} nach Skripten und Funktionen sucht. Wird eine Funktion aufgerufen wird zun\"achst im aktuellen Arbeitsverzeichnis einem Treffer gesucht. Schl\"agt diese Suche fehl, so arbeitet sich \matlab{} durch den \codeterm{Suchpfad} (siehe Abbildung). Der \codeterm{Suchpfad} ist eine Liste von Ordnern in denen \matlab{} nach Funktionen und Skripten suchen soll. Die Suche nach der aufgerufenen Funktion wird dabei von oben nach unten durchgef\"uhrt. Das heisst, dass es bei Namensgleichheit eine Rolle spielen kann an welcher Stelle im Suchpfad der erste Treffer gefunden wird. Wichtig: \matlab{} sucht nicht rekursiv! Wenn die gew\"unschte Funktion in einem Unterordner des aktuellen Arbeitsverzeichnisses liegt, dieses aber nicht explizit im Suchpfad enthalten ist, so wird die Funktion nicht gefunden. Der Suchpfad kann sowohl \"uber die Kommandozeile mit dem Kommandos \code{addpath()} und \code{userpath()} als auch\"uber die in der Abbildung gezeigte GUI angezeigt und eingestellt werden. Die GUI erlaubt Ordner aus dem Suchpfad zu entfernen, neue Ordner (optional inklusive aller Unterordner) hinzuzuf\"ugen oder die Reihenfolge der Pfade zu ver\"andern. Zum Wechseln des aktuellen Arbeitsverzeichnisses wird das Kommando \code{cd} verwendet. \code{which} zeigt an, in welchem Pfad eine bestimmte Funktion gefunden wurde. Das aktuelle Areitsverzeichnis wird durch den Aufruf \code{pwd} auf der Kommandozeile ausgegeben. \end{ibox} \section{Namensgebung von Funktionen und Skripten} \matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand des Namens. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Die beiden Dateien \file{test\_funktion.m} und \file{Test\_Funktion.m} zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art der Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine Information \"uber den Unterschied der beiden Funktionen. Auch sagt der Name nahezu nichts \"uber den Zweck der Funktion aus. Die Namensgebung f\"allt mitunter nicht leicht --- manchmal ist es sogar der schwierigste Aspekt des Programmierens! Ausdrucksstarke Namen zu finden lohnt sich aber. Ausdrucksstark bedeutet, dass sich aus dem Namen R\"uckschl\"usse auf den Zweck ziehen lassen sollte. \begin{important}[Benennung von Funktionen und Skripten] Die Namen von Funktionen und Skripten sollten m\"oglichst viel \"uber die Funktionsweise oder den Zweck aussagen (\file{firingrates.m} statt \file{uebung.m}). Gute Namen f\"ur Funktionen und Skripte sind die beste Dokumentation. \end{important} In Namen verbietet \matlab{} verbietet Leerzeichen, Sonderzeichen und Umlaute. Namen d\"urfen auch nicht mit Zahlen anfangen. Es mach f\"ur die Namensgebung selbst keine weiteren Vorgaben. Allerdings folgt die Benennung der in \matlab{} vordefinierten Funktionen gewissen Mustern: \begin{itemize} \item Namen werden immer klein geschrieben. \item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr()} f\"ur die Kreuzkorrelation oder \code{repmat()} f\"ur ``repeat matrix'') \item Funktionen, die zwischen Formaten konvertieren sind immer nach dem Muster ``format2format'' (z.B. \code{num2str()} f\"ur die Konvertierung ``number to string'', Umwandlung eines numerischen Wertes in einen Text) benannt. \end{itemize} \begin{important}[Benennung von Variablen] Die Namen von Variablen sollten m\"oglichst viel \"uber ihren Inhalt aussagen (\varcode{spike\_count} statt \varcode{x}). Gute Namen f\"ur Variablen sind die beste Dokumentation. \end{important} \begin{lstlisting}[label=chaoticcode, caption={Un\"ubersichtliche Implementation des Random-walk.}] num_runs = 10; max_steps = 1000; positions = zeros(max_steps, num_runs); for run = 1:num_runs for step = 2:max_steps x = randn(1); if x<0 positions(step, run)= positions(step-1, run)+1; elseif x>0 positions(step,run)=positions(step-1,run)-1; end end end \end{lstlisting} \pagebreak[4] \begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}] num_runs = 10; max_steps = 1000; positions = zeros(max_steps, num_runs); for run = 1:num_runs for step = 2:max_steps x = randn(1); if x < 0 positions(step, run) = positions(step-1, run) + 1; elseif x > 0 positions(step, run) = positions(step-1, run) - 1; end end end \end{lstlisting} % \begin{exercise}{logicalVector.m}{logicalVector.out} % Erstelle einen Vektor \varcode{x} mit den Werten 0--10. % \begin{enumerate} % \item F\"uhre aus: \varcode{y = x < 5} % \item Gib den Inhalt von \varcode{y} auf dem Bildschirm aus. % \item Was ist der Datentyp von \varcode{y}? % \item Gibt alle Elemente aus \varcode{x} zur\"uck, die kleiner als 5 sind. % \end{enumerate} % \pagebreak[4] % \end{exercise}