diff --git a/programmingstyle/lecture/programmingstyle.tex b/programmingstyle/lecture/programmingstyle.tex index f74717b..9a048e7 100644 --- a/programmingstyle/lecture/programmingstyle.tex +++ b/programmingstyle/lecture/programmingstyle.tex @@ -1,215 +1,208 @@ -\chapter{\tr{Programming style}{Programmierstil}} +\chapter{\tr{Code style}{Programmierstil}} \shortquote{Any code of your own that you haven't looked at for six or more months might as well have been written by someone else.}{Eagleson's law} -\selectlanguage{ngerman} +%\selectlanguage{ngerman} +Cultivating a good code style not a matter of good taste but is +a key ingredient for understandability, maintainability and in the end +facilitates reproducibility of scientific results. Programs should be +written and structured in a way that supports outsiders as well the +author himself --- a few weeks or months after it was written --- to +understand the programs' rationale. Clean code pays off for the +original author as well as others that are supposed to use the code. -Guter Programmierstil ist keine Frage des guten Geschmacks sondern des -Verst\"andnisses von Programmcode und ein Baustein in dem Bestreben -wissenschaftlichen Erkenntnisgewinn reproduzierbar zu -machen. -Programme sollten so geschrieben und strukturiert sein, dass es sowohl -einem Au{\ss}enstehenden als auch einem selbst --- nach ein paar -Wochen oder Monaten! --- leicht f\"allt den Programmablauf -nachzuvollziehen und zu verstehen. Saubere Programmierung zahlt sich -in erster Linie f\"ur einen selbst aus und macht es aber gleichzeitig -f\"ur andere Personen leichter, den Code nachzuvollziehen und zu -benutzen. - -Guter Programmierstil greift auf unterschiedlichen Ebenen an: +Clean code addresses several issues: \begin{enumerate} -\item Die Dateistruktur von Programmen. -\item Die Namensgebung von Skripten und Funktionen. -\item Die Namensgebung f\"ur Variablen und Konstanten. -\item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im - Code hervorzuheben. -\item Verwendung von Kommentaren und Hilfetexten. -\item Auslagerung von Funktionalit\"at in eigene Funktionen. +\item The programs' structure. +\item Naming of scripts and functions. +\item Naming of variables and constants. +\item Application of indentation empty lines to define blocks. +\item Use of comments and inline documentation. +\item Delegation of repeated code to functions and dedicated + subroutines. \end{enumerate} -\section{Organisation von Programmdateien im Dateisystem} - -In der Einf\"uhrung zu Funktionen und Skripten wurde schon einmal ein -typisches Programmlayout vorgestellt (box\,\ref{whenscriptsbox}). Hier -wurde vorgeschlagen ein Skript als Kontrollskript zu verwenden. Dieses -kontrolliert den weiteren Programmablauf, ruft Funktionen auf, -\"ubergibt Argumente und nimmt R\"uckgabewerte entgegen. Eine solche -Struktur macht es einfach den Ablauf zu verstehen. Es bleibt aber die -Frage, wie man das Kontrollskript unter den anderen \codeterm{m-files} -als solches erkennt. Um dieses zu erleichtern gilt es zwei Dinge zu -beachten: (i) Wie werden Programme im Dateisystem organisiert? (ii) Wie -werden Programme benannt? - -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}). +\section{Organization of programs on the file system} + +While introducing scripts and functions we suggested a typical program +layout (box\,\ref{whenscriptsbox}). The idea is to create a single +entry point by having one script that controls the rest of program by +managing data and results and calling functions that work on the data +and produce the results. Applying this structure makes it easy to +understand the flow of the program but two questions remain: (i) How +to organize the files on the file system and (ii) how to name them +that the controlling script is easily identified among the other +\codeterm{m-files}. + +Upon installation ``MATLAB'' creates a folder called \emph{MATLAB} in +the user space (Windows: My files, Linux: Documents, MacOS: +Documents). Since this folder is already appended to the Matlab search +path (Box~\ref{matlabpathbox}), it is easiest to stick to it for the +moment. Of course, any other location can specified as well. Generally +it is of great advantage to store related scripts and functions within +the same folder on the hard drive. An easy approach is to create a +project-specific folder structure that contains sub-folders for each +task (analysis) and to store all related \codeterm{m-files} +(screenshot \ref{fileorganizationfig}). In these task-related folders +one may consider to create a further sub-folder to store results +(created figures, result data). On the project level a single script +(analysis.m) controls the whole process. In parallel to the project +folder we suggest to create an additional folder for functions that +are or may be relevant across different projects. + +Within such a structure it is quite likely that programs in different +projects share the same name (e.g. a ``load\_data.m'' +function). Usually this will not lead to conflicts due to the way +matlab searches for matching functions which always starts in the +current folder (more information on the \matlab-path in +Box~\ref{matlabpathbox}). \begin{figure}[tp] \includegraphics[width=0.75\textwidth]{program_organization} - \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.} + \titlecaption{\label{fileorganizationfig} Possible folder structure + for maintaining program code on the file system.}{For each project + one maintains an individual folder in which analyses or tasks may + be structured in sub-folders. Within each analysis a ``main.m'' + script is the entry point for the analyses. On the project level + there could be a single script that triggers and controls all + analyses and tasks in the sub-folders. Functions that are of + general interest across projects are best kept in a dedicated + folder outside the project sub-structure.} \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. +\begin{ibox}[tp]{\label{matlabpathbox}\matlab{} search path} + The \codeterm{search path} defines where \matlab{} looks for scripts + and functions. When calling a function from the command line + \matlab{} needs to figure out which function is addressed and starts + looking for it in the current path. If this fails it will crawl all + locations listed in the search path (see figure). The + \codeterm{search path} is basically a list of folders. \matlab{} + will go through this list from front to end and the search will stop + on the first match. This implies that the order in the search path + may affect which version of functions that share the same name is + used. Note: \matlab{} does not perform a recursive search. That is, + a function that resides in a sub-folder that is not explicitly + listed in the \codeterm{search path} will not be found. \vspace{2ex} \includegraphics[width=0.9\textwidth]{search_path} \vspace{1.5ex} - 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. + The search path can be managed from the command line by using the + functions \code{addpath()} or \code{userpath()}. Alternatively, the + \matlab{} UI offers a graphical tool for adding/removing paths, or + changing the order of entries. + + The current working directory can be changed via the UI or also the + command line using the command \code{cd} (for change directory). The + current path is shown in the current directory text field of the UI + or can be requested using the command \code{pwd} (for present work + directory). The function \code{which()} shows the full path of the + actually used function. For example, finding out which \code{mean()} + function is used gives a result similar to: + \begin{lstlisting}[label=useofwhich, caption={Use of 'which'}] + >> which('mean') + /Applications/MATLAB2018b.app/toolbox/matlab/datafun/mean.m + \end{lstlisting} \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. +\section{Naming scripts and functions} +\matlab{} will search the search path (Box \ref{matlabpathbox}) +exclusively by name. It is case-sensitive this implies that the files +\file{test\_function.m} and \file{Test\_function.m} are two different +things. It is self-evident that choosing such names is nonsensical +because the name contains no cue about the difference between the two +and it further tells close to nothing about the purpose. Finding good +names is not trivial sometimes it is harder than the programming +itself. Expressive names, however, pay off! Expressive means that the +name provides information about the purpose. + +\begin{important}[Naming scripts and functions] + Function and script names should be expressive in the sense that the + name provides information about the function's purpose + (\file{estimate\_firingrate.m} tells much more than + \file{exercise1.m}). Choosing a good name replaces large parts of + the documentation. \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: +\matlab{} has a few rules about names: Names must not start with a +number, they must not contain blanks or other special characters like +e.g. German Umlauts. Otherwise one is free to use whatever suits. The +names of pre-defined functions shipped with \matlab{} follows several +patterns: \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. +\item Names are always lowercase. +\item Names are often abbreviations (e.g. \code{xcorr()} + stands for cross-correlation \code{repmat()} for ``repeat matrix''). +\item Functions that convert between formats are named according to + the pattern ``format2format'' (e.g. \code{num2str()} for ``number to string'' conversion). \end{itemize} -Andere \"ubliche Muster sind der \emph{camelCase}, bei dem die -Anf\"ange zusammengesetzter Worte jeweils gro{\ss} geschrieben werden -oder auch die Verwendung von Unterstrichen zur Trennung von -Namenskomponenten. Eine Funktion, die die Anzahl von -Aktionspotentialen bestimmt k\"onnte etwa \file{spikeCount.m} oder -\file{spike\_count.m} benannt werden. - - -\section{Namensgebung von Variablen und Konstanten} - -F\"ur die Bennennung von Variablen und Konstanten gelten die gleichen -Regeln wie f\"ur die Namen von Funktionen und Skripten. Die Maxime von -gutem Programmierstil ist: \emph{``Programmcode muss lesbar - sein.''}. Dabei helfen gute Namen ungemein. Auch wenn es schwer -f\"allt passende und trotzdem nicht zu lange Namen zu finden, sollte -einer gute Namensgebung sehr ernst genommen werden. - -W\"ahrend die Namen von Funktionen und Skripten ihren Zweck -beschreiben, sollten die Namen von Variablen ihren Inhalt -beschreiben. Eine Variable, die die mittlere Anzahl von -Aktionspotentialen speichert, k\"onnte also -\varcode{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht -nur einen sondern mehrere Werte aufnimmt, dann ist der Plural -angebracht (\varcode{average\_spike\_counts}). - -Die Laufvariablen von \code{for}-Schleifen werden oft nur \varcode{i}, -\varcode{j} oder \varcode{k} benannt und sollten aber die einzige Ausnahme -bzgl. ausdrucksstarker Namensgebung bleiben. - -\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. +There are other common patterns such as the \emph{camelCase} in which +the first character of compound words is capitalized. Other +conventions use the underscore to separate the individual words +\emph{snake\_case}. A function that counts the number of action +potentials could be named \file{spikeCount.m} or +\file{spike\_count.m}. + + +\section{Naming variables and constants} + +\matlab{} applies the same rules for naming variables and constants as +for the naming of scripts and functions. The dictum of good +code style is: ``Program code must be readable.'' Expressive +names are extraordinarily important in this respect. Even if it is +tricky to find expressive names that are not overly long, naming +should be taken seriously. + +While the names of scripts and functions describe the purpose, names +of variables describe the stored content. A variable storing the +average number of actions potentials could be called +\varcode{average\_spike\_count}. If this variable is meant to store +multiple spike counts the plural form would be appropriate +(\varcode{average\_spike\_counts}). + +The control variables used in the head of a \code{for} loop are often +simply named \varcode{i}, \varcode{j} or \varcode{k}. This kind-of +clashes with the previously made statements but since it is a very +common pattern the meaning of such variables in the context of the +loop is quite obvious. This should, however, be the only exception to +the general rule of expressive naming. + +\begin{important}[Naming of variables] + The names of variables should be expressive. That is, the name + itself should tell about the content of the variable. The name + \varcode{spike\_count} tells much more about the stored information + than \varcode{x}. Choosing a good variable name replaces additional + comments. \end{important} -\section{Codestil} +\section{Code style} +Readability of program code depends strongly on whether or not a +consistent code style is applied. A program that is only randomly +indented or that contains lots of empty lines is very hard to read and +to comprehend. Even though the \matlab{} language (as many others) +does not enforce indentation, indentation is very powerful for +defining coherent blocks. The \matlab{} editor supports this by an +auto-indentation mechanism. A selected section of the code and be +automatically indented by pressing the \keycode{Ctrl-I} combination. -Die Lesbarkeit von Programmen wird sehr durch den Codestil -beeinflusst. Ein Programm, in dem z.B. Schleifenk\"orper nicht (oder -zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu -verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen -wurde. Mit der Tastenkombination \keycode{Ctrl-I} (\keycode{Strg-I} -auf der deutschen Tastatur) kann ein markierter Bereich im \matlab{} -Editor automatisch richtig einger\"uckt werden. +Interspersing empty lines is very helpful to separate regions in the +code that belong together. Too many empty lines, however lead to +hard-to-read code because it might require more space than a granted +by the screen and thus takes overview. -Sparsam und konsistent eingef\"ugte einzelne Leerzeilen sind -hervorragend geeignet, um logische Abschnitte eines Programm zu -trennen. Zu viele Leerzeilen haben den Nachteil, dass das Programm -nicht mehr auf eine Seite passt und dadurch leichter der \"Uberblick -verlorgen geht. +The following two listings show basically the same implementation of a +random walk once in a rather chaotic version (listing +\ref{chaoticcode}) then in cleaner way (listing \ref{cleancode}) -Die beiden folgenden Listings \ref{chaoticcode} und \ref{cleancode} -zeigen die Implementation des random-walk einmal eher chaotisch und -einmal aufger\"aumt und \"ubersichtlich. - -\begin{lstlisting}[label=chaoticcode, caption={Un\"ubersichtliche Implementation des Random-walk.}] -num_runs = 10; -max_steps = 1000; +\begin{lstlisting}[label=chaoticcode, caption={Chaotic implementation of the random-walk.}] +num_runs = 10; max_steps = 1000; positions = zeros(max_steps, num_runs); @@ -232,7 +225,7 @@ end \pagebreak[4] -\begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}] +\begin{lstlisting}[label=cleancode, caption={Clean implementation of the random-walk.}] num_runs = 10; max_steps = 1000; positions = zeros(max_steps, num_runs); @@ -249,33 +242,30 @@ for run = 1:num_runs end \end{lstlisting} -\section{Verwendung von Kommentaren} - -Kommentarzeilen werden in \matlab{} mit dem Prozentzeichen \code{\%} -gekennzeichnet. Gezielt und sparsam eingesetzte Kommentare sind f\"ur -das Verst\"andnis eines Programms sehr n\"utzlich. Am wichtigsten -sind kurze Kommentare, die den Zweck und das Ziel eines Abschnitts im -Programm erl\"autern (z.B. \varcode{\% compute mean firing rate over all - trials}). - -Viele und h\"aufige Kommentare k\"onnen in der Entwicklungsphase eines -Programms sehr hilfreich sein, bl\"ahen aber den Code auf. Durch die -Verwendung guter Variablen- und Funktionsnamen sollten die meisten -Zeilen sowieso weitestgehend selbsterkl\"arend sein. - -Die beste Dokumentation ist der Code selbst. Gut geschriebener Code -mit ausdrucksstarken Variablen- und Funktionsnamen ben\"otigt keine -Kommentare, um den Zweck einzelner Zeilen zu erkl\"aren. z.B. ist\\ +\section{Using comments} + +It is common to provide extra information about the meaning of program +code by adding comments to it. In \matlab{} comments are indicated by +the percent character \code{\%}. Anything that is written in the +respective line following the percent is ignored and considered a +comment. When used sparsely comments can immensely important for +understanding. Comments are short sentences that describe the meaning +of the (following) lines in the program code. During the initial +implementation of a function they can be used to guide the development +but have the tendency to blow up the code and decrease readability. By +choosing expressive variable and function names, most lines should be +self-explanatory. + +For example stating the obvious does not really help:\\ \varcode{ x = x + 2; \% add two to x}\\ -ein v\"ollig unn\"otiger Kommentar. -\begin{important}[Verwendung von Kommentaren] +\begin{important}[Using comments] \begin{itemize} - \item Kommentare sollen die Absicht eines Programmabschnitts beschreiben. - \item Kommentare sind gut und wichtig --- sie m\"ussen aber richtig - sein! - \item Ein falscher Kommentar ist schlimmer als gar kein Kommentar! - \item Kommentare m\"ussen gepflegt werden, sonst sind sie wertlos! + \item Comments describe the rationale of the respective code block. + \item Comments are good and helpful --- they have to be true, however! + \item A wrong comment is worse than a non-existent comment! + \item Comments must be maintained just as the code. Otherwise they + may become wrong and worse than meaningless! \end{itemize} \widequote{Good code is its own best documentation. As you're about to add a comment, ask yourself, ``How can I improve the code so that this @@ -284,153 +274,139 @@ ein v\"ollig unn\"otiger Kommentar. \end{important} \pagebreak[4] -\section{Dokumentation von Funktionen} - -Bei allen vordefinierten \matlab{} Funktionen findet sich am Anfang -eine Kommentarblock, der den Zweck der Funktion, die verschiedenen -M\"oglichkeiten des Funktionsaufrufs und die Argumente und -R\"uckgabewerte beschreibt. Mit dem \code{help}- Befehl wird dieser -Kommentarblock angezeigt. Auch in eigenen Funktionen sind -diese Kommentare sehr wichtig. Siehe Listing~\ref{localfunctions} -f\"ur ein Beispiel einer gut dokumentierten Funktion. - -\begin{important}[Dokumentation von Funktionen] - Funktionen m\"ussen unbedingt kommentiert werde! +\section{Documenting functions} +All pre-defined \matlab{} functions begin with a comment block that +describes the purpose of the function, the required and optional +arguments, and the values returned by the function. Using the +\code{help} command one can display these comments and learn how to +use the function properly. Self-written functions can and should be +documented in a similar way. Listing ~\ref{localfunctions} shows a +well documented function. + +\begin{important}[Documenting functions] + Functions must be properly documented, otherwise a user (the author + him- or herself) must read and understand the function code which is + a waste of time! \begin{itemize} - \item In wenigen Zeilen kurz den Zweck der Funktion beschreiben. - \item Den Funktionskopf nocheinmal hinschreiben, damit - klar ist, in welcher Reihenfolge Argumente \"ubergeben werden. - \item F\"ur jedes Funktionsargument die Bedeutung, der erwartete - Datentyp (Zahl, Vektor, Matrix, etc.), und eventuell die Einheit, - in der die Zahlen erwartet werden (z.B. Sekunden). - \item Ebenso m\"ussen die R\"uckgabewerte beschrieben werden. + \item Describe with a few sentences the purpose of the function. + \item Note the function head to illustrate the order of the argments. + \item For each argument state the purpose, the expected data type + (number, vector, matrix, etc.) and, if applicable, the unit in + which a provided number must be given (e.g. seconds if a time is + expected). + \item The same for all return values. \end{itemize} \end{important} -\section{Auslagerung von Aufgaben in Funktionen} +\section{Delegating tasks in functions} +Comments and empty lines are used to organize code into logical blocks +and to briefly explain what they do. Whenever one feels tempted to do +this, one could also consider to delegate the respective task to a +function. In most cases this is preferable. -Kommentare oder Leerzeilen werden benutzt, um logische Abschnitte des -Codes abzutrennen und kurz zu erkl\"aren. Wenn eine -solche inhaltliche Trennung einzuf\"ugt wird, sollte man sich immer fragen, -ob dieser Teil des Programms nicht in eine eigene Funktion ausgelagert -werden sollte. Fast immer kann dies bejaht werden. +Not delegating the tasks leads to very long \codeterm{m-files} which +can be confusing. Sometimes such a code is called ``spaghetti +code''. It is high time to think about delegation of tasks to +functions. -Abschnitte nicht auszulagern f\"uhrt zu sehr langen -\codeterm{m-files}, die leicht un\"ubersichtlich werden. Diese Art von -Code wird \codeterm{Spaghetticode} genannt. Es ist h\"ochste Zeit -\"uber Auslagerung in Funktionen nachzudenken. - -\begin{important}[Gliederung in Funktionen] - Wann sollten Programmteile in eigene Funktionen ausgelagert werden? +\begin{important}[Delegating to functions] + When should one consider delegating tasks to specific functions? \begin{itemize} - \item Wenn innerhalb einer Funktion oder eines Skripts mehr als zwei - Einr\"uckungsebenen gebraucht werden. - \item Wenn sich Strukturen im Code mehr als einmal wiederholten. - \item Wenn man versucht ist, wiederholte Strukturen mit Copy and Paste zu erzeugen. + \item Whenever one needs more than two indentation levels to + organize to code. + \item Whenever the same lines of code are repeated more than once. + \item Whenever one is tempted to use copy-and-paste. \end{itemize} \end{important} -\subsection{Lokale Funktionen und geschachtelte Funktionen} - -Das Auslagern von Funktionalit\"at in eigene Funktionen f\"uhrt dazu, -dass eine F\"ulle von Dateien erzeugt wird, die die -\"Ubersichtlichkeit nicht unbedingt erh\"oht. Wenn die auszulagernde -Funktionalit\"at an vielen Stellen ben\"otigt wird ist es dennoch sehr -sinnvoll dies zu tun. Wenn Funktionen nur von einzelnen anderen -Funktionen verwendet werden, dann bietet \matlab{} die M\"oglichkeit -sogenannte \codeterm[Funktion!lokale]{lokale Funktionen} oder auch -\codeterm[Funktion!geschachtelte]{geschachtelte Funktionen} -(\enterm{nested functions}) in einer einzelnen Datei zu -erstellen. Listing \ref{localfunctions} zeigt ein Beispiel f\"ur eine -lokale Funktion. - -\pagebreak[3] -\lstinputlisting[label=localfunctions, caption={Beispiel f\"ur den - Einsatz von lokalen Funktionen.}]{calculateSines.m} - -Lokale Funktionen existieren in der gleichen Datei und sind nur dort -verf\"ugbar. Jede Funktion hat ihren eigenen G\"ultigkeitsbereich, das -hei{\ss}t, dass Variablen aus den aufrufenden Funktionen nicht -sichtbar sind. - -Bei sogenannten \codeterm[Funktion!geschachtelte]{geschachtelten -Funktionen} ist das anders. Diese werden innerhalb eines -Funktionsk\"orpers (zwischen den Schl\"usselworten \code{function} und -dem \code{end} definiert und k\"onnen auf alle Variablen der -``Mutterfunktion'' zugreifen und diese auch ver\"andern. Folglich -sollten sie nur mit Bedacht eingesetzt werden. - - -\section{Besonderheiten bei Skripten} - -Ein \"ahnliches Problem wurde schon bei der Einf\"uhrung der Skripte -erw\"ahnt. Variablen, die in Skripten definiert werden sind global im -\codeterm{Workspace} verf\"ugbar. Es besteht die Gefahr von -Namenskollisionen. Problem dabei ist, dass der Nutzer gar nicht -mitbekommt, wenn eine Variable redefiniert oder neuen Inhalt -zugewiesen bekommt. Fehler, die auf derartigen Kollisionen beruhen -sind h\"aufig nur schwer zu finden, da das Programm f\"ur sich korrekt -aussieht. - -Um dieses Problem zu vermeiden sollten Skripte genauso wie Funktionen -eine spezifische Aufgabe unabh\"angig vom Kontext erf\"ullen. Diese -Aufgabe ist dann nat\"urlich komplexer als die einer -Funktion. z.B. k\"onnte die Aufgabe eines Skriptes sein, die -Spiketrains aller aufgenommenen Zellen zu analysieren. Gute Skripte -sind trotzdem nicht \"uberm\"a{\ss}ig lang und deshalb leicht zu -verstehen. - -Ein weiterer, sehr wichtiger Vorteil von zweckbestimmten Skripten ist, -dass sie immer als ganzes ausf\"uhrbar sind --- am einfachsten mit -\keycode{F5} aus dem \matlab-Editor heraus. Wenn ein Fehler auftritt -ist in der Fehlermeldung die Zeilennummer des fehlerhaften Codes -angegeben. Das ist eine sehr wichtige Information, um den Fehler -beheben zu k\"onnen. - -\"Ubergeordnete Skripte k\"onnen dann einfach nacheinander -spezifischere Skripte aufrufen. Durch die Namen der aufgerufenen -Skripte ist dann klar, was passieren wird, und durch die -Unabh\"angigkeit der Skripte kommt es nicht zu Kollisionen. - -\begin{important}[Struktur von Skripten] +\subsection{Local and nested functions} +Generally, functions live in their own \codeterm{m-files} that have +the same name as the function itself. Delegating tasks to functions +thus leads to a large set of \codeterm{m-files} which increases +complexity and may lead to confusion. If the delegated functionality +is used in multiple instances, it is advisable to do so. On the other +hand, when the delegated functionality is only used within the context +of another function \matlab{} allows to define +\codeterm[function!local]{local functions} and +\codeterm[function!nested]{nested functions} within the same +file. Listing \ref{localfunctions} shows an example of a local +function definition. + +\pagebreak[3] \lstinputlisting[label=localfunctions, caption={Example + for local functions.}]{calculateSines.m} + +Local function live in the same \codeterm{m-file} as the main function +and are only available in this context. Each local function has its +own \codeterm{scope}, that is, the local function can not access (read +or write) variables of the calling function. + +This is different in so called \codeterm[function!nested]{nested + functions}. These are defined within the body of the parent function +(between the keywords \code{function} and \code{end}) and have full +access to all variables defined in the parent function. Working (in +particular changing) the parent's variables is handy on the one side, +but is also risky. One should take care when defining nested functions. + + +\section{Specifics when using scripts} +A similar problem as with nested function arises when using scripts +(instead of functions). All variables that are defined within a script +become available in the global \codeterm{Workspace}. There is the risk +of name conflicts, that is, a called sub-script redefines or uses the +same variable name and may \emph{silently} change its content. The +user will not be notified by this change and the calling script may +expect a completely different content. Bugs that are based on such +mistakes are hard to find since the program itself looks perfectly +fine. + +To avoid such issues one should design scripts in a way that they +perform their tasks independent from other scripts and functions. + +A common use case for a script could be to control the analyses made +on many datasets and to collect the results. A good script is still +not too long and is thus easy to comprehend. Another advantage of +small task-related scripts is that they can be directly executed by +either calling them from the command line or pressing \keycode{F5} in +the editor. Should it fail there will be a proper error message that +provides important information to track and fix the bug. + +\begin{important}[Structuring scripts] \begin{itemize} - \item Skripte sollten genauso wie Funktionen spezifische Aufgaben - l\"osen und nicht zu lang sein. + \item Similar to functions script should solve one task and should + not be too long. - \item Skripte sollten unabh\"angig von irgendwelchen Variablen im - \codeterm{Workspace} f\"ur sich alleine geschlossen lauff\"ahig - sein. - - \item Es empfiehlt sich zu Beginn eines Skriptes alle Variablen im - \codeterm{Workspace} zu l\"oschen (\code{clear}). Meist ist auch - ein \code{close all}, um alle Figures zu schlie{\ss}en, - angebracht. - - \item Am Ende eines Skriptes sollte der \codeterm{Workspace} - mithilfe von \code{clear} wieder von all den Variablen ges\"aubert - werden, die nicht mehr ben\"otigt werden. + \item Scripts should work independently of existing variables in the + global workspace. + + \item It is advisable to start a script with deleting variables + (\code{clear}) from the workspace and most of the times it is also + good to close all open figures (\code{close all}). + + \item Clean up the workspace at the end of a script. Delete + (\code{clear}) all variables that are no longer needed. \end{itemize} \end{important} -\section{Fazit} -Programmcode soll lesbar sein. Namen von Variablen, Funktionen und -Skripten sollten ausdrucksstark sein und R\"uckschl\"usse auf den -Inhalt oder den Zweck erlauben. Einen pers\"onlichen Programmierstil -zu entwickeln ist v\"ollig in Ordnung solange er konsistent ist. In -machen Programmiersprachen gibt es Traditionen und \"Ubereink\"unfte, -diese sollten dann beachtet werden. +\section{Summary} + +Program code must be readable. Names of variables, functions and +scripts should be expressive and describe their purpose (scripts and +functions) or their content (variables). Cultivating a personalized +code style is perfectly fine as long as it is consistent. Many +programming languages or communities have their own traditions. It is +advisable to adhere to these. -Wiederholte Programmabschnitte sollten in Funktionen ausgelagert -werden. Wenn diese nicht von globalem Interesse sind, kann mit -\codeterm[Funktion!lokale]{lokalen} oder -\codeterm[Funktion!geschachtelte]{geschachtelten - Funktionen} die \"Ubersichtlichkeit erh\"oht werden. +Repeated tasks should (to be read as must) be delegated to +functions. In cases in which a function is only locally applied and +not of more global interest across projects consider to define it as +\codeterm[function!local]{local function} or +\codeterm[function!nested]{nested function}. Taking care to increase +readability and comprehensibility pays off, even to the author! -Es lohnt sich auf den eigenen Programmierstil zu -achten!\footnote{Buchtip: Robert C. Martin: \textit{Clean Code: A - Handbook of Agile Software Craftmanship}, Prentice Hall} +\footnote{Reading tip: Robert C. Martin: \textit{Clean Code: A Handbook of + Agile Software Craftmanship}, Prentice Hall} \shortquote{Programs must be written for people to read, and only incidentally for machines to execute.}{Abelson / Sussman}