Merge branch 'programmingstyle' of raven.am28.uni-tuebingen.de:scientificComputing
This commit is contained in:
commit
504dda5cb9
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
BASENAME=scientificcomputing-script
|
BASENAME=scientificcomputing-script
|
||||||
|
|
||||||
SUBDIRS=programming plotting statistics bootstrap regression likelihood pointprocesses designpattern
|
SUBDIRS=programming plotting programmingstyle statistics bootstrap regression likelihood pointprocesses designpattern
|
||||||
SUBTEXS=$(foreach subd, $(SUBDIRS), $(subd)/lecture/$(subd).tex)
|
SUBTEXS=$(foreach subd, $(SUBDIRS), $(subd)/lecture/$(subd).tex)
|
||||||
|
|
||||||
pdf : chapters $(BASENAME).pdf
|
pdf : chapters $(BASENAME).pdf
|
||||||
|
@ -171,6 +171,7 @@
|
|||||||
\newcommand{\enterm}[1]{``#1''}
|
\newcommand{\enterm}[1]{``#1''}
|
||||||
\newcommand{\determ}[1]{\textit{#1}}
|
\newcommand{\determ}[1]{\textit{#1}}
|
||||||
\newcommand{\codeterm}[1]{\textit{#1}}
|
\newcommand{\codeterm}[1]{\textit{#1}}
|
||||||
|
\newcommand{\keycode}[1]{\texttt{#1}}
|
||||||
\newcommand{\file}[1]{\texttt{#1}}
|
\newcommand{\file}[1]{\texttt{#1}}
|
||||||
|
|
||||||
%%%%% code/matlab commands: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%% code/matlab commands: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
30
programmingstyle/code/calculate_sines.m
Normal file
30
programmingstyle/code/calculate_sines.m
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
function sines = calculate_sines(x, amplitudes, frequencies)
|
||||||
|
% Function calculates sinewaves with all combinations of
|
||||||
|
% given amplitudes and frequencies.
|
||||||
|
% Arguments: x, a vector of radiants for which the sine should be
|
||||||
|
% computed.
|
||||||
|
% amplitudes, a vector of amplitudes.
|
||||||
|
% frequencies, a vector of frequencies.
|
||||||
|
%
|
||||||
|
% Returns: a 3-D Matrix of sinewaves, 2nd dimension represents
|
||||||
|
% the amplitudes, 3rd the frequencies.
|
||||||
|
|
||||||
|
sines = zeros(length(x), length(amplitudes), length(frequencies));
|
||||||
|
|
||||||
|
for i = 1:length(amplitudes)
|
||||||
|
sines(:,i,:) = sines_with_frequencies(x, amplitudes(i), frequencies);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function sines = sines_with_frequencies(x, amplitude, frequencies)
|
||||||
|
sines = zeros(length(x), length(frequencies));
|
||||||
|
for i = 1:length(frequencies)
|
||||||
|
sines(:,i) = sinewave(x, amplitude, frequencies(i));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function sine = sinewave(x, amplitude, frequency)
|
||||||
|
sine = sin(2 .* pi .* x *frequency) .* amplitude;
|
||||||
|
end
|
31
programmingstyle/lecture/Makefile
Normal file
31
programmingstyle/lecture/Makefile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
BASENAME=programmingstyle
|
||||||
|
|
||||||
|
#TEXFILES=programmingstyle.tex
|
||||||
|
|
||||||
|
PYFILES=$(wildcard *.py)
|
||||||
|
PYPDFFILES=$(PYFILES:.py=.pdf)
|
||||||
|
|
||||||
|
all : pdf
|
||||||
|
|
||||||
|
# script:
|
||||||
|
pdf : $(BASENAME)-chapter.pdf
|
||||||
|
|
||||||
|
$(BASENAME)-chapter.pdf : $(BASENAME)-chapter.tex $(BASENAME).tex $(PYPDFFILES) ../../header.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
|
||||||
|
|
||||||
|
|
61
programmingstyle/lecture/beamercolorthemetuebingen.sty
Normal file
61
programmingstyle/lecture/beamercolorthemetuebingen.sty
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
% Copyright 2007 by Till Tantau
|
||||||
|
%
|
||||||
|
% This file may be distributed and/or modified
|
||||||
|
%
|
||||||
|
% 1. under the LaTeX Project Public License and/or
|
||||||
|
% 2. under the GNU Public License.
|
||||||
|
%
|
||||||
|
% See the file doc/licenses/LICENSE for more details.
|
||||||
|
|
||||||
|
\usepackage{color}
|
||||||
|
\definecolor{karminrot}{RGB}{165,30,55}
|
||||||
|
\definecolor{gold}{RGB}{180,160,105}
|
||||||
|
\definecolor{anthrazit}{RGB}{50 ,65 ,75 }
|
||||||
|
|
||||||
|
\mode<presentation>
|
||||||
|
|
||||||
|
\setbeamercolor*{normal text}{fg=anthrazit,bg=white}
|
||||||
|
\setbeamercolor*{alerted text}{fg=anthrazit}
|
||||||
|
\setbeamercolor*{example text}{fg=anthrazit}
|
||||||
|
\setbeamercolor*{structure}{fg=gold,bg=karminrot}
|
||||||
|
|
||||||
|
\providecommand*{\beamer@bftext@only}{%
|
||||||
|
\relax
|
||||||
|
\ifmmode
|
||||||
|
\expandafter\beamer@bftext@warning
|
||||||
|
\else
|
||||||
|
\expandafter\bfseries
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
\providecommand*{\beamer@bftext@warning}{%
|
||||||
|
\ClassWarning{beamer}
|
||||||
|
{Cannot use bold for alerted text in math mode}%
|
||||||
|
}
|
||||||
|
|
||||||
|
\setbeamerfont{alerted text}{series=\beamer@bftext@only}
|
||||||
|
|
||||||
|
\setbeamercolor{palette primary}{fg=karminrot,bg=white}
|
||||||
|
\setbeamercolor{palette secondary}{fg=gold,bg=white}
|
||||||
|
\setbeamercolor{palette tertiary}{fg=anthrazit,bg=white}
|
||||||
|
\setbeamercolor{palette quaternary}{fg=black,bg=white}
|
||||||
|
|
||||||
|
\setbeamercolor{sidebar}{bg=karminrot!100}
|
||||||
|
|
||||||
|
\setbeamercolor{palette sidebar primary}{fg=karminrot}
|
||||||
|
\setbeamercolor{palette sidebar secondary}{fg=karminrot}
|
||||||
|
\setbeamercolor{palette sidebar tertiary}{fg=karminrot}
|
||||||
|
\setbeamercolor{palette sidebar quaternary}{fg=karminrot}
|
||||||
|
|
||||||
|
\setbeamercolor{item projected}{fg=black,bg=black!20}
|
||||||
|
|
||||||
|
\setbeamercolor*{block body}{}
|
||||||
|
\setbeamercolor*{block body alerted}{}
|
||||||
|
\setbeamercolor*{block body example}{}
|
||||||
|
\setbeamercolor*{block title}{parent=structure}
|
||||||
|
\setbeamercolor*{block title alerted}{parent=alerted text}
|
||||||
|
\setbeamercolor*{block title example}{parent=example text}
|
||||||
|
|
||||||
|
\setbeamercolor*{titlelike}{parent=structure}
|
||||||
|
|
||||||
|
\mode
|
||||||
|
<all>
|
BIN
programmingstyle/lecture/figures/program_organization.png
Normal file
BIN
programmingstyle/lecture/figures/program_organization.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
programmingstyle/lecture/figures/search_path.png
Normal file
BIN
programmingstyle/lecture/figures/search_path.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
17
programmingstyle/lecture/programmingstyle-chapter.tex
Normal file
17
programmingstyle/lecture/programmingstyle-chapter.tex
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
\documentclass[12pt]{report}
|
||||||
|
|
||||||
|
\input{../../header}
|
||||||
|
|
||||||
|
\lstset{inputpath=../code}
|
||||||
|
|
||||||
|
\graphicspath{{figures/}}
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\include{programmingstyle}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
|
|
378
programmingstyle/lecture/programmingstyle.tex
Normal file
378
programmingstyle/lecture/programmingstyle.tex
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
\chapter{\tr{Programming style}{Programmierstil}}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Guter Programmierstil greift auf unterschiedlichen Ebenen an:
|
||||||
|
\begin{enumerate}
|
||||||
|
\item Die Struktur 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.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\section{Organisation von m-Files im Dateisystem}
|
||||||
|
|
||||||
|
In der Einf\"uhrung zu Funktionen und Skripten wurde schon einmal ein
|
||||||
|
typisches Programmlayout vorgestellt (\figref{programlayoutfig}). 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}).
|
||||||
|
|
||||||
|
\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.}
|
||||||
|
\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 werden.
|
||||||
|
|
||||||
|
\includegraphics[width=0.75\textwidth]{search_path}
|
||||||
|
|
||||||
|
Man kann den Suchpfad sowohl \"uber die in der Abbildung gezeigte
|
||||||
|
GUI oder auch \"uber die Kommandozeile editieren. In der GUI hat man
|
||||||
|
die M\"oglichkeit Ordner aus dem Suchpfad zu entfernen, neue Ordner
|
||||||
|
(optional inklusive aller Unterordner) hinzuzuf\"ugen oder die
|
||||||
|
Reihenfolge zu ver\"andern.
|
||||||
|
|
||||||
|
Will man das aktuelle Arbeitsverzeichis wechseln benutzt man das
|
||||||
|
Kommando \code{cd}, um herauszufinden, in welchem Pfad eine
|
||||||
|
bestimmte Funktion gefunden wurde, benutzt man das Kommando
|
||||||
|
\code{which}. Der 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
\begin{important}
|
||||||
|
Die Namen von Funktionen und Skripte sollten m\"oglichst viel \"uber
|
||||||
|
die Funktionsweise oder den Zweck aussagen (\file{firingrates.m}
|
||||||
|
statt \file{uebung.m}). Gute Namen f\"ur Funktionen und Skripte sind
|
||||||
|
die beste Dokumentation.
|
||||||
|
\end{important}
|
||||||
|
|
||||||
|
In Namen verbietet \matlab{} verbietet Leerzeichen, Sonderzeichen und
|
||||||
|
Umlaute. Namen d\"urfen auch nicht mit Zahlen anfangen. Es mach f\"ur
|
||||||
|
die Namensgebung selbst keine weiteren Vorgaben. Allerdings folgt die
|
||||||
|
Benennung der in \matlab{} vordefinierten Funktionen gewissen Mustern:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Namen werden immer klein geschrieben.
|
||||||
|
\item Es werden gerne Abk\"urzungen eingesetzt (z.B. \code{xcorr}
|
||||||
|
f\"ur die Kreuzkorrelation oder \code{repmat} f\"ur ``repeat matrix'')
|
||||||
|
\item Funktionen, die zwischen Formaten konvertieren sind immer nach
|
||||||
|
dem Muster ``format2format'' (z.B. \code{num2str} f\"ur die
|
||||||
|
Konvertierung ``number to string'', Umwandlung eines numerischen
|
||||||
|
Wertes in einen Text) benannt.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
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 nicht zu lange Namen zu finden, sollte einer gute
|
||||||
|
Namensgebung 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
|
||||||
|
nur einen sondern mehrere Werte aufnimmt, dann ist der Plural
|
||||||
|
angebracht (\codeterm{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
|
||||||
|
bzgl. ausdrucksstarker Namensgebung bleiben.
|
||||||
|
|
||||||
|
\begin{important}
|
||||||
|
Die Namen von Variablen sollten m\"oglichst viel \"uber ihren Inhalt
|
||||||
|
aussagen (\code{spike\_count} statt \code{x}). Gute Namen
|
||||||
|
f\"ur Variablen sind die beste Dokumentation.
|
||||||
|
\end{important}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Codestil}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
positions = zeros(max_steps, num_runs);
|
||||||
|
|
||||||
|
for run = 1:num_runs
|
||||||
|
|
||||||
|
|
||||||
|
for step = 2:max_steps
|
||||||
|
|
||||||
|
x = randn(1);
|
||||||
|
if x<0
|
||||||
|
positions(step, run)= positions(step-1, run)+1;
|
||||||
|
|
||||||
|
|
||||||
|
elseif x>0
|
||||||
|
positions(step,run)=positions(step-1,run)-1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\begin{lstlisting}[label=cleancode, caption={\"Ubersichtliche Implementation des Random-walk.}]
|
||||||
|
num_runs = 10;
|
||||||
|
max_steps = 1000;
|
||||||
|
positions = zeros(max_steps, num_runs);
|
||||||
|
|
||||||
|
for run = 1:num_runs
|
||||||
|
for step = 2:max_steps
|
||||||
|
x = randn(1);
|
||||||
|
if x < 0
|
||||||
|
positions(step, run) = positions(step-1, run) + 1;
|
||||||
|
elseif x > 0
|
||||||
|
positions(step, run) = positions(step-1, run) - 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
\end{lstlisting}
|
||||||
|
|
||||||
|
\section{Verwendung von Kommentaren}
|
||||||
|
|
||||||
|
Kommentarzeilen werden in \matlab{} mit dem Prozentzeichen \cide{\%}
|
||||||
|
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
|
||||||
|
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\\
|
||||||
|
\code{ x = x + 2; \% add two to x}\\
|
||||||
|
ein v\"ollig unn\"otiger Kommentar.
|
||||||
|
|
||||||
|
\begin{important}
|
||||||
|
\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!
|
||||||
|
\end{itemize}
|
||||||
|
\end{important}
|
||||||
|
|
||||||
|
\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.
|
||||||
|
|
||||||
|
\begin{important}
|
||||||
|
Funktionen m\"ussen unbedingt kommentiert werde!
|
||||||
|
\begin{itemize}
|
||||||
|
\item In wenigen Zeilen kurz den Zweck der Funktion beschreiben.
|
||||||
|
\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.
|
||||||
|
\end{itemize}
|
||||||
|
\end{important}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Auslagerung von Aufgaben in Funktionen}
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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}
|
||||||
|
Wann sollten Programmteile in eigene Funktionen ausgelagert werden?
|
||||||
|
\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.
|
||||||
|
\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 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
|
||||||
|
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.}]{calculate_sines.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
|
||||||
|
``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.
|
||||||
|
|
||||||
|
\begin{important}
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
\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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
\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}
|
@ -27,6 +27,11 @@
|
|||||||
\lstset{inputpath=plotting/code/}
|
\lstset{inputpath=plotting/code/}
|
||||||
\include{plotting/lecture/plotting}
|
\include{plotting/lecture/plotting}
|
||||||
|
|
||||||
|
|
||||||
|
\graphicspath{{programmingstyle/lecture/}{programmingstyle/lecture/figures/}}
|
||||||
|
\lstset{inputpath=programmingstyle/code/}
|
||||||
|
\include{programmingstyle/lecture/programmingstyle}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\part{Grundlagen der Datenanalyse}
|
\part{Grundlagen der Datenanalyse}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user