finished (?) chapter, add example code

This commit is contained in:
Jan Grewe 2015-11-14 13:08:21 +01:00
parent 9af291738f
commit 108210210a
2 changed files with 155 additions and 26 deletions

View 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

View File

@ -15,9 +15,11 @@ Guter Programmierstil greift auf unterschiedlichen Ebenen an:
\begin{enumerate}
\item Die Struktur von Programmen.
\item Die Namensgebung von Skripten und Funktionen.
\item Die Namensgebung fuer Variablen und Konstanten.
\item Die Verwendung von Einr\"uckungen und Leerzeilen um Bl\"ocke im Code hervorzuheben.
\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{Struktur von Programmen, Organisation von m-Files im Dateisystem}
@ -107,7 +109,7 @@ aktuellen Ordner nach passenden Dateien sucht (mehr Information in Box
\matlab{} sucht Funktionen und Skripte ausschlie{\ss}lich anhand der
Namen. Dabei spielt die Gro{\ss}- und Kleinschreibung eine Rolle. Das
hei{\ss}t, dass die Namen ``test_funktion.m'' und ``Test_funktion.m''
hei{\ss}t, dass die Namen ``test\_funktion.m'' und ``Test\_funktion.m''
zwei unterschiedliche Funktionen benennen k\"onnen. Diese Art
Variation des Namens ist nat\"urlich nicht sinnvoll. Sie tr\"agt keine
Information \"uber den Unterschied der beiden Funktionen. Auch sagt
@ -163,14 +165,55 @@ zuf\"allig) einger\"uckt sind ist deutlich schwerer zu lesen und zu
verstehen, als eines, in dem eine konsistente Einr\"uckung vorgenommen
wurde.
Gerne werden Leerzeielen eingef\"ugt um Abschnitte im Programm zu
Gerne werden Leerzeilen eingef\"ugt um Abschnitte im Programm zu
trennen. Das ist v\"ollig ok, wenn es konsistent und sparsam benutzt
wird. Hier sollte eine Leerzeile ausreichen. Zu gro{\ss}e Abst\"ande
f\"uhren dazu das das Programm nicht mehr auf eine Seite passt und man
f\"uhren dazu, dass das Programm nicht mehr auf eine Seite passt und man
leicht den \"Uberblick verliert.
\TODO chaotisches und aufger\"aumtes Listing
Die beiden folgenden Listings \ref{chaoticcode} und \ref{cleancode}
zeigen die Implementation des random-walk einmal eher chaotisch und
einmal aufger\"aumt.
\begin{lstlisting}[label=chaoticcode, caption={Random-walk Implementation unaufgr\"aumt.}]
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}
\begin{lstlisting}[label=cleancode, caption={Random-walk Implementation etwas ordentlicher.}]
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}
@ -190,8 +233,8 @@ Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend.
\begin{itemize}
\item Kommentare sind gut und wichtig aber: Sie m\"ussen richtig
sein!
\item Ein Kommentar der l\"ugt, ist schlimmer als gar kein Kommentar!
\item Kommentare m\"ussen gepflegt werden sonst sind sie mehr als
\item Ein Kommentar, der l\"ugt, ist schlimmer als gar kein Kommentar!
\item Kommentare m\"ussen gepflegt werden, sonst sind sie mehr als
wertlos!
\end{itemize}
\end{important}
@ -199,30 +242,86 @@ Variablennamen sind viel Zeilen weitestgehend selbsterkl\"arend.
\section{Auslagerung von Aufgaben in Funktionen}
Spaghetticode
inline functions
Kommentare oder Leerzeilen werden benutzt um Abschnitte des Codes
abzutrennen und nazudeuten, dass ab da etwas inhaltlich anderes
gemacht wird. Wenn man im Zuge ist, eine solche inhaltliche Trennung
einzuf\"ugen muss man sich immer fragen, ob dieser Teil des Programms
nicht in eine eigene Funktion ausgelagert werden sollte. Fast immer
kann man das bejahen.
Abschnitte nicht auszulagern f\"uhrt zu sehr langen m-Files, die
leicht un\"ubersichtlich sind. Man nennt sie
\codeterm{Spaghetticode}. Es ist h\"ochste Zeit \"uber Auslagerung in
Funktionen nachzudenken.
\section{Besonderheiten bei Skripten}
\begin{important}
Wann sollte man Programmteile in eigene Funktionen auslagern?
\begin{itemize}
\item Wenn man innerhalb einer Funktion, eines Skripts mehr als zwei
Einr\"uckungsebenen hat.
\item Wenn man wiederholte Strukturen im Code hat.
\item Wenn man versucht ist, diese mit Copy and Paste zu erzeugen.
\end{itemize}
\end{important}
Achtung, globaler G\"ultigkeitsbereich!
\subsection{Lokale Funktionen und geschachtelte Funktionen}
Eine M\"oglichkeit Spaghetticode zu vermeiden ist das Auslagern von
Funktionalit\"at in eigene Funktionen. Dies f\"uhrt dazu, dass man
eine F\"ulle von Dateien erzeugt, die die \"Ubersichtlichkeit nicht
unbedingt erh\"ohen. Wenn die auszulagernde Funktionalit\"at an vielen
Stellen ben\"otigt werden k\"onnte ist es dennoch sinnvol 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.
Kollision von Variablennamen.
\section{Besonderheiten bei Skripten}
Best practice.
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}
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.
Es lohnt sich!
Es empfiehlt sich zu Beginn eines Skriptes alle Variablen im
\codeterm{Workspace} zu l\"oschen (\code{clear}). Meist ist auch
ein \code{close all} 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 nich von globalem Interesse sind, kann man auch mit
\codeterm{lokalen} oder \codeterm{geschachtelten Funktionen} die
Lesbarkeit erh\"ohen.
Literatur zum Programmierstil: z.B. Robert C. Martin: \textit{Clean
Code: A Handbook of Agile Software Craftmanship}, Prentice Hall
\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}