[chapter 4] translate code style chapter
This commit is contained in:
		
							parent
							
								
									104717cfe7
								
							
						
					
					
						commit
						4270b65442
					
				| @ -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} | ||||
| \section{Organization of programs on the file system} | ||||
| 
 | ||||
| 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? | ||||
| 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}. | ||||
| 
 | ||||
| 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. | ||||
| 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. | ||||
| 
 | ||||
| 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}). | ||||
| 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. | ||||
|   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. | ||||
| 
 | ||||
|   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 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} | ||||
| \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. | ||||
| 
 | ||||
| \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. | ||||
| \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. | ||||
| 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{Namensgebung von Variablen und Konstanten} | ||||
| \section{Naming variables and constants} | ||||
| 
 | ||||
| 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. | ||||
| \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. | ||||
| 
 | ||||
| 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}). | ||||
| 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}). | ||||
| 
 | ||||
| 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. | ||||
| 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}[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. | ||||
| \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} | ||||
| \section{Using comments} | ||||
| 
 | ||||
| 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}). | ||||
| 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. | ||||
| 
 | ||||
| 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\\ | ||||
| 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} | ||||
| \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. | ||||
| 
 | ||||
| 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! | ||||
| \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} | ||||
| \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. | ||||
| 
 | ||||
| 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={Example | ||||
|     for local functions.}]{calculateSines.m} | ||||
| 
 | ||||
| \pagebreak[3] | ||||
| \lstinputlisting[label=localfunctions, caption={Beispiel f\"ur den | ||||
|   Einsatz von lokalen Funktionen.}]{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. | ||||
| 
 | ||||
| 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. | ||||
| 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{Besonderheiten bei Skripten} | ||||
| \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. | ||||
| 
 | ||||
| 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. | ||||
| To avoid such issues one should design scripts in a way that they | ||||
| perform their tasks independent from other scripts and functions. | ||||
| 
 | ||||
| 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. | ||||
| 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. | ||||
| 
 | ||||
| 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] | ||||
| \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 Scripts should work independently of existing variables in the | ||||
|     global workspace. | ||||
| 
 | ||||
|   \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 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} | ||||
| 
 | ||||
| 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. | ||||
| 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. | ||||
| 
 | ||||
| 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} | ||||
| 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! | ||||
| 
 | ||||
| \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} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user