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:
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user