Merge branch 'master' of raven.am28.uni-tuebingen.de:scientificComputing

Conflicts:
	pointprocesses/code/binnedRate.m
	pointprocesses/code/convolutionRate.m
	pointprocesses/code/instantaneousRate.m
	programming/lecture/programming.tex
	programmingstyle/code/calculateSines.m
	programmingstyle/lecture/programmingstyle.tex
This commit is contained in:
2015-11-30 12:03:30 +01:00
66 changed files with 1736 additions and 1549 deletions

View File

@@ -1,32 +1,12 @@
BASENAME=programmingstyle
PYFILES=$(wildcard *.py)
PYPDFFILES=$(PYFILES:.py=.pdf)
all : pdf
include ../../chapter.mk
# script:
pdf : $(BASENAME)-chapter.pdf
$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) ../../header.tex
CHAPTER=$$(( $$(sed -n -e '/contentsline {chapter}/{s/.*numberline {\([0123456789]*\)}.*/\1/; p}' $(BASENAME).aux) - 1 )); \
PAGE=$$(sed -n -e '/contentsline {chapter}/{s/.*numberline {.*}.*}{\(.*\)}{chapter.*/\1/; p}' $(BASENAME).aux); \
sed -i -e "s/setcounter{page}{.*}/setcounter{page}{$$PAGE}/; s/setcounter{chapter}{.*}/setcounter{chapter}{$$CHAPTER}/" $(BASENAME)-chapter.tex
pdflatex -interaction=scrollmode $< | tee /dev/stderr | fgrep -q "Rerun to get cross-references right" && pdflatex -interaction=scrollmode $< || true
$(PYPDFFILES) : %.pdf : %.py
python $<
clean :
rm -f *~
rm -f $(BASENAME).aux $(BASENAME).log
rm -f $(BASENAME)-chapter.aux $(BASENAME)-chapter.log $(BASENAME)-chapter.out
rm -f $(PYPDFFILES) $(GPTTEXFILES)
cleanall : clean
rm -f $(BASENAME)-chapter.pdf
watchpdf :
while true; do ! make -q pdf && make pdf; sleep 0.5; done
pdf : chapter
clean : cleanchapter
cleanall : clean cleanchapter

View File

@@ -5,8 +5,10 @@
\lstset{inputpath=../code}
\graphicspath{{figures/}}
\setcounter{page}{57}
\setcounter{chapter}{2}
\typein[\pagenumber]{Number of first page}
\typein[\chapternumber]{Chapter number}
\setcounter{page}{\pagenumber}
\setcounter{chapter}{\chapternumber}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

View File

@@ -1,19 +1,25 @@
\chapter{\tr{Programming 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}
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 Monaten,
leicht f\"allt den Programmablauf nachzuvollziehen und zu
verstehen. Saubere Programmierung zahlt sich aber in erster Linie
f\"ur den Verfasser eines Programmes aus.
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:
\begin{enumerate}
\item Die Struktur von Programmen.
\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
@@ -82,46 +88,45 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information zum
(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
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 werden.
gefunden.
\vspace{2ex}
\includegraphics[width=0.75\textwidth]{search_path}
\includegraphics[width=0.9\textwidth]{search_path}
\vspace{1.5ex}
Der Suchpfad kann sowohl \"uber die in der Abbildung gezeigte GUI
oder auch \"uber die Kommandozeile 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.
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 aktuelle Arbeitsverzeichnis wechseln 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.
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. Das
hei{\ss}t, dass 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.
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 ein R\"uckschluss auf den Zweck ziehen lassen sollte.
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
@@ -136,10 +141,10 @@ 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 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
dem Muster ``format2format'' (z.B. \code{num2str()} f\"ur die
Konvertierung ``number to string'', Umwandlung eines numerischen
Wertes in einen Text) benannt.
\end{itemize}
@@ -158,24 +163,24 @@ 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 nicht zu lange Namen zu finden, sollte einer gute
Namensgebung ernst genommen werden.
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
\codeterm{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht
\varcode{average\_spike\_count} hei{\ss}en. Wenn die Variable nicht
nur einen sondern mehrere Werte aufnimmt, dann ist der Plural
angebracht (\codeterm{average\_spike\_counts}).
angebracht (\varcode{average\_spike\_counts}).
Die Laufvariablen von \code{for}-Schleifen werden oft nur \code{i},
\code{j} oder \code{k} benannt und sollten aber die einzige Ausnahme
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 (\code{spike\_count} statt \code{x}). Gute Namen
aussagen (\varcode{spike\_count} statt \varcode{x}). Gute Namen
f\"ur Variablen sind die beste Dokumentation.
\end{important}
@@ -223,7 +228,7 @@ end
end
\end{lstlisting}
\clearpage
\pagebreak[4]
\begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}]
num_runs = 10;
@@ -248,7 +253,7 @@ 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. \code{\% compute mean firing rate over all
Programm erl\"autern (z.B. \varcode{\% compute mean firing rate over all
trials}).
Viele und h\"aufige Kommentare k\"onnen in der Entwicklungsphase eines
@@ -259,7 +264,7 @@ 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\\
\code{ x = x + 2; \% add two to x}\\
\varcode{ x = x + 2; \% add two to x}\\
ein v\"ollig unn\"otiger Kommentar.
\begin{important}[Verwendung von Kommentaren]
@@ -270,21 +275,29 @@ ein v\"ollig unn\"otiger Kommentar.
\item Ein falscher Kommentar ist schlimmer als gar kein Kommentar!
\item Kommentare m\"ussen gepflegt werden, sonst sind sie wertlos!
\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
comment isn't needed?'' Improve the code and then document it to
make it even clearer.}{Steve McConnell}
\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. Auch in eingenen Funktionen sind diese
Kommentare sehr hilfreich. Siehe Listing~\ref{localfunctions} f\"ur
ein Beispiel einer gut Dokumentierten Funktion.
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{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).
@@ -302,7 +315,7 @@ ob dieser Teil des Programms nicht in eine eigene Funktion ausgelagert
werden sollte. Fast immer kann dies bejaht werden.
Abschnitte nicht auszulagern f\"uhrt zu sehr langen
\codeterm{m-Files}, die leicht un\"ubersichtlich werden. Diese Art von
\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.
@@ -318,25 +331,31 @@ Code wird \codeterm{Spaghetticode} genannt. Es ist h\"ochste Zeit
\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
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 sinnvoll dies zu tun. Wenn nicht, dann bietet \matlab{} die
M\"oglichkeit sogenannte \codeterm{lokale Funktionen} oder auch
\codeterm{geschachtelte Funktionen} (\enterm{nested functions}) zu
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.
\lstinputlisting[label=localfunctions, caption={\codeterm{Lokale Funktionen} erh\"ohen die Lesbarkeit sind aber nur innerhalb der definierenden Datei verf\"ugbar.}]{calculateSines.m}
\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{geschachtelten Funktionen}
ist das anders. Diese werden innerhalb eines Funktionsk\"orpers
(zwischen den Schl\"usselworten \codeterm{function} und dem
\codeterm{end} definiert und k\"onnen auf alle Variablen der
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.
@@ -403,8 +422,20 @@ diese sollten dann beachtet werden.
Wiederholte Programmabschnitte sollten in Funktionen ausgelagert
werden. Wenn diese nicht von globalem Interesse sind, kann mit
\codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die
\"Ubersichtlichkeit erh\"oht werden.
\codeterm[Funktion!lokale]{lokalen} oder
\codeterm[Funktion!geschachtelte]{geschachtelten
Funktionen} die \"Ubersichtlichkeit erh\"oht werden.
\noindent Es lohnt sich auf den eigenen Programmierstil zu achten!\footnote{Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean
Code: A Handbook of Agile Software Craftmanship}, Prentice Hall}
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}
\shortquote{Programs must be written for people to read, and only
incidentally for machines to execute.}{Abelson / Sussman}
\shortquote{Any fool can write code that a computer can
understand. Good programmers write code that humans can
understand.}{Martin Fowler}
\shortquote{First, solve the problem. Then, write the code.}{John
Johnson}